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