]> granicus.if.org Git - imagemagick/blob - Magick++/lib/Color.cpp
Changed order of private members.
[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 PixelInfo),
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 PixelInfo),
81     _pixelOwn(true),
82     _isValid(true),
83     _pixelType(RGBPixel)
84 {
85   redQuantum   ( red_   );
86   greenQuantum ( green_ );
87   blueQuantum  ( blue_  );
88   alphaQuantum ( OpaqueAlpha );
89 }
90
91 // Construct from RGBA
92 Magick::Color::Color ( Quantum red_,
93                        Quantum green_,
94                        Quantum blue_,
95                        Quantum alpha_ )
96   : _pixel(new PixelInfo),
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 PixelInfo ),
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 PixelInfo),
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 PixelInfo),
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 PixelInfo
144 Magick::Color::Color ( const PixelInfo &color_ )
145   : _pixel(new PixelInfo),
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_.alpha != OpaqueAlpha )
153     _pixelType = RGBAPixel;
154 }
155
156 // Protected constructor to construct with PixelInfo*
157 // Used to point Color at a pixel.
158 Magick::Color::Color ( PixelInfo* 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   PixelInfo target_color;
197   ExceptionInfo exception;
198   GetExceptionInfo( &exception );
199   if ( QueryColorCompliance( x11color_.c_str(), AllCompliance, &target_color, &exception ) )
200     {
201       redQuantum( ClampToQuantum( target_color.red ) );
202       greenQuantum( ClampToQuantum( target_color.green ) );
203       blueQuantum( ClampToQuantum( target_color.blue ) );
204       alphaQuantum( ClampToQuantum( target_color.alpha ) );
205
206       if ( target_color.alpha != OpaqueAlpha )
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   PixelInfo
237     pixel;
238
239   pixel.colorspace=RGBColorspace;
240   pixel.alpha_trait=_pixelType == RGBAPixel ? BlendPixelTrait :
241     UndefinedPixelTrait;
242   pixel.depth=MAGICKCORE_QUANTUM_DEPTH;
243   pixel.red=_pixel->red;
244   pixel.green=_pixel->green;
245   pixel.blue=_pixel->blue;
246   pixel.alpha=_pixel->alpha;
247   GetColorTuple( &pixel, MagickTrue, colorbuf );
248
249   return std::string(colorbuf);
250 }
251
252 // Set color via ImageMagick PixelInfo
253 const Magick::Color& Magick::Color::operator= ( const MagickCore::PixelInfo &color_ )
254 {
255   *_pixel = color_;
256   if ( color_.alpha != OpaqueAlpha )
257     _pixelType = RGBAPixel;
258   else
259     _pixelType = RGBPixel;
260   return *this;
261 }
262
263 // Set pixel
264 // Used to point Color at a pixel in an image
265 void Magick::Color::pixel ( PixelInfo* rep_, PixelType pixelType_ )
266 {
267   if ( _pixelOwn )
268     delete _pixel;
269   _pixel = rep_;
270   _pixelOwn = false;
271   _isValid = true;
272   _pixelType = pixelType_;
273 }
274
275 // Does object contain valid color?
276 bool Magick::Color::isValid ( void ) const
277 {
278   return( _isValid );
279 }
280 void Magick::Color::isValid ( bool valid_ )
281 {
282   if ( (valid_ && isValid()) || (!valid_ && !isValid()) )
283     return;
284
285   if ( !_pixelOwn )
286     {
287       _pixel = new PixelInfo;
288       _pixelOwn = true;
289     }
290
291   _isValid=valid_;
292
293   initPixel();
294 }
295
296 //
297 // ColorHSL Implementation
298 //
299
300 Magick::ColorHSL::ColorHSL ( double hue_,
301                              double saturation_,
302                              double luminosity_ )
303   : Color ()
304 {
305   double red, green, blue;
306
307   ConvertHSLToRGB ( hue_,
308                  saturation_,
309                  luminosity_,
310                  &red,
311                  &green,
312                  &blue );
313
314   redQuantum   ( ClampToQuantum( red ) );
315   greenQuantum ( ClampToQuantum( green ) );
316   blueQuantum  ( ClampToQuantum( blue ) );
317   alphaQuantum ( OpaqueAlpha );
318 }
319
320 // Null constructor
321 Magick::ColorHSL::ColorHSL ( )
322   : Color ()
323 {
324 }
325
326 // Copy constructor from base class
327 Magick::ColorHSL::ColorHSL ( const Magick::Color & color_ )
328   : Color( color_ )
329 {
330 }
331
332 // Destructor
333 Magick::ColorHSL::~ColorHSL ( )
334 {
335   // Nothing to do
336 }
337
338 void Magick::ColorHSL::hue ( double hue_ )
339 {
340   double hue_val, saturation_val, luminosity_val;
341   ConvertRGBToHSL ( redQuantum(),
342                  greenQuantum(),
343                  blueQuantum(),
344                  &hue_val,
345                  &saturation_val,
346                  &luminosity_val );
347
348   hue_val = hue_;
349
350   double red, green, blue;
351   ConvertHSLToRGB ( hue_val,
352                  saturation_val,
353                  luminosity_val,
354                  &red,
355                  &green,
356                  &blue
357                  );
358
359   redQuantum   ( ClampToQuantum( red ) );
360   greenQuantum ( ClampToQuantum( green ) );
361   blueQuantum  ( ClampToQuantum( blue ) );
362 }
363
364 double Magick::ColorHSL::hue ( void ) const
365 {
366   double hue_val, saturation_val, luminosity_val;
367   ConvertRGBToHSL ( redQuantum(),
368                  greenQuantum(),
369                  blueQuantum(),
370                  &hue_val,
371                  &saturation_val,
372                  &luminosity_val );
373   return hue_val;
374 }
375
376 void Magick::ColorHSL::saturation ( double saturation_ )
377 {
378   double hue_val, saturation_val, luminosity_val;
379   ConvertRGBToHSL ( redQuantum(),
380                  greenQuantum(),
381                  blueQuantum(),
382                  &hue_val,
383                  &saturation_val,
384                  &luminosity_val );
385   
386   saturation_val = saturation_;
387   
388   double red, green, blue;
389   ConvertHSLToRGB ( hue_val,
390                  saturation_val,
391                  luminosity_val,
392                  &red,
393                  &green,
394                  &blue
395                  );
396
397   redQuantum   ( ClampToQuantum( red ) );
398   greenQuantum ( ClampToQuantum( green ) );
399   blueQuantum  ( ClampToQuantum( blue ) );
400 }
401
402 double Magick::ColorHSL::saturation ( void ) const
403 {
404   double hue_val, saturation_val, luminosity_val;
405   ConvertRGBToHSL ( redQuantum(),
406                  greenQuantum(),
407                  blueQuantum(),
408                  &hue_val,
409                  &saturation_val,
410                  &luminosity_val );
411   return saturation_val;
412 }
413
414 void Magick::ColorHSL::luminosity ( double luminosity_ )
415 {
416   double hue_val, saturation_val, luminosity_val;
417   ConvertRGBToHSL ( redQuantum(),
418                  greenQuantum(),
419                  blueQuantum(),
420                  &hue_val,
421                  &saturation_val,
422                  &luminosity_val );
423   
424   luminosity_val = luminosity_;
425   
426   double red, green, blue;
427   ConvertHSLToRGB ( hue_val,
428                  saturation_val,
429                  luminosity_val,
430                  &red,
431                  &green,
432                  &blue
433                  );
434   
435   redQuantum   ( ClampToQuantum( red ) );
436   greenQuantum ( ClampToQuantum( green ) );
437   blueQuantum  ( ClampToQuantum( blue ) );
438 }
439
440 double Magick::ColorHSL::luminosity ( void ) const
441 {
442   double hue_val, saturation_val, luminosity_val;
443   ConvertRGBToHSL ( redQuantum(),
444                  greenQuantum(),
445                  blueQuantum(),
446                  &hue_val,
447                  &saturation_val,
448                  &luminosity_val );
449   return luminosity_val;
450 }
451
452 // Assignment from base class
453 Magick::ColorHSL& Magick::ColorHSL::operator = ( const Magick::Color& color_ )
454 {
455   *static_cast<Magick::Color*>(this) = color_;
456   return *this;
457 }
458
459 //
460 // ColorGray Implementation
461 //
462 Magick::ColorGray::ColorGray ( double shade_ )
463   : Color ( scaleDoubleToQuantum( shade_ ),
464             scaleDoubleToQuantum( shade_ ),
465             scaleDoubleToQuantum( shade_ ) )
466 {
467   alphaQuantum ( OpaqueAlpha );
468 }
469
470 // Null constructor
471 Magick::ColorGray::ColorGray ( void )
472   : Color ()
473 {
474 }
475
476 // Copy constructor from base class
477 Magick::ColorGray::ColorGray ( const Magick::Color & color_ )
478   : Color( color_ )
479 {
480 }
481
482 // Destructor
483 Magick::ColorGray::~ColorGray ()
484 {
485   // Nothing to do
486 }
487
488 void Magick::ColorGray::shade ( double shade_ )
489 {
490   Quantum gray = scaleDoubleToQuantum( shade_ );
491   redQuantum   ( gray );
492   greenQuantum ( gray );
493   blueQuantum  ( gray );
494 }
495
496 double Magick::ColorGray::shade ( void ) const
497 {
498   return scaleQuantumToDouble ( greenQuantum() );
499 }
500
501 // Assignment from base class
502 Magick::ColorGray& Magick::ColorGray::operator = ( const Magick::Color& color_ )
503 {
504   *static_cast<Magick::Color*>(this) = color_;
505   return *this;
506 }
507
508 //
509 // ColorMono Implementation
510 //
511 Magick::ColorMono::ColorMono ( bool mono_  )
512   : Color ( ( mono_ ? QuantumRange : 0 ),
513             ( mono_ ? QuantumRange : 0 ),
514             ( mono_ ? QuantumRange : 0 ) )
515 {
516   alphaQuantum ( OpaqueAlpha );
517 }
518
519 // Null constructor
520 Magick::ColorMono::ColorMono ( void )
521   : Color ()
522 {
523 }
524
525 // Copy constructor from base class
526 Magick::ColorMono::ColorMono ( const Magick::Color & color_ )
527   : Color( color_ )
528 {
529 }
530
531 // Destructor
532 Magick::ColorMono::~ColorMono ()
533 {
534   // Nothing to do
535 }
536
537 void Magick::ColorMono::mono ( bool mono_ )
538 {
539   redQuantum   ( mono_ ? QuantumRange : 0 );
540   greenQuantum ( mono_ ? QuantumRange : 0 );
541   blueQuantum  ( mono_ ? QuantumRange : 0 );
542 }
543
544 bool Magick::ColorMono::mono ( void ) const
545 {
546   if ( greenQuantum() )
547     return true;
548   else
549     return false;
550 }
551
552 // Assignment from base class
553 Magick::ColorMono& Magick::ColorMono::operator = ( const Magick::Color& color_ )
554 {
555   *static_cast<Magick::Color*>(this) = color_;
556   return *this;
557 }
558
559 //
560 // ColorRGB Implementation
561 //
562
563 // Construct from red, green, and blue, components
564 Magick::ColorRGB::ColorRGB ( double red_,
565                              double green_,
566                              double blue_ )
567   : Color ( scaleDoubleToQuantum(red_),
568             scaleDoubleToQuantum(green_),
569             scaleDoubleToQuantum(blue_) )
570 {
571   alphaQuantum ( OpaqueAlpha );
572 }
573 // Null constructor
574 Magick::ColorRGB::ColorRGB ( void )
575   : Color ()
576 {
577 }
578 // Copy constructor from base class
579 Magick::ColorRGB::ColorRGB ( const Magick::Color & color_ )
580   : Color( color_ )
581 {
582 }
583 // Destructor
584 Magick::ColorRGB::~ColorRGB ( void )
585 {
586   // Nothing to do
587 }
588
589 // Assignment from base class
590 Magick::ColorRGB& Magick::ColorRGB::operator = ( const Magick::Color& color_ )
591 {
592   *static_cast<Magick::Color*>(this) = color_;
593   return *this;
594 }
595
596 //
597 // ColorYUV Implementation
598 //
599
600 //           R = Y          +1.13980*V
601 //           G = Y-0.39380*U-0.58050*V
602 //           B = Y+2.02790*U
603 //
604 //         U and V, normally -0.5 through 0.5, must be normalized to the range 0
605 //         through QuantumRange.
606 //
607 //           Y =  0.29900*R+0.58700*G+0.11400*B
608 //           U = -0.14740*R-0.28950*G+0.43690*B
609 //           V =  0.61500*R-0.51500*G-0.10000*B
610 //
611 //         U and V, normally -0.5 through 0.5, are normalized to the range 0
612 //         through QuantumRange.  Note that U = 0.493*(B-Y), V = 0.877*(R-Y).
613 //
614
615 // Construct from color components
616 Magick::ColorYUV::ColorYUV ( double y_,
617                              double u_,
618                              double v_ )
619   : Color ( scaleDoubleToQuantum(y_ + 1.13980 * v_ ),
620             scaleDoubleToQuantum(y_ - (0.39380 * u_) - (0.58050 * v_) ),
621             scaleDoubleToQuantum(y_ + 2.02790 * u_ ) )
622 {
623   alphaQuantum ( OpaqueAlpha );
624 }
625 // Null constructor
626 Magick::ColorYUV::ColorYUV ( void )
627   : Color ()
628 {
629 }
630 // Copy constructor from base class
631 Magick::ColorYUV::ColorYUV ( const Magick::Color & color_ )
632   : Color( color_ )
633 {
634 }
635 // Destructor
636 Magick::ColorYUV::~ColorYUV ( void )
637 {
638   // Nothing to do
639 }
640
641 void Magick::ColorYUV::u ( double u_ )
642 {
643   double V = v();
644   double Y = y();
645
646   redQuantum   ( scaleDoubleToQuantum( Y + 1.13980 * V ) );
647   greenQuantum ( scaleDoubleToQuantum( Y - (0.39380 * u_) - (0.58050 * V) ) );
648   blueQuantum  ( scaleDoubleToQuantum( Y + 2.02790 * u_ ) );
649 }
650
651 double Magick::ColorYUV::u ( void ) const
652 {
653   return scaleQuantumToDouble( (-0.14740 * redQuantum()) - (0.28950 *
654                                greenQuantum()) + (0.43690 * blueQuantum()) );
655 }
656
657 void Magick::ColorYUV::v ( double v_ )
658 {
659   double U = u();
660   double Y = y();
661
662   redQuantum   ( scaleDoubleToQuantum( Y + 1.13980 * v_ ) );
663   greenQuantum ( scaleDoubleToQuantum( Y - (0.39380 * U) - (0.58050 * v_) ) );
664   blueQuantum  ( scaleDoubleToQuantum( Y + 2.02790 * U ) );
665 }
666
667 double Magick::ColorYUV::v ( void ) const
668 {
669   return scaleQuantumToDouble((0.61500 * redQuantum()) -
670                               (0.51500 * greenQuantum()) -
671                               (0.10000 * blueQuantum()));
672 }
673
674 void Magick::ColorYUV::y ( double y_ )
675 {
676   double U = u();
677   double V = v();
678
679   redQuantum   ( scaleDoubleToQuantum( y_ + 1.13980 * V ) );
680   greenQuantum ( scaleDoubleToQuantum( y_ - (0.39380 * U) - (0.58050 * V) ) );
681   blueQuantum  ( scaleDoubleToQuantum( y_ + 2.02790 * U ) );
682 }
683
684 double Magick::ColorYUV::y ( void ) const
685 {
686   return scaleQuantumToDouble((0.29900 * redQuantum()) + 
687                               (0.58700 * greenQuantum()) +
688                               (0.11400 * blueQuantum()));
689 }
690
691 // Assignment from base class
692 Magick::ColorYUV& Magick::ColorYUV::operator = ( const Magick::Color& color_ )
693 {
694   *static_cast<Magick::Color*>(this) = color_;
695   return *this;
696 }