]> granicus.if.org Git - imagemagick/blob - Magick++/lib/Color.cpp
(no commit message)
[imagemagick] / Magick++ / lib / Color.cpp
1 // This may look like C code, but it is really -*- C++ -*-
2 //
3 // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003
4 //
5 // Color Implementation
6 //
7
8 #define MAGICKCORE_IMPLEMENTATION
9 #define MAGICK_PLUSPLUS_IMPLEMENTATION 1
10
11 #include "Magick++/Include.h"
12 #include <string>
13
14 using namespace std;
15
16 #include "Magick++/Color.h"
17 #include "Magick++/Exception.h"
18
19 //
20 // Color operator fuctions
21 //
22 int Magick::operator == ( const Magick::Color& left_,
23                           const Magick::Color& right_ )
24 {
25   return ( ( left_.isValid()      == right_.isValid() ) && 
26            ( left_.redQuantum()   == right_.redQuantum() ) &&
27            ( left_.greenQuantum() == right_.greenQuantum() ) &&
28            ( left_.blueQuantum()  == right_.blueQuantum() )
29           );
30 }
31 int Magick::operator != ( const Magick::Color& left_,
32                           const Magick::Color& right_ )
33 {
34   return ( ! (left_ == right_) );
35 }
36 int Magick::operator >  ( const Magick::Color& left_,
37                           const Magick::Color& right_ )
38 {
39   return ( !( left_ < right_ ) && ( left_ != right_ ) );
40 }
41 int Magick::operator <  ( const Magick::Color& left_,
42                           const Magick::Color& right_ )
43 {
44     if(left_.redQuantum() < right_.redQuantum()) return true;
45     if(left_.redQuantum() > right_.redQuantum()) return false;
46     if(left_.greenQuantum() < right_.greenQuantum()) return true;
47     if(left_.greenQuantum() > right_.greenQuantum()) return false;
48     if(left_.blueQuantum() < right_.blueQuantum()) return true;
49     return false;
50 }
51 int Magick::operator >= ( const Magick::Color& left_,
52                           const Magick::Color& right_ )
53 {
54   return ( ( left_ > right_ ) || ( left_ == right_ ) );
55 }
56 int Magick::operator <= ( const Magick::Color& left_,
57                           const Magick::Color& right_ )
58 {
59   return ( ( left_ < right_ ) || ( left_ == right_ ) );
60 }
61
62 //
63 // Color Implementation
64 //
65
66 // Default constructor
67 Magick::Color::Color ( void )
68   : _pixel(new PixelPacket),
69     _pixelOwn(true),
70     _isValid(false),
71     _pixelType(RGBPixel)
72 {
73   initPixel();
74 }
75
76 // Construct from RGB
77 Magick::Color::Color ( Quantum red_,
78                        Quantum green_,
79                        Quantum blue_ )
80   : _pixel(new PixelPacket),
81     _pixelOwn(true),
82     _isValid(true),
83     _pixelType(RGBPixel)
84 {
85   redQuantum   ( red_   );
86   greenQuantum ( green_ );
87   blueQuantum  ( blue_  );
88   alphaQuantum ( OpaqueOpacity );
89 }
90
91 // Construct from RGBA
92 Magick::Color::Color ( Quantum red_,
93                        Quantum green_,
94                        Quantum blue_,
95                        Quantum alpha_ )
96   : _pixel(new PixelPacket),
97     _pixelOwn(true),
98     _isValid(true),
99     _pixelType(RGBAPixel)
100 {
101   redQuantum   ( red_   );
102   greenQuantum ( green_ );
103   blueQuantum  ( blue_  );
104   alphaQuantum ( alpha_ );
105 }
106
107 // Copy constructor
108 Magick::Color::Color ( const Magick::Color & color_ )
109   : _pixel( new PixelPacket ),
110     _pixelOwn( true ),
111     _isValid( color_._isValid ),
112     _pixelType( color_._pixelType )
113 {
114   *_pixel    = *color_._pixel;
115 }
116
117 // Construct from color expressed as C++ string
118 Magick::Color::Color ( const std::string &x11color_ )
119   : _pixel(new PixelPacket),
120     _pixelOwn(true),
121     _isValid(true),
122     _pixelType(RGBPixel)
123 {
124   initPixel();
125
126   // Use operator = implementation
127   *this = x11color_;
128 }
129
130 // Construct from color expressed as C string
131 Magick::Color::Color ( const char * x11color_ )
132   : _pixel(new PixelPacket),
133     _pixelOwn(true),
134     _isValid(true),
135     _pixelType(RGBPixel)
136 {
137   initPixel();
138
139   // Use operator = implementation
140   *this = x11color_;
141 }
142
143 // Construct color via ImageMagick PixelPacket
144 Magick::Color::Color ( const PixelPacket &color_ )
145   : _pixel(new PixelPacket),
146     _pixelOwn(true),        // We allocated this pixel
147     _isValid(true),
148     _pixelType(RGBPixel)  // RGB pixel by default
149 {
150   *_pixel = color_;
151
152   if ( color_.opacity != OpaqueOpacity )
153     _pixelType = RGBAPixel;
154 }
155
156 // Protected constructor to construct with PixelPacket*
157 // Used to point Color at a pixel.
158 Magick::Color::Color ( PixelPacket* rep_, PixelType pixelType_  )
159   : _pixel(rep_),
160     _pixelOwn(false),
161     _isValid(true),
162     _pixelType(pixelType_)
163 {
164 }
165
166 // Destructor
167 Magick::Color::~Color( void )
168 {
169   if ( _pixelOwn )
170     delete _pixel;
171   _pixel=0;
172 }
173
174 // Assignment operator
175 Magick::Color& Magick::Color::operator = ( const Magick::Color& color_ )
176 {
177   // If not being set to ourself
178   if ( this != &color_ )
179     {
180       // Copy pixel value
181       *_pixel = *color_._pixel;
182
183       // Validity
184       _isValid =  color_._isValid;
185
186       // Copy pixel type
187       _pixelType = color_._pixelType;
188     }
189   return *this;
190 }
191
192 // Set color via X11 color specification string
193 const Magick::Color& Magick::Color::operator = ( const std::string &x11color_ )
194 {
195   initPixel();
196   PixelPacket target_color;
197   ExceptionInfo exception;
198   GetExceptionInfo( &exception );
199   if ( QueryColorDatabase( x11color_.c_str(), &target_color, &exception ) )
200     {
201       redQuantum( target_color.red );
202       greenQuantum( target_color.green );
203       blueQuantum( target_color.blue );
204       alphaQuantum( target_color.opacity );
205
206       if ( target_color.opacity > OpaqueOpacity )
207         _pixelType = RGBAPixel;
208       else
209         _pixelType = RGBPixel;
210     }
211   else
212     {
213       _isValid = false;
214       throwException(exception);
215     }
216   (void) DestroyExceptionInfo( &exception );
217
218   return *this;
219 }
220
221 // Set color via X11 color specification C string
222 const Magick::Color& Magick::Color::operator = ( const char * x11color_ )
223 {
224   *this = std::string(x11color_);
225   return *this;
226 }
227
228 // Return X11 color specification string
229 Magick::Color::operator std::string() const
230 {
231   if ( !isValid() )
232     return std::string("none");
233
234   char colorbuf[MaxTextExtent];
235
236   MagickPixelPacket
237     pixel;
238
239   pixel.colorspace=RGBColorspace;
240   pixel.matte=_pixelType == RGBAPixel ? MagickTrue : MagickFalse;
241   pixel.depth=MAGICKCORE_QUANTUM_DEPTH;
242   pixel.red=_pixel->red;
243   pixel.green=_pixel->green;
244   pixel.blue=_pixel->blue;
245   pixel.opacity=_pixel->opacity;
246   GetColorTuple( &pixel, MagickTrue, colorbuf );
247
248   return std::string(colorbuf);
249 }
250
251 // Set color via ImageMagick PixelPacket
252 const Magick::Color& Magick::Color::operator= ( const MagickCore::PixelPacket &color_ )
253 {
254   *_pixel = color_;
255   if ( color_.opacity != OpaqueOpacity )
256     _pixelType = RGBAPixel;
257   else
258     _pixelType = RGBPixel;
259   return *this;
260 }
261
262 // Set pixel
263 // Used to point Color at a pixel in an image
264 void Magick::Color::pixel ( PixelPacket* rep_, PixelType pixelType_ )
265 {
266   if ( _pixelOwn )
267     delete _pixel;
268   _pixel = rep_;
269   _pixelOwn = false;
270   _isValid = true;
271   _pixelType = pixelType_;
272 }
273
274 // Does object contain valid color?
275 bool Magick::Color::isValid ( void ) const
276 {
277   return( _isValid );
278 }
279 void Magick::Color::isValid ( bool valid_ )
280 {
281   if ( (valid_ && isValid()) || (!valid_ && !isValid()) )
282     return;
283
284   if ( !_pixelOwn )
285     {
286       _pixel = new PixelPacket;
287       _pixelOwn = true;
288     }
289
290   _isValid=valid_;
291
292   initPixel();
293 }
294
295 //
296 // ColorHSL Implementation
297 //
298
299 Magick::ColorHSL::ColorHSL ( double hue_,
300                              double saturation_,
301                              double luminosity_ )
302   : Color ()
303 {
304   Quantum red, green, blue;
305
306   ConvertHSLToRGB ( hue_,
307                  saturation_,
308                  luminosity_,
309                  &red,
310                  &green,
311                  &blue );
312
313   redQuantum   ( red );
314   greenQuantum ( green );
315   blueQuantum  ( blue );
316   alphaQuantum ( OpaqueOpacity );
317 }
318
319 // Null constructor
320 Magick::ColorHSL::ColorHSL ( )
321   : Color ()
322 {
323 }
324
325 // Copy constructor from base class
326 Magick::ColorHSL::ColorHSL ( const Magick::Color & color_ )
327   : Color( color_ )
328 {
329 }
330
331 // Destructor
332 Magick::ColorHSL::~ColorHSL ( )
333 {
334   // Nothing to do
335 }
336
337 void Magick::ColorHSL::hue ( double hue_ )
338 {
339   double hue_val, saturation_val, luminosity_val;
340   ConvertRGBToHSL ( redQuantum(),
341                  greenQuantum(),
342                  blueQuantum(),
343                  &hue_val,
344                  &saturation_val,
345                  &luminosity_val );
346
347   hue_val = hue_;
348
349   Quantum red, green, blue;
350   ConvertHSLToRGB ( hue_val,
351                  saturation_val,
352                  luminosity_val,
353                  &red,
354                  &green,
355                  &blue
356                  );
357
358   redQuantum   ( red );
359   greenQuantum ( green );
360   blueQuantum  ( blue );
361 }
362
363 double Magick::ColorHSL::hue ( void ) const
364 {
365   double hue_val, saturation_val, luminosity_val;
366   ConvertRGBToHSL ( redQuantum(),
367                  greenQuantum(),
368                  blueQuantum(),
369                  &hue_val,
370                  &saturation_val,
371                  &luminosity_val );
372   return hue_val;
373 }
374
375 void Magick::ColorHSL::saturation ( double saturation_ )
376 {
377   double hue_val, saturation_val, luminosity_val;
378   ConvertRGBToHSL ( redQuantum(),
379                  greenQuantum(),
380                  blueQuantum(),
381                  &hue_val,
382                  &saturation_val,
383                  &luminosity_val );
384   
385   saturation_val = saturation_;
386   
387   Quantum red, green, blue;
388   ConvertHSLToRGB ( hue_val,
389                  saturation_val,
390                  luminosity_val,
391                  &red,
392                  &green,
393                  &blue
394                  );
395
396   redQuantum   ( red );
397   greenQuantum ( green );
398   blueQuantum  ( blue );
399 }
400
401 double Magick::ColorHSL::saturation ( void ) const
402 {
403   double hue_val, saturation_val, luminosity_val;
404   ConvertRGBToHSL ( redQuantum(),
405                  greenQuantum(),
406                  blueQuantum(),
407                  &hue_val,
408                  &saturation_val,
409                  &luminosity_val );
410   return saturation_val;
411 }
412
413 void Magick::ColorHSL::luminosity ( double luminosity_ )
414 {
415   double hue_val, saturation_val, luminosity_val;
416   ConvertRGBToHSL ( redQuantum(),
417                  greenQuantum(),
418                  blueQuantum(),
419                  &hue_val,
420                  &saturation_val,
421                  &luminosity_val );
422   
423   luminosity_val = luminosity_;
424   
425   Quantum red, green, blue;
426   ConvertHSLToRGB ( hue_val,
427                  saturation_val,
428                  luminosity_val,
429                  &red,
430                  &green,
431                  &blue
432                  );
433   
434   redQuantum   ( red );
435   greenQuantum ( green );
436   blueQuantum  ( blue );
437 }
438
439 double Magick::ColorHSL::luminosity ( void ) const
440 {
441   double hue_val, saturation_val, luminosity_val;
442   ConvertRGBToHSL ( redQuantum(),
443                  greenQuantum(),
444                  blueQuantum(),
445                  &hue_val,
446                  &saturation_val,
447                  &luminosity_val );
448   return luminosity_val;
449 }
450
451 // Assignment from base class
452 Magick::ColorHSL& Magick::ColorHSL::operator = ( const Magick::Color& color_ )
453 {
454   *static_cast<Magick::Color*>(this) = color_;
455   return *this;
456 }
457
458 //
459 // ColorGray Implementation
460 //
461 Magick::ColorGray::ColorGray ( double shade_ )
462   : Color ( scaleDoubleToQuantum( shade_ ),
463             scaleDoubleToQuantum( shade_ ),
464             scaleDoubleToQuantum( shade_ ) )
465 {
466   alphaQuantum ( OpaqueOpacity );
467 }
468
469 // Null constructor
470 Magick::ColorGray::ColorGray ( void )
471   : Color ()
472 {
473 }
474
475 // Copy constructor from base class
476 Magick::ColorGray::ColorGray ( const Magick::Color & color_ )
477   : Color( color_ )
478 {
479 }
480
481 // Destructor
482 Magick::ColorGray::~ColorGray ()
483 {
484   // Nothing to do
485 }
486
487 void Magick::ColorGray::shade ( double shade_ )
488 {
489   Quantum gray = scaleDoubleToQuantum( shade_ );
490   redQuantum   ( gray );
491   greenQuantum ( gray );
492   blueQuantum  ( gray );
493 }
494
495 double Magick::ColorGray::shade ( void ) const
496 {
497   return scaleQuantumToDouble ( greenQuantum() );
498 }
499
500 // Assignment from base class
501 Magick::ColorGray& Magick::ColorGray::operator = ( const Magick::Color& color_ )
502 {
503   *static_cast<Magick::Color*>(this) = color_;
504   return *this;
505 }
506
507 //
508 // ColorMono Implementation
509 //
510 Magick::ColorMono::ColorMono ( bool mono_  )
511   : Color ( ( mono_ ? QuantumRange : 0 ),
512             ( mono_ ? QuantumRange : 0 ),
513             ( mono_ ? QuantumRange : 0 ) )
514 {
515   alphaQuantum ( OpaqueOpacity );
516 }
517
518 // Null constructor
519 Magick::ColorMono::ColorMono ( void )
520   : Color ()
521 {
522 }
523
524 // Copy constructor from base class
525 Magick::ColorMono::ColorMono ( const Magick::Color & color_ )
526   : Color( color_ )
527 {
528 }
529
530 // Destructor
531 Magick::ColorMono::~ColorMono ()
532 {
533   // Nothing to do
534 }
535
536 void Magick::ColorMono::mono ( bool mono_ )
537 {
538   redQuantum   ( mono_ ? QuantumRange : 0 );
539   greenQuantum ( mono_ ? QuantumRange : 0 );
540   blueQuantum  ( mono_ ? QuantumRange : 0 );
541 }
542
543 bool Magick::ColorMono::mono ( void ) const
544 {
545   if ( greenQuantum() )
546     return true;
547   else
548     return false;
549 }
550
551 // Assignment from base class
552 Magick::ColorMono& Magick::ColorMono::operator = ( const Magick::Color& color_ )
553 {
554   *static_cast<Magick::Color*>(this) = color_;
555   return *this;
556 }
557
558 //
559 // ColorRGB Implementation
560 //
561
562 // Construct from red, green, and blue, components
563 Magick::ColorRGB::ColorRGB ( double red_,
564                              double green_,
565                              double blue_ )
566   : Color ( scaleDoubleToQuantum(red_),
567             scaleDoubleToQuantum(green_),
568             scaleDoubleToQuantum(blue_) )
569 {
570   alphaQuantum ( OpaqueOpacity );
571 }
572 // Null constructor
573 Magick::ColorRGB::ColorRGB ( void )
574   : Color ()
575 {
576 }
577 // Copy constructor from base class
578 Magick::ColorRGB::ColorRGB ( const Magick::Color & color_ )
579   : Color( color_ )
580 {
581 }
582 // Destructor
583 Magick::ColorRGB::~ColorRGB ( void )
584 {
585   // Nothing to do
586 }
587
588 // Assignment from base class
589 Magick::ColorRGB& Magick::ColorRGB::operator = ( const Magick::Color& color_ )
590 {
591   *static_cast<Magick::Color*>(this) = color_;
592   return *this;
593 }
594
595 //
596 // ColorYUV Implementation
597 //
598
599 //           R = Y          +1.13980*V
600 //           G = Y-0.39380*U-0.58050*V
601 //           B = Y+2.02790*U
602 //
603 //         U and V, normally -0.5 through 0.5, must be normalized to the range 0
604 //         through QuantumRange.
605 //
606 //           Y =  0.29900*R+0.58700*G+0.11400*B
607 //           U = -0.14740*R-0.28950*G+0.43690*B
608 //           V =  0.61500*R-0.51500*G-0.10000*B
609 //
610 //         U and V, normally -0.5 through 0.5, are normalized to the range 0
611 //         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
612 //
613
614 // Construct from color components
615 Magick::ColorYUV::ColorYUV ( double y_,
616                              double u_,
617                              double v_ )
618   : Color ( scaleDoubleToQuantum(y_ + 1.13980 * v_ ),
619             scaleDoubleToQuantum(y_ - (0.39380 * u_) - (0.58050 * v_) ),
620             scaleDoubleToQuantum(y_ + 2.02790 * u_ ) )
621 {
622   alphaQuantum ( OpaqueOpacity );
623 }
624 // Null constructor
625 Magick::ColorYUV::ColorYUV ( void )
626   : Color ()
627 {
628 }
629 // Copy constructor from base class
630 Magick::ColorYUV::ColorYUV ( const Magick::Color & color_ )
631   : Color( color_ )
632 {
633 }
634 // Destructor
635 Magick::ColorYUV::~ColorYUV ( void )
636 {
637   // Nothing to do
638 }
639
640 void Magick::ColorYUV::u ( double u_ )
641 {
642   double V = v();
643   double Y = y();
644
645   redQuantum   ( scaleDoubleToQuantum( Y + 1.13980 * V ) );
646   greenQuantum ( scaleDoubleToQuantum( Y - (0.39380 * u_) - (0.58050 * V) ) );
647   blueQuantum  ( scaleDoubleToQuantum( Y + 2.02790 * u_ ) );
648 }
649
650 double Magick::ColorYUV::u ( void ) const
651 {
652   return scaleQuantumToDouble( (-0.14740 * redQuantum()) - (0.28950 *
653                                greenQuantum()) + (0.43690 * blueQuantum()) );
654 }
655
656 void Magick::ColorYUV::v ( double v_ )
657 {
658   double U = u();
659   double Y = y();
660
661   redQuantum   ( scaleDoubleToQuantum( Y + 1.13980 * v_ ) );
662   greenQuantum ( scaleDoubleToQuantum( Y - (0.39380 * U) - (0.58050 * v_) ) );
663   blueQuantum  ( scaleDoubleToQuantum( Y + 2.02790 * U ) );
664 }
665
666 double Magick::ColorYUV::v ( void ) const
667 {
668   return scaleQuantumToDouble((0.61500 * redQuantum()) -
669                               (0.51500 * greenQuantum()) -
670                               (0.10000 * blueQuantum()));
671 }
672
673 void Magick::ColorYUV::y ( double y_ )
674 {
675   double U = u();
676   double V = v();
677
678   redQuantum   ( scaleDoubleToQuantum( y_ + 1.13980 * V ) );
679   greenQuantum ( scaleDoubleToQuantum( y_ - (0.39380 * U) - (0.58050 * V) ) );
680   blueQuantum  ( scaleDoubleToQuantum( y_ + 2.02790 * U ) );
681 }
682
683 double Magick::ColorYUV::y ( void ) const
684 {
685   return scaleQuantumToDouble((0.29900 * redQuantum()) + 
686                               (0.58700 * greenQuantum()) +
687                               (0.11400 * blueQuantum()));
688 }
689
690 // Assignment from base class
691 Magick::ColorYUV& Magick::ColorYUV::operator = ( const Magick::Color& color_ )
692 {
693   *static_cast<Magick::Color*>(this) = color_;
694   return *this;
695 }