Color.cpp revision 067638f702a3e35c44bcc3ba9593c1e24951a781
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
19MagickPPExport int 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
28MagickPPExport int Magick::operator != (const Magick::Color &left_,
29  const Magick::Color &right_)
30{
31  return(!(left_ == right_));
32}
33
34MagickPPExport int Magick::operator > (const Magick::Color &left_,
35  const Magick::Color &right_)
36{
37  return(!(left_ < right_ ) && (left_ != right_ ));
38}
39
40MagickPPExport int 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
56MagickPPExport int Magick::operator >= (const Magick::Color &left_,
57  const Magick::Color &right_)
58{
59  return((left_ > right_) || (left_ == right_));
60}
61
62MagickPPExport int 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),
70    _isValid(false),
71    _pixelOwn(true),
72    _pixelType(RGBPixel)
73{
74  initPixel();
75}
76
77Magick::Color::Color(const Quantum red_,const Quantum green_,
78  const Quantum blue_)
79  : _pixel(new PixelInfo),
80    _isValid(true),
81    _pixelOwn(true),
82    _pixelType(RGBPixel)
83{
84  quantumRed(red_);
85  quantumGreen(green_);
86  quantumBlue(blue_);
87  quantumAlpha(OpaqueAlpha);
88}
89
90Magick::Color::Color(const Quantum red_,const Quantum green_,
91  const Quantum blue_, const Quantum alpha_)
92  : _pixel(new PixelInfo),
93    _isValid(true),
94    _pixelOwn(true),
95    _pixelType(RGBAPixel)
96{
97  quantumRed(red_);
98  quantumGreen(green_);
99  quantumBlue(blue_);
100  quantumAlpha(alpha_);
101}
102
103Magick::Color::Color(const char *color_)
104  : _pixel(new PixelInfo),
105    _isValid(true),
106    _pixelOwn(true),
107    _pixelType(RGBPixel)
108{
109  initPixel();
110
111  // Use operator = implementation
112  *this=color_;
113}
114
115Magick::Color::Color(const Magick::Color &color_)
116  : _pixel(new PixelInfo),
117    _isValid(color_._isValid),
118    _pixelOwn(true),
119    _pixelType(color_._pixelType)
120{
121  *_pixel=*color_._pixel;
122}
123
124Magick::Color::Color(const PixelInfo &color_)
125  : _pixel(new PixelInfo),
126    _isValid(true),
127    _pixelOwn(true),
128    _pixelType(RGBPixel)
129{
130  *_pixel=color_;
131
132  if (color_.alpha != OpaqueAlpha)
133    _pixelType=RGBAPixel;
134}
135
136Magick::Color::Color(const std::string &color_)
137  : _pixel(new PixelInfo),
138    _isValid(true),
139    _pixelOwn(true),
140    _pixelType(RGBPixel)
141{
142  initPixel();
143
144  // Use operator = implementation
145  *this=color_;
146}
147
148Magick::Color::~Color(void)
149{
150  if (_pixelOwn)
151    delete _pixel;
152
153  _pixel=(PixelInfo *)NULL;
154}
155
156Magick::Color& Magick::Color::operator=(const Magick::Color& color_)
157{
158  // If not being set to ourself
159  if (this != &color_)
160    {
161      // Copy pixel value
162      *_pixel=*color_._pixel;
163
164      // Validity
165      _isValid=color_._isValid;
166
167      // Copy pixel type
168      _pixelType=color_._pixelType;
169    }
170  return(*this);
171}
172
173const Magick::Color& Magick::Color::operator=(const char *color_)
174{
175  *this=std::string(color_);
176  return(*this);
177}
178
179const Magick::Color& Magick::Color::operator=(const MagickCore::PixelInfo &color_)
180{
181  *_pixel=color_;
182  if (color_.alpha != OpaqueAlpha)
183    _pixelType=RGBAPixel;
184  else
185    _pixelType=RGBPixel;
186
187  return(*this);
188}
189
190const Magick::Color& Magick::Color::operator=(const std::string &color_)
191{
192  PixelInfo
193    target_color;
194
195  initPixel();
196  GetPPException;
197  if (QueryColorCompliance(color_.c_str(),AllCompliance,&target_color,
198      exceptionInfo))
199    {
200      quantumRed(target_color.red);
201      quantumGreen(target_color.green);
202      quantumBlue(target_color.blue);
203      quantumAlpha(target_color.alpha);
204
205      if (quantumAlpha() != OpaqueAlpha)
206        _pixelType=RGBAPixel;
207      else
208         _pixelType=RGBPixel;
209    }
210  else
211    _isValid = false;
212  ThrowPPException;
213
214  return(*this);
215}
216
217Magick::Color::operator MagickCore::PixelInfo() const
218{
219  return *_pixel;
220}
221
222Magick::Color::operator std::string() const
223{
224  char
225    colorbuf[MaxTextExtent];
226
227  PixelInfo
228    pixel;
229
230  if (!isValid())
231    return std::string("none");
232
233  pixel.colorspace=RGBColorspace;
234  pixel.alpha_trait=_pixelType == RGBAPixel ? BlendPixelTrait :
235    UndefinedPixelTrait;
236  pixel.depth=MAGICKCORE_QUANTUM_DEPTH;
237  pixel.red=_pixel->red;
238  pixel.green=_pixel->green;
239  pixel.blue=_pixel->blue;
240  pixel.alpha=_pixel->alpha;
241  GetColorTuple(&pixel,MagickTrue,colorbuf);
242
243  return(std::string(colorbuf));
244}
245
246void Magick::Color::alpha(const double alpha_)
247{
248  quantumAlpha(scaleDoubleToQuantum(alpha_));
249}
250
251double Magick::Color::alpha(void) const
252{
253  return scaleQuantumToDouble(quantumAlpha());
254}
255
256bool Magick::Color::isValid(void) const
257{
258  return(_isValid);
259}
260
261void Magick::Color::isValid(bool valid_)
262{
263  if ((valid_ && isValid()) || (!valid_ && !isValid()))
264    return;
265
266  if (!_pixelOwn)
267    {
268      _pixel=new PixelInfo;
269      _pixelOwn=true;
270    }
271
272  _isValid=valid_;
273
274  initPixel();
275}
276
277void Magick::Color::quantumAlpha(const Magick::Quantum alpha_)
278{
279  _pixel->alpha=alpha_;
280  _isValid=true ;
281}
282
283Magick::Quantum Magick::Color::quantumAlpha(void) const
284{
285  return _pixel->alpha;
286}
287
288void Magick::Color::quantumBlue(const Magick::Quantum blue_)
289{
290  _pixel->blue=blue_;
291  _isValid=true;
292}
293
294Magick::Quantum Magick::Color::quantumBlue(void) const
295{
296  return _pixel->blue;
297}
298
299void Magick::Color::quantumGreen(const Magick::Quantum green_)
300{
301  _pixel->green=green_;
302  _isValid=true;
303}
304
305Magick::Quantum Magick::Color::quantumGreen(void) const
306{
307  return _pixel->green;
308}
309
310void Magick::Color::quantumRed(const Magick::Quantum red_)
311{
312  _pixel->red=red_;
313  _isValid=true;
314}
315
316Magick::Quantum Magick::Color::quantumRed(void) const
317{
318  return _pixel->red;
319}
320
321Magick::Color::Color(PixelInfo* rep_,PixelType pixelType_)
322  : _pixel(rep_),_pixelOwn(false),_isValid(true),_pixelType(pixelType_)
323{
324}
325
326void Magick::Color::pixel(PixelInfo *rep_,PixelType pixelType_)
327{
328  if (_pixelOwn)
329    delete _pixel;
330
331  _pixel=rep_;
332  _pixelOwn=false;
333  _isValid=true;
334  _pixelType=pixelType_;
335}
336
337Magick::Quantum Magick::Color::scaleDoubleToQuantum(const double double_)
338{
339  return (static_cast<Magick::Quantum>(double_*QuantumRange));
340}
341
342double Magick::Color::scaleQuantumToDouble(const Magick::Quantum quantum_)
343{
344#if (MAGICKCORE_QUANTUM_DEPTH < 32)
345  return (static_cast<double>(quantum_)/QuantumRange);
346#else
347  return (quantum_/QuantumRange);
348#endif
349}
350
351void Magick::Color::initPixel()
352{
353  _pixel->red=0;
354  _pixel->green=0;
355  _pixel->blue=0;
356  _pixel->alpha=TransparentAlpha;
357}
358
359Magick::ColorGray::ColorGray(void)
360  : Color()
361{
362}
363
364Magick::ColorGray::ColorGray(const Magick::Color & color_)
365  : Color(color_)
366{
367}
368
369Magick::ColorGray::ColorGray(double shade_)
370  : Color(scaleDoubleToQuantum(shade_),scaleDoubleToQuantum(shade_),
371          scaleDoubleToQuantum(shade_))
372{
373  quantumAlpha(OpaqueAlpha);
374}
375
376Magick::ColorGray::~ColorGray()
377{
378}
379
380void Magick::ColorGray::shade(double shade_)
381{
382  Quantum gray=scaleDoubleToQuantum(shade_);
383  quantumRed(gray);
384  quantumGreen(gray);
385  quantumBlue(gray);
386}
387
388double Magick::ColorGray::shade(void) const
389{
390  return(scaleQuantumToDouble(quantumGreen()));
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(ClampToQuantum(red));
461  quantumGreen(ClampToQuantum(green));
462  quantumBlue(ClampToQuantum(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(ClampToQuantum(red));
498  quantumGreen(ClampToQuantum(green));
499  quantumBlue(ClampToQuantum(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(ClampToQuantum(red));
535  quantumGreen(ClampToQuantum(green));
536  quantumBlue(ClampToQuantum(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((mono_ ? QuantumRange : 0),(mono_ ? QuantumRange : 0),
559          (mono_ ? QuantumRange : 0))
560{
561  quantumAlpha(OpaqueAlpha);
562}
563
564Magick::ColorMono::ColorMono(const Magick::Color &color_)
565  : Color(color_)
566{
567}
568
569Magick::ColorMono::~ColorMono()
570{
571}
572
573Magick::ColorMono& Magick::ColorMono::operator=(const Magick::Color& color_)
574{
575  *static_cast<Magick::Color*>(this)=color_;
576  return(*this);
577}
578
579void Magick::ColorMono::mono(bool mono_)
580{
581  quantumRed(mono_ ? QuantumRange : 0);
582  quantumGreen(mono_ ? QuantumRange : 0);
583  quantumBlue(mono_ ? QuantumRange : 0);
584}
585
586bool Magick::ColorMono::mono(void) const
587{
588  return(quantumGreen() == 0);
589}
590
591Magick::ColorMono::ColorMono(PixelInfo *rep_,PixelType pixelType_)
592  : Color(rep_,pixelType_)
593{
594}
595
596Magick::ColorRGB::ColorRGB(void)
597  : Color()
598{
599}
600
601Magick::ColorRGB::ColorRGB(const Magick::Color &color_)
602  : Color(color_)
603{
604}
605
606Magick::ColorRGB::ColorRGB(const double red_,const double green_,
607  const double blue_)
608  : Color(scaleDoubleToQuantum(red_),scaleDoubleToQuantum(green_),
609          scaleDoubleToQuantum(blue_))
610{
611  quantumAlpha(OpaqueAlpha);
612}
613
614Magick::ColorRGB::ColorRGB(const double red_,const double green_,
615  const double blue_,const double alpha_)
616  : Color(scaleDoubleToQuantum(red_),scaleDoubleToQuantum(green_),
617          scaleDoubleToQuantum(blue_),scaleDoubleToQuantum(alpha_))
618{
619}
620
621Magick::ColorRGB::~ColorRGB(void)
622{
623}
624
625Magick::ColorRGB& Magick::ColorRGB::operator=(const Magick::Color& color_)
626{
627  *static_cast<Magick::Color*>(this)=color_;
628  return(*this);
629}
630
631void Magick::ColorRGB::blue(const double blue_)
632{
633  quantumBlue(scaleDoubleToQuantum(blue_));
634}
635
636double Magick::ColorRGB::blue(void) const
637{
638  return scaleQuantumToDouble(quantumBlue());
639}
640
641void Magick::ColorRGB::green(const double green_)
642{
643  quantumGreen(scaleDoubleToQuantum(green_));
644}
645
646double Magick::ColorRGB::green(void) const
647{
648  return scaleQuantumToDouble(quantumGreen());
649}
650
651void Magick::ColorRGB::red(const double red_)
652{
653  quantumRed(scaleDoubleToQuantum(red_));
654}
655
656double Magick::ColorRGB::red(void) const
657{
658  return scaleQuantumToDouble(quantumRed());
659}
660
661Magick::ColorRGB::ColorRGB(PixelInfo *rep_,PixelType pixelType_)
662  : Color(rep_,pixelType_)
663{
664}
665
666Magick::ColorYUV::ColorYUV(void)
667  : Color()
668{
669}
670
671Magick::ColorYUV::ColorYUV(const Magick::Color &color_)
672  : Color(color_)
673{
674}
675
676Magick::ColorYUV::ColorYUV(const double y_,const double u_,const double v_)
677  : Color()
678{
679  convert(y_, u_, v_);
680  quantumAlpha(OpaqueAlpha);
681}
682
683Magick::ColorYUV::~ColorYUV(void)
684{
685}
686
687Magick::ColorYUV& Magick::ColorYUV::operator=(const Magick::Color &color_)
688{
689  *static_cast<Magick::Color*>(this)=color_;
690  return(*this);
691}
692
693void Magick::ColorYUV::u(const double u_)
694{
695  convert(y(), u_, v());
696}
697
698double Magick::ColorYUV::u(void) const
699{
700  return scaleQuantumToDouble((-0.14740 * quantumRed()) - (0.28950 *
701    quantumGreen()) + (0.43690 * quantumBlue()));
702}
703
704void Magick::ColorYUV::v(const double v_)
705{
706  convert(y(), u(), v_);
707}
708
709double Magick::ColorYUV::v(void) const
710{
711  return scaleQuantumToDouble((0.61500 * quantumRed()) - (0.51500 *
712    quantumGreen()) - (0.10000 * quantumBlue()));
713}
714
715void Magick::ColorYUV::y(const double y_)
716{
717  convert(y_, u(), v());
718}
719
720double Magick::ColorYUV::y ( void ) const
721{
722  return scaleQuantumToDouble((0.29900 * quantumRed()) + (0.58700 *
723    quantumGreen()) + (0.11400 * quantumBlue()));
724}
725
726void Magick::ColorYUV::convert(const double y_,const double u_,const double v_)
727{
728  quantumRed(scaleDoubleToQuantum(y_ + 1.13980 * v_));
729  quantumGreen(scaleDoubleToQuantum(y_ - (0.39380 * u_) - (0.58050 * v_)));
730  quantumBlue(scaleDoubleToQuantum(y_ + 2.02790 * u_));
731}
732
733Magick::ColorYUV::ColorYUV(PixelInfo *rep_,PixelType pixelType_)
734  : Color(rep_,pixelType_)
735{
736}
737