1 
2 ///////////////////////////////////////////////////////////
3 //                                                       //
4 //                         SAGA                          //
5 //                                                       //
6 //      System for Automated Geoscientific Analyses      //
7 //                                                       //
8 //           Application Programming Interface           //
9 //                                                       //
10 //                  Library: SAGA_API                    //
11 //                                                       //
12 //-------------------------------------------------------//
13 //                                                       //
14 //                   api_colors.cpp                      //
15 //                                                       //
16 //          Copyright (C) 2005 by Olaf Conrad            //
17 //                                                       //
18 //-------------------------------------------------------//
19 //                                                       //
20 // This file is part of 'SAGA - System for Automated     //
21 // Geoscientific Analyses'.                              //
22 //                                                       //
23 // This library is free software; you can redistribute   //
24 // it and/or modify it under the terms of the GNU Lesser //
25 // General Public License as published by the Free       //
26 // Software Foundation, either version 2.1 of the        //
27 // License, or (at your option) any later version.       //
28 //                                                       //
29 // This library is distributed in the hope that it will  //
30 // be useful, but WITHOUT ANY WARRANTY; without even the //
31 // implied warranty of MERCHANTABILITY or FITNESS FOR A  //
32 // PARTICULAR PURPOSE. See the GNU Lesser General Public //
33 // License for more details.                             //
34 //                                                       //
35 // You should have received a copy of the GNU Lesser     //
36 // General Public License along with this program; if    //
37 // not, see <http://www.gnu.org/licenses/>.              //
38 //                                                       //
39 //-------------------------------------------------------//
40 //                                                       //
41 //    contact:    Olaf Conrad                            //
42 //                Institute of Geography                 //
43 //                University of Goettingen               //
44 //                Goldschmidtstr. 5                      //
45 //                37077 Goettingen                       //
46 //                Germany                                //
47 //                                                       //
48 //    e-mail:     oconrad@saga-gis.org                   //
49 //                                                       //
50 ///////////////////////////////////////////////////////////
51 
52 //---------------------------------------------------------
53 #include <stdlib.h>
54 #include <string.h>
55 
56 #include "api_core.h"
57 #include "mat_tools.h"
58 
59 
60 ///////////////////////////////////////////////////////////
61 //														 //
62 //														 //
63 //														 //
64 ///////////////////////////////////////////////////////////
65 
66 //---------------------------------------------------------
SG_Colors_Get_Name(int Index)67 CSG_String	SG_Colors_Get_Name	(int Index)
68 {
69 	return( CSG_Colors::Get_Predefined_Name(Index) );
70 }
71 
72 //---------------------------------------------------------
SG_Color_Get_Random(void)73 long		SG_Color_Get_Random	(void)
74 {
75 	return(	SG_GET_RGB(CSG_Random::Get_Uniform(0, 255), CSG_Random::Get_Uniform(0, 255), CSG_Random::Get_Uniform(0, 255)) );
76 }
77 
78 //---------------------------------------------------------
SG_Color_From_Text(const CSG_String & Text,long & Color)79 bool		SG_Color_From_Text	(const CSG_String &Text, long &Color)
80 {	// from wx/colourmng.cpp, hexadecimal prefixed with # ("HTML syntax") see https://drafts.csswg.org/css-color/#hex-notation
81 
82 	const char	*s	= Text.b_str();	unsigned long	c;
83 
84 	if( sscanf(s + 1, "%lx", &c) == 1 )
85 	{
86 		switch( Text.Length() - 1 )
87 		{
88 		case 6: // #rrggbb
89 			Color	= (long)((c << 8) + 0xFF);
90 			return( true );
91 
92 		case 8: // #rrggbbaa
93 			Color	= SG_GET_RGBA(
94 				(unsigned char)((c >> 24) & 0xFF),
95 				(unsigned char)((c >> 16) & 0xFF),
96 				(unsigned char)((c >>  8) & 0xFF),
97 				(unsigned char)((c      ) & 0xFF)
98 			);
99 			return( true );
100 
101 		case 3: // #rgb
102 			Color	= (long)((c << 4) + 0xF);
103 			return( true );
104 
105 		case 4: // #rgba
106 			Color	= SG_GET_RGBA(
107 				(unsigned char)(((c >> 12) & 0xF) * 0x11),
108 				(unsigned char)(((c >>  8) & 0xF) * 0x11),
109 				(unsigned char)(((c >>  4) & 0xF) * 0x11),
110 				(unsigned char)(((c      ) & 0xF) * 0x11)
111 			);
112 			return( true );
113 		}
114 	}
115 
116 	return( false );
117 }
118 
119 //---------------------------------------------------------
SG_Color_To_Text(long Color,bool bHexadecimal)120 CSG_String	SG_Color_To_Text	(long Color, bool bHexadecimal)
121 {
122 	CSG_String	Text;
123 
124 	if( bHexadecimal )
125 	{
126 		Text.Printf("#%02X%02X%02X",
127 			SG_GET_R(Color),
128 			SG_GET_G(Color),
129 			SG_GET_B(Color)
130 		);
131 	}
132 	else
133 	{
134 		Text.Printf("%ld", Color);
135 	}
136 
137 	return( Text );
138 }
139 
140 
141 ///////////////////////////////////////////////////////////
142 //														 //
143 //														 //
144 //														 //
145 ///////////////////////////////////////////////////////////
146 
147 //---------------------------------------------------------
CSG_Colors(void)148 CSG_Colors::CSG_Colors(void)
149 {
150 	m_Colors	= NULL;
151 	m_nColors	= 0;
152 
153 	Create();
154 }
155 
156 //---------------------------------------------------------
CSG_Colors(const CSG_Colors & Colors)157 CSG_Colors::CSG_Colors(const CSG_Colors &Colors)
158 {
159 	m_Colors	= NULL;
160 	m_nColors	= 0;
161 
162 	Create(Colors);
163 }
164 
165 //---------------------------------------------------------
CSG_Colors(int nColors,int Palette,bool bRevert)166 CSG_Colors::CSG_Colors(int nColors, int Palette, bool bRevert)
167 {
168 	m_Colors	= NULL;
169 	m_nColors	= 0;
170 
171 	Create(nColors, Palette, bRevert);
172 }
173 
174 //---------------------------------------------------------
~CSG_Colors(void)175 CSG_Colors::~CSG_Colors(void)
176 {
177 	Destroy();
178 }
179 
180 
181 ///////////////////////////////////////////////////////////
182 //														 //
183 ///////////////////////////////////////////////////////////
184 
185 //---------------------------------------------------------
Create(void)186 bool CSG_Colors::Create(void)
187 {
188 	return( Create(11) );
189 }
190 
191 //---------------------------------------------------------
Create(const CSG_Colors & Colors)192 bool CSG_Colors::Create(const CSG_Colors &Colors)
193 {
194 	if( Colors.m_nColors > 0 )
195 	{
196 		m_nColors	= Colors.m_nColors;
197 		m_Colors	= (long *)SG_Realloc(m_Colors, m_nColors * sizeof(long));
198 
199 		memcpy(m_Colors, Colors.m_Colors, m_nColors * sizeof(long));
200 
201 		return( true );
202 	}
203 
204 	return( false );
205 }
206 
207 //---------------------------------------------------------
Create(int nColors,int Palette,bool bRevert)208 bool CSG_Colors::Create(int nColors, int Palette, bool bRevert)
209 {
210 	if( nColors <= 1 )
211 	{
212 		nColors	= 11;
213 	}
214 
215 	Set_Count(nColors);
216 
217 	Set_Palette(Palette, bRevert, nColors);
218 
219 	return( true );
220 }
221 
222 //---------------------------------------------------------
Destroy(void)223 void CSG_Colors::Destroy(void)
224 {
225 	if( m_nColors > 0 )
226 	{
227 		SG_Free(m_Colors);
228 
229 		m_Colors	= NULL;
230 		m_nColors	= 0;
231 	}
232 }
233 
234 
235 ///////////////////////////////////////////////////////////
236 //														 //
237 ///////////////////////////////////////////////////////////
238 
239 //---------------------------------------------------------
Set_Count(int nColors)240 bool CSG_Colors::Set_Count(int nColors)
241 {
242 	if( nColors == m_nColors )
243 	{
244 		return( true );
245 	}
246 
247 	if( nColors < 1 )
248 	{
249 		return( false );
250 	}
251 
252 	if( m_nColors == 0 )
253 	{
254 		return( Set_Default(nColors) );
255 	}
256 
257 	//-----------------------------------------------------
258 	CSG_Colors	Colors(*this);
259 
260 	m_nColors	= nColors;
261 	m_Colors	= (long *)SG_Realloc(m_Colors, m_nColors * sizeof(long));
262 
263 	double	dStep	= Get_Count() > 1 ? (Colors.Get_Count() - 1.0) / (Get_Count() - 1.0) : 0.0;
264 
265 	for(int i=0; i<Get_Count(); i++)
266 	{
267 		if( Get_Count() < Colors.Get_Count() )
268 		{
269 			m_Colors[i]	= Colors[(int)(i * dStep)];
270 		}
271 		else // if( Get_Count() > Colors.Get_Count() )
272 		{
273 			m_Colors[i]	= Colors.Get_Interpolated(i * dStep);
274 		}
275 	}
276 
277 	//---------------------------------------------
278 	return( true );
279 }
280 
281 
282 ///////////////////////////////////////////////////////////
283 //														 //
284 ///////////////////////////////////////////////////////////
285 
286 //---------------------------------------------------------
Set_Color(int Index,long Color)287 bool CSG_Colors::Set_Color(int Index, long Color)
288 {
289 	if( Index >= 0 && Index < m_nColors )
290 	{
291 		m_Colors[Index]	= Color;
292 
293 		return( true );
294 	}
295 
296 	return( false );
297 }
298 
299 //---------------------------------------------------------
Set_Color(int Index,int Red,int Green,int Blue)300 bool CSG_Colors::Set_Color(int Index, int Red, int Green, int Blue)
301 {
302 	return( Set_Color(Index, SG_GET_RGB(Red, Green, Blue)) );
303 }
304 
305 //---------------------------------------------------------
Set_Red(int Index,int Value)306 bool CSG_Colors::Set_Red(int Index, int Value)
307 {
308 	return( Set_Color(Index, Value			, Get_Green(Index)	, Get_Blue(Index)) );
309 }
310 
311 //---------------------------------------------------------
Set_Green(int Index,int Value)312 bool CSG_Colors::Set_Green(int Index, int Value)
313 {
314 	return( Set_Color(Index, Get_Red(Index)	, Value				, Get_Blue(Index)) );
315 }
316 
317 //---------------------------------------------------------
Set_Blue(int Index,int Value)318 bool CSG_Colors::Set_Blue(int Index, int Value)
319 {
320 	return( Set_Color(Index, Get_Red(Index)	, Get_Green(Index)	, Value) );
321 }
322 
323 //---------------------------------------------------------
Set_Brightness(int Index,int Value)324 bool CSG_Colors::Set_Brightness(int Index, int Value)
325 {
326 	double	r, g, b, ds;
327 
328 	//-----------------------------------------------------
329 	if( Value < 0 )
330 	{
331 		Value	= 0;
332 	}
333 	else if( Value > 255 )
334 	{
335 		Value	= 255;
336 	}
337 
338 	//-----------------------------------------------------
339 	r	= Get_Red  (Index);
340 	g	= Get_Green(Index);
341 	b	= Get_Blue (Index);
342 	ds	= (r + g + b) / 3.0;
343 
344 	if( ds > 0.0 )
345 	{
346 		ds	= Value / ds;
347 		r	*= ds;
348 		g	*= ds;
349 		b	*= ds;
350 
351 		_Set_Brightness(r, g, b);
352 	}
353 	else
354 	{
355 		r	= g	= b	= Value / 3.0;
356 	}
357 
358 	return( Set_Color(Index, (int)r, (int)g, (int)b) );
359 }
360 
361 //---------------------------------------------------------
_Set_Brightness(double & a,double & b,double & c,int Pass)362 void CSG_Colors::_Set_Brightness(double &a, double &b, double &c, int Pass)
363 {
364 	if( a > 255 )
365 	{
366 		int		addSum;
367 
368 		addSum	= (int)((a - 255) / 2.0);
369 		a		= 255;
370 
371 		b		+= addSum;
372 		c		+= addSum;
373 
374 		if( b > 255 )
375 		{
376 			addSum	= (int)(b - 255);
377 			b		= 255;
378 
379 			c		+= addSum;
380 
381 			if( c > 255 )
382 			{
383 				c	= 255;
384 			}
385 		}
386 		else if( c > 255 )
387 		{
388 			addSum	= (int)(c - 255);
389 			c		= 255;
390 
391 			b		+= addSum;
392 
393 			if( b > 255 )
394 			{
395 				b	= 255;
396 			}
397 		}
398 	}
399 	else if( Pass < 2 )
400 	{
401 		_Set_Brightness(b, c, a, Pass + 1);
402 	}
403 }
404 
405 
406 ///////////////////////////////////////////////////////////
407 //														 //
408 ///////////////////////////////////////////////////////////
409 
410 //---------------------------------------------------------
Get_Predefined_Count(void)411 int CSG_Colors::Get_Predefined_Count(void)
412 {
413 	return( SG_COLORS_COUNT );
414 }
415 
416 //---------------------------------------------------------
Get_Predefined_Name(int Index)417 const SG_Char * CSG_Colors::Get_Predefined_Name(int Index)
418 {
419 	switch( Index )
420 	{
421 	case SG_COLORS_DEFAULT        :	return( _TL("default"                  ) );
422 	case SG_COLORS_DEFAULT_BRIGHT :	return( _TL("default (same brightness)") );
423 	case SG_COLORS_BLACK_WHITE    :	return( _TL("greyscale"                ) );
424 	case SG_COLORS_BLACK_RED      :	return( _TL("black > red"              ) );
425 	case SG_COLORS_BLACK_GREEN    :	return( _TL("black > green"            ) );
426 	case SG_COLORS_BLACK_BLUE     :	return( _TL("black > blue"             ) );
427 	case SG_COLORS_WHITE_RED      :	return( _TL("white > red"              ) );
428 	case SG_COLORS_WHITE_GREEN    :	return( _TL("white > green"            ) );
429 	case SG_COLORS_WHITE_BLUE     :	return( _TL("white > blue"             ) );
430 	case SG_COLORS_YELLOW_RED     :	return( _TL("yellow > red"             ) );
431 	case SG_COLORS_YELLOW_GREEN   :	return( _TL("yellow > green"           ) );
432 	case SG_COLORS_YELLOW_BLUE    :	return( _TL("yellow > blue"            ) );
433 	case SG_COLORS_RED_GREEN      :	return( _TL("red > green"              ) );
434 	case SG_COLORS_RED_BLUE       :	return( _TL("red > blue"               ) );
435 	case SG_COLORS_GREEN_BLUE     :	return( _TL("green > blue"             ) );
436 	case SG_COLORS_RED_GREY_BLUE  :	return( _TL("red > grey > blue"        ) );
437 	case SG_COLORS_RED_GREY_GREEN :	return( _TL("red > grey > green"       ) );
438 	case SG_COLORS_GREEN_GREY_BLUE:	return( _TL("green > grey > blue"      ) );
439 	case SG_COLORS_RED_GREEN_BLUE :	return( _TL("red > green > blue"       ) );
440 	case SG_COLORS_RED_BLUE_GREEN :	return( _TL("red > blue > green"       ) );
441 	case SG_COLORS_GREEN_RED_BLUE :	return( _TL("green > red > blue"       ) );
442 	case SG_COLORS_RAINBOW        :	return( _TL("rainbow"                  ) );
443 	case SG_COLORS_NEON           :	return( _TL("neon"                     ) );
444 	case SG_COLORS_TOPOGRAPHY     :	return( _TL("topography 1"             ) );
445 	case SG_COLORS_TOPOGRAPHY_2   :	return( _TL("topography 2"             ) );
446 	case SG_COLORS_TOPOGRAPHY_3   :	return( _TL("topography 3"             ) );
447 	case SG_COLORS_PRECIPITATION  :	return( _TL("precipitation"            ) );
448 	case SG_COLORS_ASPECT_1       :	return( _TL("aspect 1"                 ) );
449 	case SG_COLORS_ASPECT_2       :	return( _TL("aspect 2"                 ) );
450 	case SG_COLORS_ASPECT_3       :	return( _TL("aspect 3"                 ) );
451 	default                       : return( _TL(""                         ) );
452 	}
453 }
454 
455 //---------------------------------------------------------
Set_Predefined(int Index,bool bRevert,int nColors)456 bool CSG_Colors::Set_Predefined(int Index, bool bRevert, int nColors)
457 {
458 	switch( Index )
459 	{
460 	case SG_COLORS_DEFAULT:
461 		Set_Default(nColors);
462 		break;
463 
464 	case SG_COLORS_DEFAULT_BRIGHT:
465 		Set_Default(nColors);
466 		Set_Ramp_Brighness(127, 127);
467 		break;
468 
469 	case SG_COLORS_BLACK_WHITE:
470 		Set_Ramp(SG_GET_RGB(  0,   0,   0), SG_GET_RGB(255, 255, 255));
471 		break;
472 
473 	case SG_COLORS_BLACK_RED:
474 		Set_Ramp(SG_GET_RGB(  0,   0,   0), SG_GET_RGB(255,   0,   0));
475 		break;
476 
477 	case SG_COLORS_BLACK_GREEN:
478 		Set_Ramp(SG_GET_RGB(  0,   0,   0), SG_GET_RGB(  0, 255,   0));
479 		break;
480 
481 	case SG_COLORS_BLACK_BLUE:
482 		Set_Ramp(SG_GET_RGB(  0,   0,   0), SG_GET_RGB(  0,   0, 255));
483 		break;
484 
485 	case SG_COLORS_WHITE_RED:
486 		Set_Count(3);
487 		Set_Color(0, SG_GET_RGB(255, 255, 255));
488 		Set_Color(1, SG_GET_RGB(255, 127,   0));
489 		Set_Color(2, SG_GET_RGB(159,   0,   0));
490 		break;
491 
492 	case SG_COLORS_WHITE_GREEN:
493 		Set_Ramp(SG_GET_RGB(255, 255, 255), SG_GET_RGB(  0, 127,   0));
494 		break;
495 
496 	case SG_COLORS_WHITE_BLUE:
497 		Set_Count(3);
498 		Set_Color(0, SG_GET_RGB(255, 255, 255));
499 		Set_Color(1, SG_GET_RGB(  0, 127, 255));
500 		Set_Color(2, SG_GET_RGB(  0,   0, 159));
501 		break;
502 
503 	case SG_COLORS_YELLOW_RED:
504 		Set_Ramp(SG_GET_RGB(255, 255,   0), SG_GET_RGB(191,   0,   0));
505 		break;
506 
507 	case SG_COLORS_YELLOW_GREEN:
508 		Set_Ramp(SG_GET_RGB(255, 255,   0), SG_GET_RGB(  0,  63,   0));
509 		break;
510 
511 	case SG_COLORS_YELLOW_BLUE:
512 		Set_Count(3);
513 		Set_Color(2, SG_GET_RGB(  0,  64, 127));
514 		Set_Color(1, SG_GET_RGB(127, 192, 255));
515 		Set_Color(0, SG_GET_RGB(255, 255, 200));
516 		break;
517 
518 	case SG_COLORS_RED_GREEN:
519 		Set_Count(5);
520 		Set_Color(0, SG_GET_RGB(159,   0,   0));
521 		Set_Color(1, SG_GET_RGB(255, 159,   0));
522 		Set_Color(2, SG_GET_RGB(255, 255,   0));
523 		Set_Color(3, SG_GET_RGB(159, 255,   0));
524 		Set_Color(4, SG_GET_RGB(  0, 159,   0));
525 		break;
526 
527 	case SG_COLORS_RED_BLUE:
528 		Set_Ramp(SG_GET_RGB(255,   0,   0), SG_GET_RGB(  0,   0, 255));
529 		break;
530 
531 	case SG_COLORS_GREEN_BLUE:
532 		Set_Ramp(SG_GET_RGB(  0, 255,   0), SG_GET_RGB(  0,   0, 255));
533 		break;
534 
535 	case SG_COLORS_RED_GREY_BLUE:
536 		Set_Count(5);
537 		Set_Color(0, SG_GET_RGB(127,   0,   0));
538 		Set_Color(1, SG_GET_RGB(255, 127,   0));
539 		Set_Color(2, SG_GET_RGB(239, 239, 239));
540 		Set_Color(3, SG_GET_RGB(  0, 127, 255));
541 		Set_Color(4, SG_GET_RGB(  0,   0, 127));
542 		break;
543 
544 	case SG_COLORS_RED_GREY_GREEN:
545 		Set_Count(5);
546 		Set_Color(0, SG_GET_RGB(127,   0,   0));
547 		Set_Color(1, SG_GET_RGB(255, 127,   0));
548 		Set_Color(2, SG_GET_RGB(239, 239, 239));
549 		Set_Color(3, SG_GET_RGB(  0, 255, 127));
550 		Set_Color(4, SG_GET_RGB(  0, 127,   0));
551 		break;
552 
553 	case SG_COLORS_GREEN_GREY_BLUE:
554 		Set_Count(5);
555 		Set_Color(0, SG_GET_RGB(  0, 127,   0));
556 		Set_Color(1, SG_GET_RGB(127, 255,   0));
557 		Set_Color(2, SG_GET_RGB(239, 239, 239));
558 		Set_Color(3, SG_GET_RGB(  0, 127, 255));
559 		Set_Color(4, SG_GET_RGB(  0,   0, 127));
560 		break;
561 
562 	case SG_COLORS_RED_GREEN_BLUE:
563 		Set_Count(5);
564 		Set_Color(0, SG_GET_RGB(127,   0, 127));
565 		Set_Color(1, SG_GET_RGB(255,   0,   0));
566 		Set_Color(2, SG_GET_RGB(  0, 255,   0));
567 		Set_Color(3, SG_GET_RGB(  0,   0, 255));
568 		Set_Color(4, SG_GET_RGB(127,   0, 127));
569 		break;
570 
571 	case SG_COLORS_RED_BLUE_GREEN:
572 		Set_Count(5);
573 		Set_Color(0, SG_GET_RGB(127, 127,   0));
574 		Set_Color(1, SG_GET_RGB(255,   0,   0));
575 		Set_Color(2, SG_GET_RGB(  0,   0, 255));
576 		Set_Color(3, SG_GET_RGB(  0, 255,   0));
577 		Set_Color(4, SG_GET_RGB(127, 127,   0));
578 		break;
579 
580 	case SG_COLORS_GREEN_RED_BLUE:
581 		Set_Count(5);
582 		Set_Color(0, SG_GET_RGB(  0, 127, 127));
583 		Set_Color(1, SG_GET_RGB(  0, 255,   0));
584 		Set_Color(2, SG_GET_RGB(255,   0,   0));
585 		Set_Color(3, SG_GET_RGB(  0,   0, 255));
586 		Set_Color(4, SG_GET_RGB(  0, 127, 127));
587 		break;
588 
589 	case SG_COLORS_RAINBOW:
590 		Set_Count(8);
591 		Set_Color(0, SG_GET_RGB( 64,   0, 127));
592 		Set_Color(1, SG_GET_RGB(  0,   0, 255));
593 		Set_Color(2, SG_GET_RGB(  0, 255, 255));
594 		Set_Color(3, SG_GET_RGB(  0, 191,   0));
595 		Set_Color(4, SG_GET_RGB(255, 255,   0));
596 		Set_Color(5, SG_GET_RGB(255, 127,   0));
597 		Set_Color(6, SG_GET_RGB(255,   0,   0));
598 		Set_Color(7, SG_GET_RGB(127,   0,   0));
599 		break;
600 
601 	case SG_COLORS_NEON:
602 		Set_Count(7);
603 		Set_Color(0, SG_GET_RGB(  0,   0,   0));
604 		Set_Color(1, SG_GET_RGB(255,   0,   0));
605 		Set_Color(2, SG_GET_RGB(  0,   0,   0));
606 		Set_Color(3, SG_GET_RGB(255, 255,   0));
607 		Set_Color(4, SG_GET_RGB(  0,   0,   0));
608 		Set_Color(5, SG_GET_RGB(  0, 255,   0));
609 		Set_Color(6, SG_GET_RGB(  0,   0,   0));
610 		break;
611 
612 	case SG_COLORS_TOPOGRAPHY:
613 		Set_Count(5);
614 		Set_Color(0, SG_GET_RGB(  0,  63, 127));
615 		Set_Color(1, SG_GET_RGB(127, 255,   0));
616 		Set_Color(2, SG_GET_RGB(255, 255, 127));
617 		Set_Color(3, SG_GET_RGB(191, 127,   0));
618 		Set_Color(4, SG_GET_RGB(127,  63,   0));
619 		break;
620 
621 	case SG_COLORS_TOPOGRAPHY_2:
622 		Set_Count(6);
623 		Set_Color(0, SG_GET_RGB(  0, 191, 191));
624 		Set_Color(1, SG_GET_RGB(  0, 255,   0));
625 		Set_Color(2, SG_GET_RGB(255, 255,   0));
626 		Set_Color(3, SG_GET_RGB(255, 127,   0));
627 		Set_Color(4, SG_GET_RGB(191, 152, 110));
628 		Set_Color(5, SG_GET_RGB(199, 199, 199));
629 		break;
630 
631 	case SG_COLORS_TOPOGRAPHY_3:
632 		Set_Count(9);
633 		Set_Color(0, SG_GET_RGB(177, 242, 212));
634 		Set_Color(1, SG_GET_RGB(248, 252, 179));
635 		Set_Color(2, SG_GET_RGB( 11, 128, 064));
636 		Set_Color(3, SG_GET_RGB(248, 202,  80));
637 		Set_Color(4, SG_GET_RGB(158,  30,   0));
638 		Set_Color(5, SG_GET_RGB(128, 064, 064));
639 		Set_Color(6, SG_GET_RGB(185, 121, 076));
640 		Set_Color(7, SG_GET_RGB(179, 179, 179));
641 		Set_Color(8, SG_GET_RGB(255, 255, 255));
642 		break;
643 
644 	case SG_COLORS_PRECIPITATION:	// juergen's favorite precipition colour ramp
645 		Set_Count(22);
646 		Set_Color( 0, SG_GET_RGB(216, 204, 131));
647 		Set_Color( 1, SG_GET_RGB(196, 208, 111));
648 		Set_Color( 2, SG_GET_RGB(184, 210, 101));
649 		Set_Color( 3, SG_GET_RGB(172, 212,  91));
650 		Set_Color( 4, SG_GET_RGB(139, 212,  99));
651 		Set_Color( 5, SG_GET_RGB(107, 212, 107));
652 		Set_Color( 6, SG_GET_RGB( 75, 212, 119));
653 		Set_Color( 7, SG_GET_RGB( 42, 212, 131));
654 		Set_Color( 8, SG_GET_RGB( 26, 212, 151));
655 		Set_Color( 9, SG_GET_RGB( 10, 212, 172));
656 		Set_Color(10, SG_GET_RGB( 30, 192, 192));
657 		Set_Color(11, SG_GET_RGB( 50, 172, 212));
658 		Set_Color(12, SG_GET_RGB( 70, 151, 214));
659 		Set_Color(13, SG_GET_RGB( 91, 131, 216));
660 		Set_Color(14, SG_GET_RGB( 75, 115, 198));
661 		Set_Color(15, SG_GET_RGB( 58,  99, 180));
662 		Set_Color(16, SG_GET_RGB( 42,  83, 184));
663 		Set_Color(17, SG_GET_RGB( 26, 066, 188));
664 		Set_Color(18, SG_GET_RGB( 26, 046, 180));
665 		Set_Color(19, SG_GET_RGB( 26, 026, 166));
666 		Set_Color(20, SG_GET_RGB( 38,  18, 151));
667 		Set_Color(21, SG_GET_RGB( 50, 010, 131));
668 		break;
669 
670 	case SG_COLORS_ASPECT_1:
671 		Set_Count(5);
672 		Set_Color(0, SG_GET_RGB(225, 225, 225));
673 		Set_Color(1, SG_GET_RGB(127, 127, 255));
674 		Set_Color(2, SG_GET_RGB( 20,  20,  20));
675 		Set_Color(3, SG_GET_RGB(127, 255, 127));
676 		Set_Color(4, SG_GET_RGB(225, 225, 225));
677 		break;
678 
679 	case SG_COLORS_ASPECT_2:
680 		Set_Count(5);
681 		Set_Color(0, SG_GET_RGB(225, 225, 225));
682 		Set_Color(1, SG_GET_RGB(255, 127, 127));
683 		Set_Color(2, SG_GET_RGB( 20,  20,  20));
684 		Set_Color(3, SG_GET_RGB(127, 255, 127));
685 		Set_Color(4, SG_GET_RGB(225, 225, 225));
686 		break;
687 
688 	case SG_COLORS_ASPECT_3:
689 		Set_Count(5);
690 		Set_Color(0, SG_GET_RGB(225, 225, 225));
691 		Set_Color(1, SG_GET_RGB(255, 127, 127));
692 		Set_Color(2, SG_GET_RGB( 20,  20,  20));
693 		Set_Color(3, SG_GET_RGB(127, 127, 255));
694 		Set_Color(4, SG_GET_RGB(225, 225, 225));
695 		break;
696 
697 	case SG_COLORS_COUNT + 0:
698 		Set_Count(3);
699 		Set_Color(0, SG_GET_RGB(  0, 128,   0));
700 		Set_Color(1, SG_GET_RGB(255, 255, 127));
701 		Set_Color(2, SG_GET_RGB(127,  63,  63));
702 		break;
703 
704 	case SG_COLORS_COUNT + 1:
705 		Set_Count(3);
706 		Set_Color(0, SG_GET_RGB(  0,   0, 255));
707 		Set_Color(1, SG_GET_RGB(255, 255,   0));
708 		Set_Color(2, SG_GET_RGB(255,   0,   0));
709 		break;
710 
711 	case SG_COLORS_COUNT + 2:
712 		Set_Count(3);
713 		Set_Color(0, SG_GET_RGB(  0, 127,   0));
714 		Set_Color(1, SG_GET_RGB(255, 255, 255));
715 		Set_Color(2, SG_GET_RGB(255,   0,   0));
716 		break;
717 
718 	case SG_COLORS_COUNT + 3:
719 		Set_Count(3);
720 		Set_Color(0, SG_GET_RGB(  0,   0, 255));
721 		Set_Color(1, SG_GET_RGB(255, 255, 255));
722 		Set_Color(2, SG_GET_RGB(  0, 127,   0));
723 		break;
724 
725 	case SG_COLORS_COUNT + 4:
726 		Set_Count(4);
727 		Set_Color(0, SG_GET_RGB(  0,   0, 255));
728 		Set_Color(1, SG_GET_RGB(  0, 255,   0));
729 		Set_Color(2, SG_GET_RGB(255, 255,   0));
730 		Set_Color(3, SG_GET_RGB(255,   0,   0));
731 		break;
732 
733 	case SG_COLORS_COUNT + 5:
734 		Set_Count(11);
735 		Set_Color( 0, SG_GET_RGB( 37,  57, 175));
736 		Set_Color( 1, SG_GET_RGB( 40, 127, 251));
737 		Set_Color( 2, SG_GET_RGB( 50, 190, 255));
738 		Set_Color( 3, SG_GET_RGB(106, 235, 255));
739 		Set_Color( 4, SG_GET_RGB(138, 236, 174));
740 		Set_Color( 5, SG_GET_RGB(205, 255, 162));
741 		Set_Color( 6, SG_GET_RGB(240, 236, 121));
742 		Set_Color( 7, SG_GET_RGB(255, 189,  87));
743 		Set_Color( 8, SG_GET_RGB(255, 161,  68));
744 		Set_Color( 9, SG_GET_RGB(255, 186, 133));
745 		Set_Color(10, SG_GET_RGB(255, 255, 255));
746 		break;
747 
748 	case SG_COLORS_COUNT + 6:
749 		Set_Count(8);
750 		Set_Color(0, SG_GET_RGB(171,  43,   0));
751 		Set_Color(1, SG_GET_RGB(255, 127,   0));
752 		Set_Color(2, SG_GET_RGB(255, 255,   0));
753 		Set_Color(3, SG_GET_RGB(  0, 255,   0));
754 		Set_Color(4, SG_GET_RGB(  0, 255, 255));
755 		Set_Color(5, SG_GET_RGB(  0,   0, 255));
756 		Set_Color(6, SG_GET_RGB(255,   0, 255));
757 		Set_Color(7, SG_GET_RGB(255, 255, 255));
758 		break;
759 
760 	case SG_COLORS_COUNT + 7:
761 		Set_Count(5);
762 		Set_Color(0, SG_GET_RGB(  0,   0, 191));
763 		Set_Color(1, SG_GET_RGB(255,   0, 255));
764 		Set_Color(2, SG_GET_RGB(255,   0,   0));
765 		Set_Color(3, SG_GET_RGB(255, 255,   0));
766 		Set_Color(4, SG_GET_RGB(245, 245, 163));
767 		break;
768 
769 	case SG_COLORS_COUNT + 8:
770 		Set_Count(6);
771 		Set_Color(0, SG_GET_RGB(127, 255, 255));
772 		Set_Color(1, SG_GET_RGB(  0,   0, 255));
773 		Set_Color(2, SG_GET_RGB(127,   0, 255));
774 		Set_Color(3, SG_GET_RGB(255,   0,   0));
775 		Set_Color(4, SG_GET_RGB(255, 255,   0));
776 		Set_Color(5, SG_GET_RGB(255, 255, 127));
777 		break;
778 
779 	case SG_COLORS_COUNT + 9:
780 		Set_Count(5);
781 		Set_Color(0, SG_GET_RGB(  0,   0, 127));
782 		Set_Color(1, SG_GET_RGB(  0, 127, 255));
783 		Set_Color(2, SG_GET_RGB(  0, 191,   0));
784 		Set_Color(3, SG_GET_RGB(191, 255,   0));
785 		Set_Color(4, SG_GET_RGB(255, 255, 127));
786 		break;
787 
788 	case SG_COLORS_COUNT + 10:
789 		Set_Count(nColors);
790 		Random();
791 		break;
792 
793 	default:
794 		return( false );
795 	}
796 
797 	//-----------------------------------------------------
798 	if( bRevert )
799 	{
800 		Revert();
801 	}
802 
803 	return( Set_Count(nColors) );
804 }
805 
806 //---------------------------------------------------------
Set_Default(int nColors)807 bool CSG_Colors::Set_Default(int nColors)
808 {
809 	if( nColors > 0 )
810 	{
811 		m_nColors	= nColors;
812 		m_Colors	= (long *)SG_Realloc(m_Colors, m_nColors * sizeof(long));
813 
814 		double	d	= 0., dStep = 2. * M_PI / (double)Get_Count();
815 
816 		for(int i=0; i<Get_Count(); i++, d+=dStep)
817 		{
818 			Set_Color(i,
819 				(int)(d < M_PI / 2 ? 0 : 128 - 127 * sin(M_PI - d)),
820 				(int)(128 - 127 * cos(d)),
821 				(int)(d > M_PI * 3 / 2 ? 0 : 128 + 127 * sin(d))
822 			);
823 		}
824 
825 		return( true );
826 	}
827 
828 	return( false );
829 }
830 
831 //---------------------------------------------------------
Set_Ramp(long Color_A,long Color_B)832 bool CSG_Colors::Set_Ramp(long Color_A, long Color_B)
833 {
834 	return( Set_Ramp(Color_A, Color_B, 0, Get_Count() - 1) );
835 }
836 
837 //---------------------------------------------------------
Set_Ramp(long Color_A,long Color_B,int iColor_A,int iColor_B)838 bool CSG_Colors::Set_Ramp(long Color_A, long Color_B, int iColor_A, int iColor_B)
839 {
840 	if( iColor_A > iColor_B )
841 	{
842 		int	i    = iColor_A;
843 		iColor_A = iColor_B;
844 		iColor_B = i;
845 	}
846 
847 	if( iColor_A < 0 )
848 	{
849 		iColor_A = 0;
850 	}
851 
852 	if( iColor_B >= Get_Count() )
853 	{
854 		iColor_B = Get_Count() - 1;
855 	}
856 
857 	//-----------------------------------------------------
858 	int	n	= iColor_B - iColor_A;
859 
860 	if( n > 0 )
861 	{
862 		int		ar	= SG_GET_R(Color_A);
863 		double	dr	= (double)(SG_GET_R(Color_B) - ar) / (double)n;
864 
865 		int		ag	= SG_GET_G(Color_A);
866 		double	dg	= (double)(SG_GET_G(Color_B) - ag) / (double)n;
867 
868 		int		ab	= SG_GET_B(Color_A);
869 		double	db	= (double)(SG_GET_B(Color_B) - ab) / (double)n;
870 
871 		for(int i=0; i<=n; i++)
872 		{
873 			Set_Color(iColor_A + i,
874 				(int)(ar + i * dr),
875 				(int)(ag + i * dg),
876 				(int)(ab + i * db)
877 			);
878 		}
879 
880 		return( true );
881 	}
882 
883 	return( false );
884 }
885 
886 //---------------------------------------------------------
Set_Ramp_Brighness(int Brightness_A,int Brightness_B)887 bool CSG_Colors::Set_Ramp_Brighness(int Brightness_A, int Brightness_B)
888 {
889 	return( Set_Ramp_Brighness(Brightness_A, Brightness_B, 0, Get_Count() - 1) );
890 }
891 
892 //---------------------------------------------------------
Set_Ramp_Brighness(int Brightness_A,int Brightness_B,int iColor_A,int iColor_B)893 bool CSG_Colors::Set_Ramp_Brighness(int Brightness_A, int Brightness_B, int iColor_A, int iColor_B)
894 {
895 	if( iColor_A > iColor_B )
896 	{
897 		int	i    = iColor_A;
898 		iColor_A = iColor_B;
899 		iColor_B = i;
900 	}
901 
902 	if( iColor_A < 0 )
903 	{
904 		iColor_A = 0;
905 	}
906 
907 	if( iColor_B >= Get_Count() )
908 	{
909 		iColor_B = Get_Count() - 1;
910 	}
911 
912 	//-----------------------------------------------------
913 	int	n	= iColor_B - iColor_A;
914 
915 	if( n > 0 )
916 	{
917 		double	dBrightness	= (double)(Brightness_B - Brightness_A) / (double)n;
918 
919 		for(int i=0; i<=n; i++)
920 		{
921 			Set_Brightness(iColor_A + i, (int)(Brightness_A + i * dBrightness));
922 		}
923 
924 		return( true );
925 	}
926 
927 	return( false );
928 }
929 
930 
931 ///////////////////////////////////////////////////////////
932 //														 //
933 ///////////////////////////////////////////////////////////
934 
935 //---------------------------------------------------------
Random(void)936 bool CSG_Colors::Random(void)
937 {
938 	for(int i=0; i<Get_Count(); i++)
939 	{
940 		Set_Color(i,
941 			(int)(255.0 * (double)rand() / (double)RAND_MAX),
942 			(int)(255.0 * (double)rand() / (double)RAND_MAX),
943 			(int)(255.0 * (double)rand() / (double)RAND_MAX)
944 		);
945 	}
946 
947 	return( Get_Count() > 0 );
948 }
949 
950 //---------------------------------------------------------
Invert(void)951 bool CSG_Colors::Invert(void)
952 {
953 	for(int i=0; i<Get_Count(); i++)
954 	{
955 		Set_Color(i, 255 - Get_Red(i), 255 - Get_Green(i), 255 - Get_Blue(i));
956 	}
957 
958 	return( Get_Count() > 0 );
959 }
960 
961 //---------------------------------------------------------
Revert(void)962 bool CSG_Colors::Revert(void)
963 {
964 	for(int i=0, j=Get_Count()-1; i<j; i++, j--)
965 	{
966 		long    c  = Get_Color(j);
967 		Set_Color(j, Get_Color(i));
968 		Set_Color(i, c);
969 	}
970 
971 	return( Get_Count() > 0 );
972 }
973 
974 //---------------------------------------------------------
Greyscale(void)975 bool CSG_Colors::Greyscale(void)
976 {
977 	for(int i=0; i<Get_Count(); i++)
978 	{
979 		long	c	= Get_Brightness(i);
980 
981 		Set_Color(i, c, c, c);
982 	}
983 
984 	return( Get_Count() > 0 );
985 }
986 
987 
988 ///////////////////////////////////////////////////////////
989 //														 //
990 ///////////////////////////////////////////////////////////
991 
992 //---------------------------------------------------------
operator =(const CSG_Colors & Colors)993 CSG_Colors & CSG_Colors::operator = (const CSG_Colors &Colors)
994 {
995 	Create(Colors);
996 
997 	return( *this );
998 }
999 
1000 //---------------------------------------------------------
Assign(const CSG_Colors & Colors)1001 bool CSG_Colors::Assign(const CSG_Colors &Colors)
1002 {
1003 	return( Create(Colors) );
1004 }
1005 
1006 //---------------------------------------------------------
Assign(CSG_Colors * pColors)1007 bool CSG_Colors::Assign(CSG_Colors *pColors)
1008 {
1009 	return( pColors ? Create(*pColors) : false );
1010 }
1011 
1012 
1013 ///////////////////////////////////////////////////////////
1014 //														 //
1015 ///////////////////////////////////////////////////////////
1016 
1017 //---------------------------------------------------------
1018 #define COLORS_SERIAL_VERSION_BINARY	"SAGA_COLORPALETTE_VERSION_0.100_BINARY"
1019 #define COLORS_SERIAL_VERSION__ASCII	"SAGA_COLORPALETTE_VERSION_0.100__ASCII"
1020 
1021 //---------------------------------------------------------
Load(const CSG_String & File_Name)1022 bool CSG_Colors::Load(const CSG_String &File_Name)
1023 {
1024 	CSG_File	Stream;
1025 
1026 	if( !Stream.Open(File_Name, SG_FILE_R, true) )
1027 	{
1028 		return( false );
1029 	}
1030 
1031 	CSG_String	Version;
1032 
1033 	Stream.Read(Version, sizeof(COLORS_SERIAL_VERSION__ASCII));
1034 
1035 	//-----------------------------------------------------
1036 	if( Version.Find(COLORS_SERIAL_VERSION__ASCII) == 0 )
1037 	{
1038 		return( Serialize(Stream, false, false) );
1039 	}
1040 
1041 	//-----------------------------------------------------
1042 	Stream.Seek_Start();
1043 	Stream.Read(Version, sizeof(COLORS_SERIAL_VERSION_BINARY));
1044 
1045 	if( Version.Find(COLORS_SERIAL_VERSION_BINARY) == 0 )
1046 	{
1047 		int	nColors;
1048 
1049 		Stream.Read(&nColors, sizeof(nColors));
1050 
1051 		if( Set_Count(nColors) )	// different os, different sizeof(long) !!
1052 		{
1053 			size_t	ValueSize	= (size_t)((Stream.Length() - (sizeof(COLORS_SERIAL_VERSION_BINARY) + sizeof(int))) / nColors);
1054 
1055 			if( ValueSize > 0 )
1056 			{
1057 				BYTE	*c	= (BYTE *)SG_Malloc(ValueSize);
1058 
1059 				for(int i=0; i<nColors; i++)
1060 				{
1061 					Stream.Read(c, ValueSize);
1062 
1063 					Set_Color(i, c[0], c[1], c[2]);
1064 				}
1065 
1066 				SG_Free(c);
1067 			}
1068 
1069 			return( true );
1070 		}
1071 	}
1072 
1073 	//-----------------------------------------------------
1074 	else // SAGA 1.x compatibility...
1075 	{
1076 		short	nColors;
1077 
1078 		Stream.Seek_Start();
1079 		Stream.Read(&nColors, sizeof(short));
1080 
1081 		if( Stream.Length() == (int)(sizeof(short) + 3 * nColors) && Set_Count(nColors) )
1082 		{
1083 			BYTE *R = (BYTE *)SG_Malloc(nColors * sizeof(BYTE)); Stream.Read(R, nColors * sizeof(BYTE));
1084 			BYTE *G = (BYTE *)SG_Malloc(nColors * sizeof(BYTE)); Stream.Read(G, nColors * sizeof(BYTE));
1085 			BYTE *B = (BYTE *)SG_Malloc(nColors * sizeof(BYTE)); Stream.Read(B, nColors * sizeof(BYTE));
1086 
1087 			for(int i=0; i<nColors; i++)
1088 			{
1089 				Set_Color(i, R[i], G[i], B[i]);
1090 			}
1091 
1092 			SG_Free(R); SG_Free(G); SG_Free(B);
1093 
1094 			return( true );
1095 		}
1096 	}
1097 
1098 	//-----------------------------------------------------
1099 	return( false );
1100 }
1101 
1102 //---------------------------------------------------------
Save(const CSG_String & File_Name,bool bBinary)1103 bool CSG_Colors::Save(const CSG_String &File_Name, bool bBinary)
1104 {
1105 	CSG_File	Stream;
1106 
1107 	if( Stream.Open(File_Name, SG_FILE_W, bBinary) )
1108 	{
1109 		if( bBinary )
1110 		{
1111 			Stream.Write((void *)COLORS_SERIAL_VERSION_BINARY, sizeof(COLORS_SERIAL_VERSION_BINARY));
1112 		}
1113 		else
1114 		{
1115 			Stream.Write(COLORS_SERIAL_VERSION__ASCII); Stream.Write("\n");
1116 		}
1117 
1118 		Serialize(Stream, true, bBinary);
1119 
1120 		return( true );
1121 	}
1122 
1123 	return( false );
1124 }
1125 
1126 
1127 ///////////////////////////////////////////////////////////
1128 //														 //
1129 ///////////////////////////////////////////////////////////
1130 
1131 //---------------------------------------------------------
Serialize(CSG_File & Stream,bool bSave,bool bBinary)1132 bool CSG_Colors::Serialize(CSG_File &Stream, bool bSave, bool bBinary)
1133 {
1134 	if( Stream.is_Open() )
1135 	{
1136 		//-------------------------------------------------
1137 		if( bBinary )
1138 		{
1139 			if( bSave )
1140 			{
1141 				if( m_nColors > 0 )
1142 				{
1143 					Stream.Write(&m_nColors, sizeof(m_nColors));
1144 					Stream.Write(m_Colors, sizeof(long), m_nColors);
1145 				}
1146 			}
1147 			else
1148 			{
1149 				int	nColors;
1150 
1151 				Stream.Read(&nColors, sizeof(m_nColors));
1152 
1153 				if( Set_Count(nColors) )
1154 				{
1155 					Stream.Read(m_Colors, sizeof(long), m_nColors);
1156 				}
1157 			}
1158 
1159 			return( true );
1160 		}
1161 
1162 		//-------------------------------------------------
1163 		else
1164 		{
1165 			if( bSave )
1166 			{
1167 				if( Get_Count() > 0 )
1168 				{
1169 					Stream.Printf("%d\n", Get_Count());
1170 
1171 					for(int i=0; i<Get_Count(); i++)
1172 					{
1173 						Stream.Printf("%03d %03d %03d\n", (int)Get_Red(i), (int)Get_Green(i), (int)Get_Blue(i));
1174 					}
1175 				}
1176 			}
1177 			else
1178 			{
1179 				CSG_String	sLine;
1180 
1181 				while( Stream.Read_Line(sLine) && sLine.is_Empty() ) {}	// skip empty lines
1182 
1183 				if( Set_Count(sLine.asInt()) )
1184 				{
1185 					for(int i=0; i<Get_Count(); i++)
1186 					{
1187 						Stream.Read_Line(sLine);
1188 
1189 						Set_Color(i,
1190 							sLine                .asInt(),
1191 							sLine.AfterFirst(' ').asInt(),
1192 							sLine.AfterLast (' ').asInt()
1193 						);
1194 					}
1195 				}
1196 			}
1197 
1198 			return( true );
1199 		}
1200 	}
1201 
1202 	return( false );
1203 }
1204 
1205 //---------------------------------------------------------
to_Text(CSG_String & String)1206 bool CSG_Colors::to_Text(CSG_String &String)
1207 {
1208 	if( Get_Count() > 0 )
1209 	{
1210 		String.Clear();
1211 
1212 		for(int i=0; i<Get_Count(); i++)
1213 		{
1214 			String	+= CSG_String::Format("%03d %03d %03d;", (int)Get_Red(i), (int)Get_Green(i), (int)Get_Blue(i));
1215 		}
1216 
1217 		return( true );
1218 	}
1219 
1220 	return( false );
1221 }
1222 
1223 //---------------------------------------------------------
from_Text(const CSG_String & String)1224 bool CSG_Colors::from_Text(const CSG_String &String)
1225 {
1226 	if( Set_Count((int)String.Length() / 12) )
1227 	{
1228 		for(int i=0, j=0; i<Get_Count(); i++, j+=12)
1229 		{
1230 			Set_Color(i,
1231 				String.Mid(j + 0, 4).asInt(),
1232 				String.Mid(j + 4, 4).asInt(),
1233 				String.Mid(j + 8, 4).asInt()
1234 			);
1235 		}
1236 
1237 		return( true );
1238 	}
1239 
1240 	return( false );
1241 }
1242 
1243 
1244 ///////////////////////////////////////////////////////////
1245 //														 //
1246 //														 //
1247 //														 //
1248 ///////////////////////////////////////////////////////////
1249 
1250 //---------------------------------------------------------
1251