| // This may look like C code, but it is really -*- C++ -*- |
| // |
| // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003 |
| // |
| // Color Implementation |
| // |
| |
| #define MAGICKCORE_IMPLEMENTATION |
| #define MAGICK_PLUSPLUS_IMPLEMENTATION 1 |
| |
| #include "Magick++/Include.h" |
| #include <string> |
| |
| using namespace std; |
| |
| #include "Magick++/Color.h" |
| #include "Magick++/Exception.h" |
| |
| // |
| // Color operator fuctions |
| // |
| int Magick::operator == ( const Magick::Color& left_, |
| const Magick::Color& right_ ) |
| { |
| return ( ( left_.isValid() == right_.isValid() ) && |
| ( left_.redQuantum() == right_.redQuantum() ) && |
| ( left_.greenQuantum() == right_.greenQuantum() ) && |
| ( left_.blueQuantum() == right_.blueQuantum() ) |
| ); |
| } |
| int Magick::operator != ( const Magick::Color& left_, |
| const Magick::Color& right_ ) |
| { |
| return ( ! (left_ == right_) ); |
| } |
| int Magick::operator > ( const Magick::Color& left_, |
| const Magick::Color& right_ ) |
| { |
| return ( !( left_ < right_ ) && ( left_ != right_ ) ); |
| } |
| int Magick::operator < ( const Magick::Color& left_, |
| const Magick::Color& right_ ) |
| { |
| if(left_.redQuantum() < right_.redQuantum()) return true; |
| if(left_.redQuantum() > right_.redQuantum()) return false; |
| if(left_.greenQuantum() < right_.greenQuantum()) return true; |
| if(left_.greenQuantum() > right_.greenQuantum()) return false; |
| if(left_.blueQuantum() < right_.blueQuantum()) return true; |
| return false; |
| } |
| int Magick::operator >= ( const Magick::Color& left_, |
| const Magick::Color& right_ ) |
| { |
| return ( ( left_ > right_ ) || ( left_ == right_ ) ); |
| } |
| int Magick::operator <= ( const Magick::Color& left_, |
| const Magick::Color& right_ ) |
| { |
| return ( ( left_ < right_ ) || ( left_ == right_ ) ); |
| } |
| |
| // |
| // Color Implementation |
| // |
| |
| // Default constructor |
| Magick::Color::Color ( void ) |
| : _pixel(new PixelInfo), |
| _pixelOwn(true), |
| _isValid(false), |
| _pixelType(RGBPixel) |
| { |
| initPixel(); |
| } |
| |
| // Construct from RGB |
| Magick::Color::Color ( Quantum red_, |
| Quantum green_, |
| Quantum blue_ ) |
| : _pixel(new PixelInfo), |
| _pixelOwn(true), |
| _isValid(true), |
| _pixelType(RGBPixel) |
| { |
| redQuantum ( red_ ); |
| greenQuantum ( green_ ); |
| blueQuantum ( blue_ ); |
| alphaQuantum ( OpaqueAlpha ); |
| } |
| |
| // Construct from RGBA |
| Magick::Color::Color ( Quantum red_, |
| Quantum green_, |
| Quantum blue_, |
| Quantum alpha_ ) |
| : _pixel(new PixelInfo), |
| _pixelOwn(true), |
| _isValid(true), |
| _pixelType(RGBAPixel) |
| { |
| redQuantum ( red_ ); |
| greenQuantum ( green_ ); |
| blueQuantum ( blue_ ); |
| alphaQuantum ( alpha_ ); |
| } |
| |
| // Copy constructor |
| Magick::Color::Color ( const Magick::Color & color_ ) |
| : _pixel( new PixelInfo ), |
| _pixelOwn( true ), |
| _isValid( color_._isValid ), |
| _pixelType( color_._pixelType ) |
| { |
| *_pixel = *color_._pixel; |
| } |
| |
| // Construct from color expressed as C++ string |
| Magick::Color::Color ( const std::string &x11color_ ) |
| : _pixel(new PixelInfo), |
| _pixelOwn(true), |
| _isValid(true), |
| _pixelType(RGBPixel) |
| { |
| initPixel(); |
| |
| // Use operator = implementation |
| *this = x11color_; |
| } |
| |
| // Construct from color expressed as C string |
| Magick::Color::Color ( const char * x11color_ ) |
| : _pixel(new PixelInfo), |
| _pixelOwn(true), |
| _isValid(true), |
| _pixelType(RGBPixel) |
| { |
| initPixel(); |
| |
| // Use operator = implementation |
| *this = x11color_; |
| } |
| |
| // Construct color via ImageMagick PixelInfo |
| Magick::Color::Color ( const PixelInfo &color_ ) |
| : _pixel(new PixelInfo), |
| _pixelOwn(true), // We allocated this pixel |
| _isValid(true), |
| _pixelType(RGBPixel) // RGB pixel by default |
| { |
| *_pixel = color_; |
| |
| if ( color_.alpha != OpaqueAlpha ) |
| _pixelType = RGBAPixel; |
| } |
| |
| // Protected constructor to construct with PixelInfo* |
| // Used to point Color at a pixel. |
| Magick::Color::Color ( PixelInfo* rep_, PixelType pixelType_ ) |
| : _pixel(rep_), |
| _pixelOwn(false), |
| _isValid(true), |
| _pixelType(pixelType_) |
| { |
| } |
| |
| // Destructor |
| Magick::Color::~Color( void ) |
| { |
| if ( _pixelOwn ) |
| delete _pixel; |
| _pixel=0; |
| } |
| |
| // Assignment operator |
| Magick::Color& Magick::Color::operator = ( const Magick::Color& color_ ) |
| { |
| // If not being set to ourself |
| if ( this != &color_ ) |
| { |
| // Copy pixel value |
| *_pixel = *color_._pixel; |
| |
| // Validity |
| _isValid = color_._isValid; |
| |
| // Copy pixel type |
| _pixelType = color_._pixelType; |
| } |
| return *this; |
| } |
| |
| // Set color via X11 color specification string |
| const Magick::Color& Magick::Color::operator = ( const std::string &x11color_ ) |
| { |
| initPixel(); |
| PixelInfo target_color; |
| ExceptionInfo exception; |
| GetExceptionInfo( &exception ); |
| if ( QueryColorCompliance( x11color_.c_str(), AllCompliance, &target_color, &exception ) ) |
| { |
| redQuantum( ClampToQuantum( target_color.red ) ); |
| greenQuantum( ClampToQuantum( target_color.green ) ); |
| blueQuantum( ClampToQuantum( target_color.blue ) ); |
| alphaQuantum( ClampToQuantum( target_color.alpha ) ); |
| |
| if ( target_color.alpha != OpaqueAlpha ) |
| _pixelType = RGBAPixel; |
| else |
| _pixelType = RGBPixel; |
| } |
| else |
| { |
| _isValid = false; |
| throwException(exception); |
| } |
| (void) DestroyExceptionInfo( &exception ); |
| |
| return *this; |
| } |
| |
| // Set color via X11 color specification C string |
| const Magick::Color& Magick::Color::operator = ( const char * x11color_ ) |
| { |
| *this = std::string(x11color_); |
| return *this; |
| } |
| |
| // Return X11 color specification string |
| Magick::Color::operator std::string() const |
| { |
| if ( !isValid() ) |
| return std::string("none"); |
| |
| char colorbuf[MaxTextExtent]; |
| |
| PixelInfo |
| pixel; |
| |
| pixel.colorspace=RGBColorspace; |
| pixel.alpha_trait=_pixelType == RGBAPixel ? BlendPixelTrait : |
| UndefinedPixelTrait; |
| pixel.depth=MAGICKCORE_QUANTUM_DEPTH; |
| pixel.red=_pixel->red; |
| pixel.green=_pixel->green; |
| pixel.blue=_pixel->blue; |
| pixel.alpha=_pixel->alpha; |
| GetColorTuple( &pixel, MagickTrue, colorbuf ); |
| |
| return std::string(colorbuf); |
| } |
| |
| // Set color via ImageMagick PixelInfo |
| const Magick::Color& Magick::Color::operator= ( const MagickCore::PixelInfo &color_ ) |
| { |
| *_pixel = color_; |
| if ( color_.alpha != OpaqueAlpha ) |
| _pixelType = RGBAPixel; |
| else |
| _pixelType = RGBPixel; |
| return *this; |
| } |
| |
| // Set pixel |
| // Used to point Color at a pixel in an image |
| void Magick::Color::pixel ( PixelInfo* rep_, PixelType pixelType_ ) |
| { |
| if ( _pixelOwn ) |
| delete _pixel; |
| _pixel = rep_; |
| _pixelOwn = false; |
| _isValid = true; |
| _pixelType = pixelType_; |
| } |
| |
| // Does object contain valid color? |
| bool Magick::Color::isValid ( void ) const |
| { |
| return( _isValid ); |
| } |
| void Magick::Color::isValid ( bool valid_ ) |
| { |
| if ( (valid_ && isValid()) || (!valid_ && !isValid()) ) |
| return; |
| |
| if ( !_pixelOwn ) |
| { |
| _pixel = new PixelInfo; |
| _pixelOwn = true; |
| } |
| |
| _isValid=valid_; |
| |
| initPixel(); |
| } |
| |
| // |
| // ColorHSL Implementation |
| // |
| |
| Magick::ColorHSL::ColorHSL ( double hue_, |
| double saturation_, |
| double luminosity_ ) |
| : Color () |
| { |
| double red, green, blue; |
| |
| ConvertHSLToRGB ( hue_, |
| saturation_, |
| luminosity_, |
| &red, |
| &green, |
| &blue ); |
| |
| redQuantum ( ClampToQuantum( red ) ); |
| greenQuantum ( ClampToQuantum( green ) ); |
| blueQuantum ( ClampToQuantum( blue ) ); |
| alphaQuantum ( OpaqueAlpha ); |
| } |
| |
| // Null constructor |
| Magick::ColorHSL::ColorHSL ( ) |
| : Color () |
| { |
| } |
| |
| // Copy constructor from base class |
| Magick::ColorHSL::ColorHSL ( const Magick::Color & color_ ) |
| : Color( color_ ) |
| { |
| } |
| |
| // Destructor |
| Magick::ColorHSL::~ColorHSL ( ) |
| { |
| // Nothing to do |
| } |
| |
| void Magick::ColorHSL::hue ( double hue_ ) |
| { |
| double hue_val, saturation_val, luminosity_val; |
| ConvertRGBToHSL ( redQuantum(), |
| greenQuantum(), |
| blueQuantum(), |
| &hue_val, |
| &saturation_val, |
| &luminosity_val ); |
| |
| hue_val = hue_; |
| |
| double red, green, blue; |
| ConvertHSLToRGB ( hue_val, |
| saturation_val, |
| luminosity_val, |
| &red, |
| &green, |
| &blue |
| ); |
| |
| redQuantum ( ClampToQuantum( red ) ); |
| greenQuantum ( ClampToQuantum( green ) ); |
| blueQuantum ( ClampToQuantum( blue ) ); |
| } |
| |
| double Magick::ColorHSL::hue ( void ) const |
| { |
| double hue_val, saturation_val, luminosity_val; |
| ConvertRGBToHSL ( redQuantum(), |
| greenQuantum(), |
| blueQuantum(), |
| &hue_val, |
| &saturation_val, |
| &luminosity_val ); |
| return hue_val; |
| } |
| |
| void Magick::ColorHSL::saturation ( double saturation_ ) |
| { |
| double hue_val, saturation_val, luminosity_val; |
| ConvertRGBToHSL ( redQuantum(), |
| greenQuantum(), |
| blueQuantum(), |
| &hue_val, |
| &saturation_val, |
| &luminosity_val ); |
| |
| saturation_val = saturation_; |
| |
| double red, green, blue; |
| ConvertHSLToRGB ( hue_val, |
| saturation_val, |
| luminosity_val, |
| &red, |
| &green, |
| &blue |
| ); |
| |
| redQuantum ( ClampToQuantum( red ) ); |
| greenQuantum ( ClampToQuantum( green ) ); |
| blueQuantum ( ClampToQuantum( blue ) ); |
| } |
| |
| double Magick::ColorHSL::saturation ( void ) const |
| { |
| double hue_val, saturation_val, luminosity_val; |
| ConvertRGBToHSL ( redQuantum(), |
| greenQuantum(), |
| blueQuantum(), |
| &hue_val, |
| &saturation_val, |
| &luminosity_val ); |
| return saturation_val; |
| } |
| |
| void Magick::ColorHSL::luminosity ( double luminosity_ ) |
| { |
| double hue_val, saturation_val, luminosity_val; |
| ConvertRGBToHSL ( redQuantum(), |
| greenQuantum(), |
| blueQuantum(), |
| &hue_val, |
| &saturation_val, |
| &luminosity_val ); |
| |
| luminosity_val = luminosity_; |
| |
| double red, green, blue; |
| ConvertHSLToRGB ( hue_val, |
| saturation_val, |
| luminosity_val, |
| &red, |
| &green, |
| &blue |
| ); |
| |
| redQuantum ( ClampToQuantum( red ) ); |
| greenQuantum ( ClampToQuantum( green ) ); |
| blueQuantum ( ClampToQuantum( blue ) ); |
| } |
| |
| double Magick::ColorHSL::luminosity ( void ) const |
| { |
| double hue_val, saturation_val, luminosity_val; |
| ConvertRGBToHSL ( redQuantum(), |
| greenQuantum(), |
| blueQuantum(), |
| &hue_val, |
| &saturation_val, |
| &luminosity_val ); |
| return luminosity_val; |
| } |
| |
| // Assignment from base class |
| Magick::ColorHSL& Magick::ColorHSL::operator = ( const Magick::Color& color_ ) |
| { |
| *static_cast<Magick::Color*>(this) = color_; |
| return *this; |
| } |
| |
| // |
| // ColorGray Implementation |
| // |
| Magick::ColorGray::ColorGray ( double shade_ ) |
| : Color ( scaleDoubleToQuantum( shade_ ), |
| scaleDoubleToQuantum( shade_ ), |
| scaleDoubleToQuantum( shade_ ) ) |
| { |
| alphaQuantum ( OpaqueAlpha ); |
| } |
| |
| // Null constructor |
| Magick::ColorGray::ColorGray ( void ) |
| : Color () |
| { |
| } |
| |
| // Copy constructor from base class |
| Magick::ColorGray::ColorGray ( const Magick::Color & color_ ) |
| : Color( color_ ) |
| { |
| } |
| |
| // Destructor |
| Magick::ColorGray::~ColorGray () |
| { |
| // Nothing to do |
| } |
| |
| void Magick::ColorGray::shade ( double shade_ ) |
| { |
| Quantum gray = scaleDoubleToQuantum( shade_ ); |
| redQuantum ( gray ); |
| greenQuantum ( gray ); |
| blueQuantum ( gray ); |
| } |
| |
| double Magick::ColorGray::shade ( void ) const |
| { |
| return scaleQuantumToDouble ( greenQuantum() ); |
| } |
| |
| // Assignment from base class |
| Magick::ColorGray& Magick::ColorGray::operator = ( const Magick::Color& color_ ) |
| { |
| *static_cast<Magick::Color*>(this) = color_; |
| return *this; |
| } |
| |
| // |
| // ColorMono Implementation |
| // |
| Magick::ColorMono::ColorMono ( bool mono_ ) |
| : Color ( ( mono_ ? QuantumRange : 0 ), |
| ( mono_ ? QuantumRange : 0 ), |
| ( mono_ ? QuantumRange : 0 ) ) |
| { |
| alphaQuantum ( OpaqueAlpha ); |
| } |
| |
| // Null constructor |
| Magick::ColorMono::ColorMono ( void ) |
| : Color () |
| { |
| } |
| |
| // Copy constructor from base class |
| Magick::ColorMono::ColorMono ( const Magick::Color & color_ ) |
| : Color( color_ ) |
| { |
| } |
| |
| // Destructor |
| Magick::ColorMono::~ColorMono () |
| { |
| // Nothing to do |
| } |
| |
| void Magick::ColorMono::mono ( bool mono_ ) |
| { |
| redQuantum ( mono_ ? QuantumRange : 0 ); |
| greenQuantum ( mono_ ? QuantumRange : 0 ); |
| blueQuantum ( mono_ ? QuantumRange : 0 ); |
| } |
| |
| bool Magick::ColorMono::mono ( void ) const |
| { |
| if ( greenQuantum() ) |
| return true; |
| else |
| return false; |
| } |
| |
| // Assignment from base class |
| Magick::ColorMono& Magick::ColorMono::operator = ( const Magick::Color& color_ ) |
| { |
| *static_cast<Magick::Color*>(this) = color_; |
| return *this; |
| } |
| |
| // |
| // ColorRGB Implementation |
| // |
| |
| // Construct from red, green, and blue, components |
| Magick::ColorRGB::ColorRGB ( double red_, |
| double green_, |
| double blue_ ) |
| : Color ( scaleDoubleToQuantum(red_), |
| scaleDoubleToQuantum(green_), |
| scaleDoubleToQuantum(blue_) ) |
| { |
| alphaQuantum ( OpaqueAlpha ); |
| } |
| // Null constructor |
| Magick::ColorRGB::ColorRGB ( void ) |
| : Color () |
| { |
| } |
| // Copy constructor from base class |
| Magick::ColorRGB::ColorRGB ( const Magick::Color & color_ ) |
| : Color( color_ ) |
| { |
| } |
| // Destructor |
| Magick::ColorRGB::~ColorRGB ( void ) |
| { |
| // Nothing to do |
| } |
| |
| // Assignment from base class |
| Magick::ColorRGB& Magick::ColorRGB::operator = ( const Magick::Color& color_ ) |
| { |
| *static_cast<Magick::Color*>(this) = color_; |
| return *this; |
| } |
| |
| // |
| // ColorYUV Implementation |
| // |
| |
| // R = Y +1.13980*V |
| // G = Y-0.39380*U-0.58050*V |
| // B = Y+2.02790*U |
| // |
| // U and V, normally -0.5 through 0.5, must be normalized to the range 0 |
| // through QuantumRange. |
| // |
| // Y = 0.29900*R+0.58700*G+0.11400*B |
| // U = -0.14740*R-0.28950*G+0.43690*B |
| // V = 0.61500*R-0.51500*G-0.10000*B |
| // |
| // U and V, normally -0.5 through 0.5, are normalized to the range 0 |
| // through QuantumRange. Note that U = 0.493*(B-Y), V = 0.877*(R-Y). |
| // |
| |
| // Construct from color components |
| Magick::ColorYUV::ColorYUV ( double y_, |
| double u_, |
| double v_ ) |
| : Color ( scaleDoubleToQuantum(y_ + 1.13980 * v_ ), |
| scaleDoubleToQuantum(y_ - (0.39380 * u_) - (0.58050 * v_) ), |
| scaleDoubleToQuantum(y_ + 2.02790 * u_ ) ) |
| { |
| alphaQuantum ( OpaqueAlpha ); |
| } |
| // Null constructor |
| Magick::ColorYUV::ColorYUV ( void ) |
| : Color () |
| { |
| } |
| // Copy constructor from base class |
| Magick::ColorYUV::ColorYUV ( const Magick::Color & color_ ) |
| : Color( color_ ) |
| { |
| } |
| // Destructor |
| Magick::ColorYUV::~ColorYUV ( void ) |
| { |
| // Nothing to do |
| } |
| |
| void Magick::ColorYUV::u ( double u_ ) |
| { |
| double V = v(); |
| double Y = y(); |
| |
| redQuantum ( scaleDoubleToQuantum( Y + 1.13980 * V ) ); |
| greenQuantum ( scaleDoubleToQuantum( Y - (0.39380 * u_) - (0.58050 * V) ) ); |
| blueQuantum ( scaleDoubleToQuantum( Y + 2.02790 * u_ ) ); |
| } |
| |
| double Magick::ColorYUV::u ( void ) const |
| { |
| return scaleQuantumToDouble( (-0.14740 * redQuantum()) - (0.28950 * |
| greenQuantum()) + (0.43690 * blueQuantum()) ); |
| } |
| |
| void Magick::ColorYUV::v ( double v_ ) |
| { |
| double U = u(); |
| double Y = y(); |
| |
| redQuantum ( scaleDoubleToQuantum( Y + 1.13980 * v_ ) ); |
| greenQuantum ( scaleDoubleToQuantum( Y - (0.39380 * U) - (0.58050 * v_) ) ); |
| blueQuantum ( scaleDoubleToQuantum( Y + 2.02790 * U ) ); |
| } |
| |
| double Magick::ColorYUV::v ( void ) const |
| { |
| return scaleQuantumToDouble((0.61500 * redQuantum()) - |
| (0.51500 * greenQuantum()) - |
| (0.10000 * blueQuantum())); |
| } |
| |
| void Magick::ColorYUV::y ( double y_ ) |
| { |
| double U = u(); |
| double V = v(); |
| |
| redQuantum ( scaleDoubleToQuantum( y_ + 1.13980 * V ) ); |
| greenQuantum ( scaleDoubleToQuantum( y_ - (0.39380 * U) - (0.58050 * V) ) ); |
| blueQuantum ( scaleDoubleToQuantum( y_ + 2.02790 * U ) ); |
| } |
| |
| double Magick::ColorYUV::y ( void ) const |
| { |
| return scaleQuantumToDouble((0.29900 * redQuantum()) + |
| (0.58700 * greenQuantum()) + |
| (0.11400 * blueQuantum())); |
| } |
| |
| // Assignment from base class |
| Magick::ColorYUV& Magick::ColorYUV::operator = ( const Magick::Color& color_ ) |
| { |
| *static_cast<Magick::Color*>(this) = color_; |
| return *this; |
| } |