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