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