Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
Color.ih
1/**
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *
15 **/
16
17/**
18 * @file Color.ih
19 * @author Bertrand Kerautret (\c kerautre@loria.fr )
20 * LORIA (CNRS, UMR 7503), University of Nancy, France
21 *
22 * @date 2011/07/17
23 *
24 * Implementation of inline methods defined in Color.h
25 *
26 * This file is part of the DGtal library.
27 */
28
29///////////////////////////////////////////////////////////////////////////////
30// IMPLEMENTATION of inline methods.
31///////////////////////////////////////////////////////////////////////////////
32
33//////////////////////////////////////////////////////////////////////////////
34#include <cstdlib>
35#include <cmath>
36//////////////////////////////////////////////////////////////////////////////
37
38
39
40///////////////////////////////////////////////////////////////////////////////
41// Implementation of inline methods //
42
43
44///////////////////////////////////////////////////////////////////////////////
45// Implementation of inline functions and external operators //
46
47/**
48 * Overloads 'operator<<' for displaying objects of class 'Color'.
49 * @param out the output stream where the object is written.
50 * @param object the object of class 'Color' to write.
51 * @return the output stream after the writing.
52 */
53inline
54std::ostream&
55DGtal::operator<< ( std::ostream & out,
56 const Color & object )
57{
58 object.selfDisplay ( out );
59 return out;
60}
61
62inline
63DGtal::Color
64DGtal::operator*( const double coeff,
65 const Color & aColor )
66 {
67 Color c=aColor*coeff;
68 return c;
69 }
70
71inline DGtal::Color &
72DGtal::Color::setRGBi( const unsigned char aRedValue,
73 const unsigned char aGreenValue,
74 const unsigned char aBlueValue,
75 const unsigned char aAlphaValue ) {
76 myRed = aRedValue;
77 myGreen = aGreenValue;
78 myBlue = aBlueValue;
79 myAlpha = aAlphaValue;
80 return *this;
81}
82
83
84inline void
85DGtal::Color::red( const unsigned char aRedValue )
86{
87 myRed = aRedValue;
88}
89
90inline void
91DGtal::Color::green( unsigned char aGreenValue )
92{
93 myGreen = aGreenValue;
94}
95
96inline void
97DGtal::Color::blue( unsigned char aBlueValue )
98{
99 myBlue = aBlueValue;
100}
101
102inline void
103DGtal::Color::alpha( unsigned char aAlphaValue )
104{
105 myAlpha = aAlphaValue;
106}
107
108inline
109unsigned char
110DGtal::Color::red() const
111{
112 return myRed;
113}
114
115inline
116unsigned char
117DGtal::Color::green() const
118{
119 return myGreen;
120}
121
122inline
123unsigned char
124DGtal::Color::blue() const
125{
126 return myBlue;
127}
128
129inline
130unsigned char
131DGtal::Color::alpha() const
132{
133 return myAlpha;
134}
135inline
136double
137DGtal::Color::r() const
138{
139 return ((double) myRed)/255.0;
140}
141
142inline
143double
144DGtal::Color::g() const
145{
146 return ((double) myGreen)/255.0;
147}
148
149inline
150double
151DGtal::Color::b() const
152{
153 return ((double) myBlue)/255.0;
154}
155
156inline
157double
158DGtal::Color::a() const
159{
160 return ((double) myAlpha)/255.0;
161}
162
163inline
164DGtal::uint32_t
165DGtal::Color::getRGB() const
166{
167 return (((DGtal::uint32_t) myRed) << 16)
168 | (((DGtal::uint32_t) myGreen) << 8)
169 | ((DGtal::uint32_t) myBlue);
170}
171
172inline
173DGtal::uint32_t
174DGtal::Color::getRGBA() const
175{
176 return (((DGtal::uint32_t) myRed) << 24)
177 | (((DGtal::uint32_t) myGreen) << 16)
178 | (((DGtal::uint32_t) myBlue)<< 8)
179 | ((DGtal::uint32_t) myAlpha);
180}
181
182inline
183bool
184DGtal::Color::valid() const
185{
186 return (*this) != Color::None;
187}
188
189inline
190void
191DGtal::Color::HSVtoRGB
192( double & r, double & g, double & b,
193 const double h, const double s, const double v)
194{
195 int i;
196 double f, p, q, t;
197 if( s == 0 ) { // achromatic (gray)
198 r = g = b = v;
199 return;
200 }
201 i = static_cast<int>( floor( h / 60 ) );
202 f = ( h / 60 ) - i; // factorial part of h
203 p = v * ( 1.0 - s );
204 q = v * ( 1.0 - s * f );
205 t = v * ( 1.0 - s * ( 1.0 - f ) );
206 switch( i ) {
207 case 0:
208 r = v; g = t; b = p;
209 break;
210 case 1:
211 r = q; g = v; b = p;
212 break;
213 case 2:
214 r = p; g = v; b = t;
215 break;
216 case 3:
217 r = p; g = q; b = v;
218 break;
219 case 4:
220 r = t; g = p; b = v;
221 break;
222 default: // case 5:
223 r = v; g = p; b = q;
224 break;
225 }
226}
227
228inline
229void
230DGtal::Color::RGBtoHSV
231( double &h, double &s, double &v,
232 const unsigned char r,
233 const unsigned char g,
234 const unsigned char b )
235{
236 double min = (r<g) ? r : g;
237 if ( b < min ) min = b;
238 unsigned char max = (r>g) ? r : g;
239 if ( b > max ) max = b;
240
241 double dr = r / 255.0;
242 double dg = g / 255.0;
243 double db = b / 255.0;
244 v = max / 255.0; // (0.3*dr + 0.59*dg + 0.11*db);
245 if ( max == min ) {
246 h = 0;
247 s = 0;
248 return;
249 } else {
250 double diff = ( max - min ) / 255.0;
251 if ( max == r ) {
252 h = (dg - db ) / diff;
253 } else if ( max == g ) {
254 h = 2.0 + ( ( db - dr ) / diff );
255 } else if ( max == b ) {
256 h = 4.0 + ( ( dr - dg ) / diff );
257 }
258 h *= 60.0;
259 if ( h < 0 ) h += 360;
260 s = diff / v;
261 }
262}
263
264// //
265///////////////////////////////////////////////////////////////////////////////
266
267///////////////////////////////////////////////////////////////////////////////
268// class Color
269///////////////////////////////////////////////////////////////////////////////
270
271
272///////////////////////////////////////////////////////////////////////////////
273// Standard services - public :
274
275
276inline
277DGtal::Color::Color( const unsigned int rgb, unsigned char aAlphaValue )
278 :myAlpha( aAlphaValue )
279{
280 myRed = ( rgb & 0xFF0000u ) >> 16;
281 myGreen = ( rgb & 0xFF00u ) >> 8;
282 myBlue = rgb & 0xFF;
283}
284
285
286inline
287DGtal::Color &
288DGtal::Color::setRGBA( const DGtal::uint32_t aRGBA )
289{
290 myRed = ( aRGBA & 0xFF000000u ) >> 24;
291 myGreen = ( aRGBA & 0xFF0000u ) >> 16;
292 myBlue = ( aRGBA & 0xFF00u ) >> 8;
293 myAlpha = aRGBA & 0xFF;
294 return *this;
295}
296
297
298inline
299DGtal::Color &
300DGtal::Color::setRGBf( float aRedValue,
301 float aGreenValue,
302 float aBlueValue,
303 float aAlphaValue ) {
304 if ( aRedValue > 1.0f ) aRedValue = 1.0f;
305 if ( aRedValue < 0.0f ) aRedValue = 0.0f;
306 myRed = static_cast<unsigned char>( 255 * aRedValue );
307 if ( aGreenValue > 1.0f ) aGreenValue = 1.0f;
308 if ( aGreenValue < 0.0f ) aGreenValue = 0.0f;
309 myGreen = static_cast<unsigned char>( 255 * aGreenValue );
310 if ( aBlueValue > 1.0f ) aBlueValue = 1.0f;
311 if ( aBlueValue < 0.0f ) aBlueValue = 0.0f;
312 myBlue = static_cast<unsigned char>( 255 * aBlueValue );
313 if ( aAlphaValue > 1.0f ) aAlphaValue = 1.0f;
314 if ( aAlphaValue < 0.0f ) aAlphaValue = 0.0f;
315 myAlpha = static_cast<unsigned char>( 255 * aAlphaValue );
316 return *this;
317}
318
319
320inline
321bool
322DGtal::Color::operator==( const Color & aColor ) const
323{
324 return myRed == aColor.myRed
325 && myGreen == aColor.myGreen
326 && myBlue == aColor.myBlue
327 && myAlpha == aColor.myAlpha;
328}
329
330
331inline
332bool
333DGtal::Color::operator!=( const Color & aColor ) const
334{
335 return myRed != aColor.myRed
336 || myGreen != aColor.myGreen
337 || myBlue != aColor.myBlue
338 || myAlpha != aColor.myAlpha;
339}
340
341
342inline
343bool
344DGtal::Color::operator<( const Color & aColor ) const
345{
346 if ( myRed < aColor.myRed )
347 return true;
348 if ( myRed == aColor.myRed ) {
349 if ( myGreen < aColor.myGreen )
350 return true;
351 if ( myGreen == aColor.myGreen ) {
352 if ( myBlue < aColor.myBlue )
353 return true;
354 if ( myBlue == aColor.myBlue )
355 return myAlpha < aColor.myAlpha;
356 }
357 }
358 return false;
359}
360
361
362inline
363bool
364DGtal::Color::operator>( const Color & aColor ) const
365{
366 return !this->operator<(aColor);
367}
368
369
370inline
371bool
372DGtal::Color::operator<=( const Color & aColor ) const
373{
374 return this->operator<(aColor) || this->operator==(aColor);
375}
376
377
378inline
379bool
380DGtal::Color::operator>=( const Color & aColor ) const
381{
382 return this->operator>(aColor) || this->operator==(aColor);
383}
384
385
386inline
387void
388DGtal::Color::flushPostscript( std::ostream & stream ) const
389{
390 stream << ((double)myRed/255.0) << " "
391 << ((double)myGreen/255.0) << " "
392 << ((double)myBlue/255.0) << " srgb\n";
393}
394
395
396inline
397std::string
398DGtal::Color::postscript() const
399{
400 char buffer[255];
401 secured_sprintf( buffer, 255, "%.4f %.4f %.4f", myRed/255.0, myGreen/255.0, myBlue/255.0 );
402 return buffer;
403}
404
405
406inline
407std::string
408DGtal::Color::svg() const
409{
410 char buffer[255];
411 if ( *this == DGtal::Color::None ) return "none";
412 secured_sprintf( buffer, 255, "rgb(%d,%d,%d)",myRed, myGreen, myBlue );
413 return buffer;
414}
415
416
417inline
418std::string
419DGtal::Color::svgAlpha( const char * prefix ) const
420{
421 char buffer[255];
422 if ( myAlpha == 255 || *this == DGtal::Color::None ) return "";
423 secured_sprintf( buffer, 255, " %s-opacity=\"%f\"", prefix, myAlpha/255.0f );
424 return buffer;
425}
426
427
428inline
429std::string
430DGtal::Color::tikz() const
431{
432 // see tex/generic/pgf/utilities/pgfutil-plain.def for color definitions
433 char buffer[255];
434 if ( *this == DGtal::Color::None ) return "none";
435 if ( *this == DGtal::Color::Black ) return "black";
436 if ( *this == DGtal::Color::Gray ) return "gray";
437 if ( *this == DGtal::Color::White ) return "white";
438 if ( *this == DGtal::Color::Red ) return "red";
439 if ( *this == DGtal::Color::Green ) return "green!50!black";
440 if ( *this == DGtal::Color::Lime ) return "green";
441 if ( *this == DGtal::Color::Blue ) return "blue";
442// if ( *this == DGtal::Color::Cyan ) return "cyan";
443// if ( *this == DGtal::Color::Magenta ) return "magenta";
444// if ( *this == DGtal::Color::Yellow ) return "yellow";
445 if ( *this == DGtal::Color::Silver ) return "white!75!black";
446 if ( *this == DGtal::Color::Purple ) return "purple";
447 if ( *this == DGtal::Color::Navy ) return "blue!50!black";
448// if ( *this == DGtal::Color::Aqua ) return "cyan"; // ???: Is Color::Aqua meant to be equal to Color::Cyan?
449 secured_sprintf( buffer, 255, "{rgb,255:red,%d;green,%d;blue,%d}", myRed, myGreen, myBlue );
450 return buffer;
451}
452
453
454///////////////////////////////////////////////////////////////////////////////
455// Interface - public :
456
457/**
458 * Writes/Displays the object on an output stream.
459 * @param out the output stream where the object is written.
460 */
461inline
462void
463DGtal::Color::selfDisplay ( std::ostream & out ) const
464{
465 out << "[Color] RGBA("<<(int)myRed<<","<<(int)myGreen<<","<<(int)myBlue<<","<<(int)myAlpha<<")";
466}
467
468/**
469 * Checks the validity/consistency of the object.
470 * @return 'true' if the object is valid, 'false' otherwise.
471 */
472inline
473bool
474DGtal::Color::isValid() const
475{
476 return true;
477}
478
479
480///////////////////////////////////////////////////////////////////////////////
481// Interface - Constants :
482
483inline const DGtal::Color DGtal::Color::None(0,0,0,0);
484inline const DGtal::Color DGtal::Color::Black((unsigned char)0,(unsigned char)0,(unsigned char)0);
485inline const DGtal::Color DGtal::Color::Gray((unsigned char)128,(unsigned char)128,(unsigned char)128);
486inline const DGtal::Color DGtal::Color::White((unsigned char)255,(unsigned char)255,(unsigned char)255);
487inline const DGtal::Color DGtal::Color::Red((unsigned char)255,(unsigned char)0,(unsigned char)0);
488inline const DGtal::Color DGtal::Color::Green((unsigned char)0,(unsigned char)255,(unsigned char)0);
489inline const DGtal::Color DGtal::Color::Lime((unsigned char)0,(unsigned char)255,(unsigned char)0);
490inline const DGtal::Color DGtal::Color::Blue((unsigned char)0,(unsigned char)0,(unsigned char)255);
491inline const DGtal::Color DGtal::Color::Cyan((unsigned char)0,(unsigned char)255,(unsigned char)255);
492inline const DGtal::Color DGtal::Color::Magenta((unsigned char)255,(unsigned char)0,(unsigned char)255);
493inline const DGtal::Color DGtal::Color::Yellow((unsigned char)255,(unsigned char)255,(unsigned char)0);
494inline const DGtal::Color DGtal::Color::Silver((unsigned char)190,(unsigned char)190,(unsigned char)190);
495inline const DGtal::Color DGtal::Color::Purple((unsigned char)128,(unsigned char)0,(unsigned char)128);
496inline const DGtal::Color DGtal::Color::Navy((unsigned char)0,(unsigned char)0,(unsigned char)128);
497inline const DGtal::Color DGtal::Color::Aqua((unsigned char)0,(unsigned char)255,(unsigned char)255);
498
499// //
500///////////////////////////////////////////////////////////////////////////////
501
502
503///////////////////////////////////////////////////////////////////////////////
504// Internals - private :
505
506// //
507///////////////////////////////////////////////////////////////////////////////