1 // This may look like C code, but it is really -*- C++ -*- 2 // 3 // Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2003 4 // Copyright Dirk Lemstra 2013-2017 5 // 6 // Definition and implementation of template functions for using 7 // Magick::Image with STL containers. 8 // 9 10 #ifndef Magick_STL_header 11 #define Magick_STL_header 12 13 #include "Magick++/Include.h" 14 #include <algorithm> 15 #include <functional> 16 #include <iterator> 17 #include <map> 18 #include <utility> 19 20 #include "Magick++/CoderInfo.h" 21 #include "Magick++/Drawable.h" 22 #include "Magick++/Exception.h" 23 #include "Magick++/Montage.h" 24 25 namespace Magick 26 { 27 // 28 // STL function object declarations/definitions 29 // 30 31 // Function objects provide the means to invoke an operation on one 32 // or more image objects in an STL-compatable container. The 33 // arguments to the function object constructor(s) are compatable 34 // with the arguments to the equivalent Image class method and 35 // provide the means to supply these options when the function 36 // object is invoked. 37 38 // For example, to read a GIF animation, set the color red to 39 // transparent for all frames, and write back out: 40 // 41 // list<image> images; 42 // readImages( &images, "animation.gif" ); 43 // for_each( images.begin(), images.end(), transparentImage( "red" ) ); 44 // writeImages( images.begin(), images.end(), "animation.gif" ); 45 46 // Adaptive-blur image with specified blur factor 47 class MagickPPExport adaptiveBlurImage 48 { 49 public: 50 adaptiveBlurImage( const double radius_ = 1, const double sigma_ = 0.5 ); 51 52 void operator()( Image &image_ ) const; 53 54 private: 55 double _radius; 56 double _sigma; 57 }; 58 59 // Local adaptive threshold image 60 // http://www.dai.ed.ac.uk/HIPR2/adpthrsh.htm 61 // Width x height define the size of the pixel neighborhood 62 // offset = constant to subtract from pixel neighborhood mean 63 class MagickPPExport adaptiveThresholdImage 64 { 65 public: 66 adaptiveThresholdImage( const size_t width_, 67 const size_t height_, 68 const ::ssize_t offset_ = 0 ); 69 70 void operator()( Image &image_ ) const; 71 72 private: 73 size_t _width; 74 size_t _height; 75 ::ssize_t _offset; 76 }; 77 78 // Add noise to image with specified noise type 79 class MagickPPExport addNoiseImage 80 { 81 public: 82 addNoiseImage(const NoiseType noiseType_,const double attenuate_ = 1.0); 83 84 void operator()(Image &image_) const; 85 86 private: 87 NoiseType _noiseType; 88 double _attenuate; 89 }; 90 91 // Transform image by specified affine (or free transform) matrix. 92 class MagickPPExport affineTransformImage 93 { 94 public: 95 affineTransformImage( const DrawableAffine &affine_ ); 96 97 void operator()( Image &image_ ) const; 98 99 private: 100 DrawableAffine _affine; 101 }; 102 103 // Annotate image (draw text on image) 104 class MagickPPExport annotateImage 105 { 106 public: 107 // Annotate using specified text, and placement location 108 annotateImage ( const std::string &text_, 109 const Geometry &geometry_ ); 110 111 // Annotate using specified text, bounding area, and placement 112 // gravity 113 annotateImage ( const std::string &text_, 114 const Geometry &geometry_, 115 const GravityType gravity_ ); 116 117 // Annotate with text using specified text, bounding area, 118 // placement gravity, and rotation. 119 annotateImage ( const std::string &text_, 120 const Geometry &geometry_, 121 const GravityType gravity_, 122 const double degrees_ ); 123 124 // Annotate with text (bounding area is entire image) and 125 // placement gravity. 126 annotateImage ( const std::string &text_, 127 const GravityType gravity_ ); 128 129 void operator()( Image &image_ ) const; 130 131 private: 132 const std::string _text; 133 const Geometry _geometry; 134 const GravityType _gravity; 135 const double _degrees; 136 }; 137 138 // Blur image with specified blur factor 139 class MagickPPExport blurImage 140 { 141 public: 142 blurImage( const double radius_ = 1, const double sigma_ = 0.5 ); 143 144 void operator()( Image &image_ ) const; 145 146 private: 147 double _radius; 148 double _sigma; 149 }; 150 151 // Border image (add border to image) 152 class MagickPPExport borderImage 153 { 154 public: 155 borderImage( const Geometry &geometry_ = borderGeometryDefault ); 156 157 void operator()( Image &image_ ) const; 158 159 private: 160 Geometry _geometry; 161 }; 162 163 // Extract channel from image 164 class MagickPPExport channelImage 165 { 166 public: 167 channelImage( const ChannelType channel_ ); 168 169 void operator()( Image &image_ ) const; 170 171 private: 172 ChannelType _channel; 173 }; 174 175 // Charcoal effect image (looks like charcoal sketch) 176 class MagickPPExport charcoalImage 177 { 178 public: 179 charcoalImage( const double radius_ = 1, const double sigma_ = 0.5 ); 180 181 void operator()( Image &image_ ) const; 182 183 private: 184 double _radius; 185 double _sigma; 186 }; 187 188 // Chop image (remove vertical or horizontal subregion of image) 189 class MagickPPExport chopImage 190 { 191 public: 192 chopImage( const Geometry &geometry_ ); 193 194 void operator()( Image &image_ ) const; 195 196 private: 197 Geometry _geometry; 198 }; 199 200 // Accepts a lightweight Color Correction Collection (CCC) file which solely 201 // contains one or more color corrections and applies the correction to the 202 // image. 203 class MagickPPExport cdlImage 204 { 205 public: 206 cdlImage( const std::string &cdl_ ); 207 208 void operator()( Image &image_ ) const; 209 210 private: 211 std::string _cdl; 212 }; 213 214 // Colorize image using pen color at specified percent alpha 215 class MagickPPExport colorizeImage 216 { 217 public: 218 colorizeImage( const unsigned int alphaRed_, 219 const unsigned int alphaGreen_, 220 const unsigned int alphaBlue_, 221 const Color &penColor_ ); 222 223 colorizeImage( const unsigned int alpha_, 224 const Color &penColor_ ); 225 226 void operator()( Image &image_ ) const; 227 228 private: 229 unsigned int _alphaRed; 230 unsigned int _alphaGreen; 231 unsigned int _alphaBlue; 232 Color _penColor; 233 }; 234 235 // Apply a color matrix to the image channels. The user supplied 236 // matrix may be of order 1 to 5 (1x1 through 5x5). 237 class MagickPPExport colorMatrixImage 238 { 239 public: 240 colorMatrixImage( const size_t order_, 241 const double *color_matrix_ ); 242 243 void operator()( Image &image_ ) const; 244 245 private: 246 size_t _order; 247 const double *_color_matrix; 248 }; 249 250 // Convert the image colorspace representation 251 class MagickPPExport colorSpaceImage 252 { 253 public: 254 colorSpaceImage( ColorspaceType colorSpace_ ); 255 256 void operator()( Image &image_ ) const; 257 258 private: 259 ColorspaceType _colorSpace; 260 }; 261 262 // Comment image (add comment string to image) 263 class MagickPPExport commentImage 264 { 265 public: 266 commentImage( const std::string &comment_ ); 267 268 void operator()( Image &image_ ) const; 269 270 private: 271 std::string _comment; 272 }; 273 274 // Compose an image onto another at specified offset and using 275 // specified algorithm 276 class MagickPPExport compositeImage 277 { 278 public: 279 compositeImage( const Image &compositeImage_, 280 ::ssize_t xOffset_, 281 ::ssize_t yOffset_, 282 CompositeOperator compose_ = InCompositeOp ); 283 284 compositeImage( const Image &compositeImage_, 285 const Geometry &offset_, 286 CompositeOperator compose_ = InCompositeOp ); 287 288 void operator()( Image &image_ ) const; 289 290 private: 291 Image _compositeImage; 292 ::ssize_t _xOffset; 293 ::ssize_t _yOffset; 294 CompositeOperator _compose; 295 }; 296 297 // Contrast image (enhance intensity differences in image) 298 class MagickPPExport contrastImage 299 { 300 public: 301 contrastImage( const size_t sharpen_ ); 302 303 void operator()( Image &image_ ) const; 304 305 private: 306 size_t _sharpen; 307 }; 308 309 // Crop image (subregion of original image) 310 class MagickPPExport cropImage 311 { 312 public: 313 cropImage( const Geometry &geometry_ ); 314 315 void operator()( Image &image_ ) const; 316 317 private: 318 Geometry _geometry; 319 }; 320 321 // Cycle image colormap 322 class MagickPPExport cycleColormapImage 323 { 324 public: 325 cycleColormapImage( const ::ssize_t amount_ ); 326 327 void operator()( Image &image_ ) const; 328 329 private: 330 ::ssize_t _amount; 331 }; 332 333 // Despeckle image (reduce speckle noise) 334 class MagickPPExport despeckleImage 335 { 336 public: 337 despeckleImage( void ); 338 339 void operator()( Image &image_ ) const; 340 341 private: 342 }; 343 344 // Distort image. distorts an image using various distortion methods, by 345 // mapping color lookups of the source image to a new destination image 346 // usally of the same size as the source image, unless 'bestfit' is set to 347 // true. 348 class MagickPPExport distortImage 349 { 350 public: 351 distortImage( const Magick::DistortMethod method_, 352 const size_t number_arguments_, 353 const double *arguments_, 354 const bool bestfit_ ); 355 356 distortImage( const Magick::DistortMethod method_, 357 const size_t number_arguments_, 358 const double *arguments_ ); 359 360 void operator()( Image &image_ ) const; 361 362 private: 363 DistortMethod _method; 364 size_t _number_arguments; 365 const double *_arguments; 366 bool _bestfit; 367 }; 368 369 // Draw on image 370 class MagickPPExport drawImage 371 { 372 public: 373 // Draw on image using a single drawable 374 // Store in list to make implementation easier 375 drawImage( const Drawable &drawable_ ); 376 377 // Draw on image using a drawable list 378 drawImage( const DrawableList &drawable_ ); 379 380 void operator()( Image &image_ ) const; 381 382 private: 383 DrawableList _drawableList; 384 }; 385 386 // Edge image (hilight edges in image) 387 class MagickPPExport edgeImage 388 { 389 public: 390 edgeImage( const double radius_ = 0.0 ); 391 392 void operator()( Image &image_ ) const; 393 394 private: 395 double _radius; 396 }; 397 398 // Emboss image (hilight edges with 3D effect) 399 class MagickPPExport embossImage 400 { 401 public: 402 embossImage( void ); 403 embossImage( const double radius_, const double sigma_ ); 404 405 void operator()( Image &image_ ) const; 406 407 private: 408 double _radius; 409 double _sigma; 410 }; 411 412 // Enhance image (minimize noise) 413 class MagickPPExport enhanceImage 414 { 415 public: 416 enhanceImage( void ); 417 418 void operator()( Image &image_ ) const; 419 420 private: 421 }; 422 423 // Equalize image (histogram equalization) 424 class MagickPPExport equalizeImage 425 { 426 public: 427 equalizeImage( void ); 428 429 void operator()( Image &image_ ) const; 430 431 private: 432 }; 433 434 // Color to use when filling drawn objects 435 class MagickPPExport fillColorImage 436 { 437 public: 438 fillColorImage( const Color &fillColor_ ); 439 440 void operator()( Image &image_ ) const; 441 442 private: 443 Color _fillColor; 444 }; 445 446 // Flip image (reflect each scanline in the vertical direction) 447 class MagickPPExport flipImage 448 { 449 public: 450 flipImage( void ); 451 452 void operator()( Image &image_ ) const; 453 454 private: 455 }; 456 457 // Floodfill designated area with a matte value 458 class MagickPPExport floodFillAlphaImage 459 460 { 461 public: 462 floodFillAlphaImage(const ::ssize_t x_,const ::ssize_t y_, 463 const unsigned int alpha_,const Color &target_,const bool invert_=false); 464 465 void operator()(Image &image_) const; 466 467 private: 468 Color _target; 469 unsigned int _alpha; 470 ::ssize_t _x; 471 ::ssize_t _y; 472 bool _invert; 473 }; 474 475 // Flood-fill image with color 476 class MagickPPExport floodFillColorImage 477 478 { 479 public: 480 // Flood-fill color across pixels starting at target-pixel and 481 // stopping at pixels matching specified border color. 482 // Uses current fuzz setting when determining color match. 483 floodFillColorImage(const Geometry &point_,const Color &fillColor_, 484 const bool invert_=false); 485 floodFillColorImage(const ::ssize_t x_,const ::ssize_t y_, 486 const Color &fillColor_,const bool invert_=false); 487 488 // Flood-fill color across pixels starting at target-pixel and 489 // stopping at pixels matching specified border color. 490 // Uses current fuzz setting when determining color match. 491 floodFillColorImage(const Geometry &point_,const Color &fillColor_, 492 const Color &borderColor_,const bool invert_=false); 493 floodFillColorImage(const ::ssize_t x_,const ::ssize_t y_, 494 const Color &fillColor_,const Color &borderColor_, 495 const bool invert_=false); 496 497 void operator()(Image &image_) const; 498 499 private: 500 ::ssize_t _x; 501 ::ssize_t _y; 502 Color _fillColor; 503 Color _borderColor; 504 bool _invert; 505 }; 506 507 // Flood-fill image with texture 508 class MagickPPExport floodFillTextureImage 509 510 { 511 public: 512 // Flood-fill texture across pixels that match the color of the 513 // target pixel and are neighbors of the target pixel. 514 // Uses current fuzz setting when determining color match. 515 floodFillTextureImage(const ::ssize_t x_,const ::ssize_t y_, 516 const Image &texture_,const bool invert_=false); 517 floodFillTextureImage(const Geometry &point_,const Image &texture_, 518 const bool invert_=false); 519 520 // Flood-fill texture across pixels starting at target-pixel and 521 // stopping at pixels matching specified border color. 522 // Uses current fuzz setting when determining color match. 523 floodFillTextureImage(const ::ssize_t x_,const ::ssize_t y_, 524 const Image &texture_,const Color &borderColor_, 525 const bool invert_=false); 526 527 floodFillTextureImage(const Geometry &point_,const Image &texture_, 528 const Color &borderColor_,const bool invert_=false); 529 530 void operator()(Image &image_) const; 531 532 private: 533 ::ssize_t _x; 534 ::ssize_t _y; 535 Image _texture; 536 Color _borderColor; 537 bool _invert; 538 }; 539 540 // Flop image (reflect each scanline in the horizontal direction) 541 class MagickPPExport flopImage 542 { 543 public: 544 flopImage( void ); 545 546 void operator()( Image &image_ ) const; 547 548 private: 549 }; 550 551 // Frame image 552 class MagickPPExport frameImage 553 { 554 public: 555 frameImage( const Geometry &geometry_ = frameGeometryDefault ); 556 557 frameImage( const size_t width_, const size_t height_, 558 const ::ssize_t innerBevel_ = 6, const ::ssize_t outerBevel_ = 6 ); 559 560 void operator()( Image &image_ ) const; 561 562 private: 563 size_t _width; 564 size_t _height; 565 ::ssize_t _outerBevel; 566 ::ssize_t _innerBevel; 567 }; 568 569 // Gamma correct image 570 class MagickPPExport gammaImage 571 { 572 public: 573 gammaImage( const double gamma_ ); 574 575 gammaImage ( const double gammaRed_, 576 const double gammaGreen_, 577 const double gammaBlue_ ); 578 579 void operator()( Image &image_ ) const; 580 581 private: 582 double _gammaRed; 583 double _gammaGreen; 584 double _gammaBlue; 585 }; 586 587 // Gaussian blur image 588 // The number of neighbor pixels to be included in the convolution 589 // mask is specified by 'width_'. The standard deviation of the 590 // gaussian bell curve is specified by 'sigma_'. 591 class MagickPPExport gaussianBlurImage 592 { 593 public: 594 gaussianBlurImage( const double width_, const double sigma_ ); 595 596 void operator()( Image &image_ ) const; 597 598 private: 599 double _width; 600 double _sigma; 601 }; 602 603 // Apply a color lookup table (Hald CLUT) to the image. 604 class MagickPPExport haldClutImage 605 { 606 public: 607 haldClutImage( const Image &haldClutImage_ ); 608 609 void operator()( Image &image_ ) const; 610 611 private: 612 Image _haldClutImage; 613 }; 614 615 // Implode image (special effect) 616 class MagickPPExport implodeImage 617 { 618 public: 619 implodeImage( const double factor_ = 50 ); 620 621 void operator()( Image &image_ ) const; 622 623 private: 624 double _factor; 625 }; 626 627 // implements the inverse discrete Fourier transform (IFT) of the image 628 // either as a magnitude / phase or real / imaginary image pair. 629 class MagickPPExport inverseFourierTransformImage 630 { 631 public: 632 inverseFourierTransformImage( const Image &phaseImage_ ); 633 634 void operator()( Image &image_ ) const; 635 636 private: 637 Image _phaseImage; 638 }; 639 640 // Set image validity. Valid images become empty (inValid) if 641 // argument is false. 642 class MagickPPExport isValidImage 643 { 644 public: 645 isValidImage( const bool isValid_ ); 646 647 void operator()( Image &image_ ) const; 648 649 private: 650 bool _isValid; 651 }; 652 653 // Label image 654 class MagickPPExport labelImage 655 { 656 public: 657 labelImage( const std::string &label_ ); 658 659 void operator()( Image &image_ ) const; 660 661 private: 662 std::string _label; 663 }; 664 665 666 // Level image 667 class MagickPPExport levelImage 668 { 669 public: 670 levelImage( const double black_point, 671 const double white_point, 672 const double mid_point=1.0 ); 673 674 void operator()( Image &image_ ) const; 675 676 private: 677 double _black_point; 678 double _white_point; 679 double _mid_point; 680 }; 681 682 // Magnify image by integral size 683 class MagickPPExport magnifyImage 684 { 685 public: 686 magnifyImage( void ); 687 688 void operator()( Image &image_ ) const; 689 690 private: 691 }; 692 693 // Remap image colors with closest color from reference image 694 class MagickPPExport mapImage 695 { 696 public: 697 mapImage( const Image &mapImage_ , 698 const bool dither_ = false ); 699 700 void operator()( Image &image_ ) const; 701 702 private: 703 Image _mapImage; 704 bool _dither; 705 }; 706 707 // Filter image by replacing each pixel component with the median 708 // color in a circular neighborhood 709 class MagickPPExport medianConvolveImage 710 { 711 public: 712 medianConvolveImage( const double radius_ = 0.0 ); 713 714 void operator()( Image &image_ ) const; 715 716 private: 717 double _radius; 718 }; 719 720 // Merge image layers 721 class MagickPPExport mergeLayersImage 722 { 723 public: 724 mergeLayersImage ( LayerMethod layerMethod_ ); 725 726 void operator()( Image &image_ ) const; 727 728 private: 729 LayerMethod _layerMethod; 730 }; 731 732 // Reduce image by integral size 733 class MagickPPExport minifyImage 734 { 735 public: 736 minifyImage( void ); 737 738 void operator()( Image &image_ ) const; 739 740 private: 741 }; 742 743 // Modulate percent hue, saturation, and brightness of an image 744 class MagickPPExport modulateImage 745 { 746 public: 747 modulateImage( const double brightness_, 748 const double saturation_, 749 const double hue_ ); 750 751 void operator()( Image &image_ ) const; 752 753 private: 754 double _brightness; 755 double _saturation; 756 double _hue; 757 }; 758 759 // Negate colors in image. Set grayscale to only negate grayscale 760 // values in image. 761 class MagickPPExport negateImage 762 { 763 public: 764 negateImage( const bool grayscale_ = false ); 765 766 void operator()( Image &image_ ) const; 767 768 private: 769 bool _grayscale; 770 }; 771 772 // Normalize image (increase contrast by normalizing the pixel 773 // values to span the full range of color values) 774 class MagickPPExport normalizeImage 775 { 776 public: 777 normalizeImage( void ); 778 779 void operator()( Image &image_ ) const; 780 781 private: 782 }; 783 784 // Oilpaint image (image looks like oil painting) 785 class MagickPPExport oilPaintImage 786 { 787 public: 788 oilPaintImage( const double radius_ = 3 ); 789 790 void operator()( Image &image_ ) const; 791 792 private: 793 double _radius; 794 }; 795 796 // Set or attenuate the image alpha channel. If the image pixels 797 // are opaque then they are set to the specified alpha value, 798 // otherwise they are blended with the supplied alpha value. The 799 // value of alpha_ ranges from 0 (completely opaque) to 800 // QuantumRange. The defines OpaqueAlpha and TransparentAlpha are 801 // available to specify completely opaque or completely transparent, 802 // respectively. 803 class MagickPPExport alphaImage 804 { 805 public: 806 alphaImage( const unsigned int alpha_ ); 807 808 void operator()( Image &image_ ) const; 809 810 private: 811 unsigned int _alpha; 812 }; 813 814 // Change color of opaque pixel to specified pen color. 815 class MagickPPExport opaqueImage 816 { 817 public: 818 opaqueImage( const Color &opaqueColor_, 819 const Color &penColor_ ); 820 821 void operator()( Image &image_ ) const; 822 823 private: 824 Color _opaqueColor; 825 Color _penColor; 826 }; 827 828 // Quantize image (reduce number of colors) 829 class MagickPPExport quantizeImage 830 { 831 public: 832 quantizeImage( const bool measureError_ = false ); 833 834 void operator()( Image &image_ ) const; 835 836 private: 837 bool _measureError; 838 }; 839 840 // Raise image (lighten or darken the edges of an image to give a 841 // 3-D raised or lowered effect) 842 class MagickPPExport raiseImage 843 { 844 public: 845 raiseImage( const Geometry &geometry_ = raiseGeometryDefault, 846 const bool raisedFlag_ = false ); 847 848 void operator()( Image &image_ ) const; 849 850 private: 851 Geometry _geometry; 852 bool _raisedFlag; 853 }; 854 855 class MagickPPExport ReadOptions 856 { 857 public: 858 859 // Default constructor 860 ReadOptions(void); 861 862 // Copy constructor 863 ReadOptions(const ReadOptions& options_); 864 865 // Destructor 866 ~ReadOptions(); 867 868 // Vertical and horizontal resolution in pixels of the image 869 void density(const Geometry &geomery_); 870 Geometry density(void) const; 871 872 // Image depth (8 or 16) 873 void depth(size_t depth_); 874 size_t depth(void) const; 875 876 // Ping the image instead of reading it 877 void ping(const bool flag_); 878 bool ping(void) const; 879 880 // Suppress all warning messages. Error messages are still reported. 881 void quiet(const bool quiet_); 882 bool quiet(void) const; 883 884 // Image size (required for raw formats) 885 void size(const Geometry &geometry_); 886 Geometry size(void) const; 887 888 // 889 // Internal implementation methods. Please do not use. 890 // 891 892 MagickCore::ImageInfo *imageInfo(void); 893 894 private: 895 896 // Assignment not supported 897 ReadOptions& operator=(const ReadOptions&); 898 899 MagickCore::ImageInfo *_imageInfo; 900 bool _quiet; 901 }; 902 903 // Reduce noise in image using a noise peak elimination filter 904 class MagickPPExport reduceNoiseImage 905 { 906 public: 907 reduceNoiseImage( void ); 908 909 reduceNoiseImage (const size_t order_ ); 910 911 void operator()( Image &image_ ) const; 912 913 private: 914 size_t _order; 915 }; 916 917 // Resize image to specified size. 918 class MagickPPExport resizeImage 919 { 920 public: 921 resizeImage( const Geometry &geometry_ ); 922 923 void operator()( Image &image_ ) const; 924 925 private: 926 Geometry _geometry; 927 }; 928 929 // Roll image (rolls image vertically and horizontally) by specified 930 // number of columnms and rows) 931 class MagickPPExport rollImage 932 { 933 public: 934 rollImage( const Geometry &roll_ ); 935 936 rollImage( const ::ssize_t columns_, const ::ssize_t rows_ ); 937 938 void operator()( Image &image_ ) const; 939 940 private: 941 size_t _columns; 942 size_t _rows; 943 }; 944 945 // Rotate image counter-clockwise by specified number of degrees. 946 class MagickPPExport rotateImage 947 { 948 public: 949 rotateImage( const double degrees_ ); 950 951 void operator()( Image &image_ ) const; 952 953 private: 954 double _degrees; 955 }; 956 957 // Resize image by using pixel sampling algorithm 958 class MagickPPExport sampleImage 959 { 960 public: 961 sampleImage( const Geometry &geometry_ ); 962 963 void operator()( Image &image_ ) const; 964 965 private: 966 Geometry _geometry; 967 }; 968 969 // Resize image by using simple ratio algorithm 970 class MagickPPExport scaleImage 971 { 972 public: 973 scaleImage( const Geometry &geometry_ ); 974 975 void operator()( Image &image_ ) const; 976 977 private: 978 Geometry _geometry; 979 }; 980 981 // Segment (coalesce similar image components) by analyzing the 982 // histograms of the color components and identifying units that are 983 // homogeneous with the fuzzy c-means technique. 984 // Also uses QuantizeColorSpace and Verbose image attributes 985 class MagickPPExport segmentImage 986 { 987 public: 988 segmentImage( const double clusterThreshold_ = 1.0, 989 const double smoothingThreshold_ = 1.5 ); 990 991 void operator()( Image &image_ ) const; 992 993 private: 994 double _clusterThreshold; 995 double _smoothingThreshold; 996 }; 997 998 // Shade image using distant light source 999 class MagickPPExport shadeImage 1000 { 1001 public: 1002 shadeImage( const double azimuth_ = 30, 1003 const double elevation_ = 30, 1004 const bool colorShading_ = false ); 1005 1006 void operator()( Image &image_ ) const; 1007 1008 private: 1009 double _azimuth; 1010 double _elevation; 1011 bool _colorShading; 1012 }; 1013 1014 // Shadow effect image (simulate an image shadow) 1015 class MagickPPExport shadowImage 1016 { 1017 public: 1018 shadowImage( const double percent_opacity_ = 80, const double sigma_ = 0.5, 1019 const ssize_t x_ = 5, const ssize_t y_ = 5 ); 1020 1021 void operator()( Image &image_ ) const; 1022 1023 private: 1024 double _percent_opacity; 1025 double _sigma; 1026 ssize_t _x; 1027 ssize_t _y; 1028 }; 1029 1030 // Sharpen pixels in image 1031 class MagickPPExport sharpenImage 1032 { 1033 public: 1034 sharpenImage( const double radius_ = 1, const double sigma_ = 0.5 ); 1035 1036 void operator()( Image &image_ ) const; 1037 1038 private: 1039 double _radius; 1040 double _sigma; 1041 }; 1042 1043 // Shave pixels from image edges. 1044 class MagickPPExport shaveImage 1045 { 1046 public: 1047 shaveImage( const Geometry &geometry_ ); 1048 1049 void operator()( Image &image_ ) const; 1050 1051 private: 1052 Geometry _geometry; 1053 }; 1054 1055 1056 // Shear image (create parallelogram by sliding image by X or Y axis) 1057 class MagickPPExport shearImage 1058 { 1059 public: 1060 shearImage( const double xShearAngle_, 1061 const double yShearAngle_ ); 1062 1063 void operator()( Image &image_ ) const; 1064 1065 private: 1066 double _xShearAngle; 1067 double _yShearAngle; 1068 }; 1069 1070 // Solarize image (similar to effect seen when exposing a 1071 // photographic film to light during the development process) 1072 class MagickPPExport solarizeImage 1073 { 1074 public: 1075 solarizeImage( const double factor_ ); 1076 1077 void operator()( Image &image_ ) const; 1078 1079 private: 1080 double _factor; 1081 }; 1082 1083 // Splice the background color into the image. 1084 class MagickPPExport spliceImage 1085 { 1086 public: 1087 spliceImage( const Geometry &geometry_ ); 1088 1089 void operator()( Image &image_ ) const; 1090 1091 private: 1092 Geometry _geometry; 1093 }; 1094 1095 // Spread pixels randomly within image by specified ammount 1096 class MagickPPExport spreadImage 1097 { 1098 public: 1099 spreadImage( const size_t amount_ = 3 ); 1100 1101 void operator()( Image &image_ ) const; 1102 1103 private: 1104 size_t _amount; 1105 }; 1106 1107 // Add a digital watermark to the image (based on second image) 1108 class MagickPPExport steganoImage 1109 { 1110 public: 1111 steganoImage( const Image &waterMark_ ); 1112 1113 void operator()( Image &image_ ) const; 1114 1115 private: 1116 Image _waterMark; 1117 }; 1118 1119 // Create an image which appears in stereo when viewed with red-blue glasses 1120 // (Red image on left, blue on right) 1121 class MagickPPExport stereoImage 1122 { 1123 public: 1124 stereoImage( const Image &rightImage_ ); 1125 1126 void operator()( Image &image_ ) const; 1127 1128 private: 1129 Image _rightImage; 1130 }; 1131 1132 // Color to use when drawing object outlines 1133 class MagickPPExport strokeColorImage 1134 { 1135 public: 1136 strokeColorImage( const Color &strokeColor_ ); 1137 1138 void operator()( Image &image_ ) const; 1139 1140 private: 1141 Color _strokeColor; 1142 }; 1143 1144 // Swirl image (image pixels are rotated by degrees) 1145 class MagickPPExport swirlImage 1146 { 1147 public: 1148 swirlImage( const double degrees_ ); 1149 1150 void operator()( Image &image_ ) const; 1151 1152 private: 1153 double _degrees; 1154 }; 1155 1156 // Channel a texture on image background 1157 class MagickPPExport textureImage 1158 { 1159 public: 1160 textureImage( const Image &texture_ ); 1161 1162 void operator()( Image &image_ ) const; 1163 1164 private: 1165 Image _texture; 1166 }; 1167 1168 // Threshold image 1169 class MagickPPExport thresholdImage 1170 { 1171 public: 1172 thresholdImage( const double threshold_ ); 1173 1174 void operator()( Image &image_ ) const; 1175 1176 private: 1177 double _threshold; 1178 }; 1179 1180 // Set image color to transparent 1181 class MagickPPExport transparentImage 1182 { 1183 public: 1184 transparentImage( const Color& color_ ); 1185 1186 void operator()( Image &image_ ) const; 1187 1188 private: 1189 Color _color; 1190 }; 1191 1192 // Trim edges that are the background color from the image 1193 class MagickPPExport trimImage 1194 { 1195 public: 1196 trimImage( void ); 1197 1198 void operator()( Image &image_ ) const; 1199 1200 private: 1201 }; 1202 1203 // Map image pixels to a sine wave 1204 class MagickPPExport waveImage 1205 { 1206 public: 1207 waveImage( const double amplitude_ = 25.0, 1208 const double wavelength_ = 150.0 ); 1209 1210 void operator()( Image &image_ ) const; 1211 1212 private: 1213 double _amplitude; 1214 double _wavelength; 1215 }; 1216 1217 // Zoom image to specified size. 1218 class MagickPPExport zoomImage 1219 { 1220 public: 1221 zoomImage( const Geometry &geometry_ ); 1222 1223 void operator()( Image &image_ ) const; 1224 1225 private: 1226 Geometry _geometry; 1227 }; 1228 1229 // 1230 // Function object image attribute accessors 1231 // 1232 1233 // Join images into a single multi-image file 1234 class MagickPPExport adjoinImage 1235 { 1236 public: 1237 adjoinImage( const bool flag_ ); 1238 1239 void operator()( Image &image_ ) const; 1240 1241 private: 1242 bool _flag; 1243 }; 1244 1245 // Time in 1/100ths of a second which must expire before displaying 1246 // the next image in an animated sequence. 1247 class MagickPPExport animationDelayImage 1248 { 1249 public: 1250 animationDelayImage( const size_t delay_ ); 1251 1252 void operator()( Image &image_ ) const; 1253 1254 private: 1255 size_t _delay; 1256 }; 1257 1258 // Number of iterations to loop an animation (e.g. Netscape loop 1259 // extension) for. 1260 class MagickPPExport animationIterationsImage 1261 { 1262 public: 1263 animationIterationsImage( const size_t iterations_ ); 1264 1265 void operator()( Image &image_ ) const; 1266 1267 private: 1268 size_t _iterations; 1269 }; 1270 1271 // Image background color 1272 class MagickPPExport backgroundColorImage 1273 { 1274 public: 1275 backgroundColorImage( const Color &color_ ); 1276 1277 void operator()( Image &image_ ) const; 1278 1279 private: 1280 Color _color; 1281 }; 1282 1283 // Name of texture image to tile onto the image background 1284 class MagickPPExport backgroundTextureImage 1285 { 1286 public: 1287 backgroundTextureImage( const std::string &backgroundTexture_ ); 1288 1289 void operator()( Image &image_ ) const; 1290 1291 private: 1292 std::string _backgroundTexture; 1293 }; 1294 1295 // Image border color 1296 class MagickPPExport borderColorImage 1297 { 1298 public: 1299 borderColorImage( const Color &color_ ); 1300 1301 void operator()( Image &image_ ) const; 1302 1303 private: 1304 Color _color; 1305 }; 1306 1307 // Text bounding-box base color (default none) 1308 class MagickPPExport boxColorImage 1309 { 1310 public: 1311 boxColorImage( const Color &boxColor_ ); 1312 1313 void operator()( Image &image_ ) const; 1314 1315 private: 1316 Color _boxColor; 1317 }; 1318 1319 // Chromaticity blue primary point. 1320 class MagickPPExport chromaBluePrimaryImage 1321 { 1322 public: 1323 chromaBluePrimaryImage(const double x_,const double y_,const double z_); 1324 1325 void operator()(Image &image_) const; 1326 1327 private: 1328 double _x; 1329 double _y; 1330 double _z; 1331 }; 1332 1333 // Chromaticity green primary point. 1334 class MagickPPExport chromaGreenPrimaryImage 1335 { 1336 public: 1337 chromaGreenPrimaryImage(const double x_,const double y_,const double z_); 1338 1339 void operator()(Image &image_) const; 1340 1341 private: 1342 double _x; 1343 double _y; 1344 double _z; 1345 }; 1346 1347 // Chromaticity red primary point. 1348 class MagickPPExport chromaRedPrimaryImage 1349 { 1350 public: 1351 chromaRedPrimaryImage(const double x_,const double y_,const double z_); 1352 1353 void operator()(Image &image_) const; 1354 1355 private: 1356 double _x; 1357 double _y; 1358 double _z; 1359 }; 1360 1361 // Chromaticity white point. 1362 class MagickPPExport chromaWhitePointImage 1363 { 1364 public: 1365 chromaWhitePointImage(const double x_,const double y_,const double z_); 1366 1367 void operator()(Image &image_) const; 1368 1369 private: 1370 double _x; 1371 double _y; 1372 double _z; 1373 }; 1374 1375 // Colors within this distance are considered equal 1376 class MagickPPExport colorFuzzImage 1377 { 1378 public: 1379 colorFuzzImage( const double fuzz_ ); 1380 1381 void operator()( Image &image_ ) const; 1382 1383 private: 1384 double _fuzz; 1385 }; 1386 1387 // Color at colormap position index_ 1388 class MagickPPExport colorMapImage 1389 { 1390 public: 1391 colorMapImage( const size_t index_, const Color &color_ ); 1392 1393 void operator()( Image &image_ ) const; 1394 1395 private: 1396 size_t _index; 1397 Color _color; 1398 }; 1399 1400 // Composition operator to be used when composition is implicitly used 1401 // (such as for image flattening). 1402 class MagickPPExport composeImage 1403 { 1404 public: 1405 composeImage( const CompositeOperator compose_ ); 1406 1407 void operator()( Image &image_ ) const; 1408 1409 private: 1410 CompositeOperator _compose; 1411 }; 1412 1413 // Compression type 1414 class MagickPPExport compressTypeImage 1415 { 1416 public: 1417 compressTypeImage( const CompressionType compressType_ ); 1418 1419 void operator()( Image &image_ ) const; 1420 1421 private: 1422 CompressionType _compressType; 1423 }; 1424 1425 // Vertical and horizontal resolution in pixels of the image 1426 class MagickPPExport densityImage 1427 { 1428 public: 1429 densityImage( const Point &point_ ); 1430 1431 void operator()( Image &image_ ) const; 1432 1433 private: 1434 Point _point; 1435 }; 1436 1437 // Image depth (bits allocated to red/green/blue components) 1438 class MagickPPExport depthImage 1439 { 1440 public: 1441 depthImage( const size_t depth_ ); 1442 1443 void operator()( Image &image_ ) const; 1444 1445 private: 1446 size_t _depth; 1447 }; 1448 1449 // Endianness (LSBEndian like Intel or MSBEndian like SPARC) for image 1450 // formats which support endian-specific options. 1451 class MagickPPExport endianImage 1452 { 1453 public: 1454 endianImage( const EndianType endian_ ); 1455 1456 void operator()( Image &image_ ) const; 1457 1458 private: 1459 EndianType _endian; 1460 }; 1461 1462 // Image file name 1463 class MagickPPExport fileNameImage 1464 { 1465 public: 1466 fileNameImage( const std::string &fileName_ ); 1467 1468 void operator()( Image &image_ ) const; 1469 1470 private: 1471 std::string _fileName; 1472 }; 1473 1474 // Filter to use when resizing image 1475 class MagickPPExport filterTypeImage 1476 { 1477 public: 1478 filterTypeImage( const FilterType filterType_ ); 1479 1480 void operator()( Image &image_ ) const; 1481 1482 private: 1483 FilterType _filterType; 1484 }; 1485 1486 // Text rendering font 1487 class MagickPPExport fontImage 1488 { 1489 public: 1490 fontImage( const std::string &font_ ); 1491 1492 void operator()( Image &image_ ) const; 1493 1494 private: 1495 std::string _font; 1496 }; 1497 1498 // Font point size 1499 class MagickPPExport fontPointsizeImage 1500 { 1501 public: 1502 fontPointsizeImage( const size_t pointsize_ ); 1503 1504 void operator()( Image &image_ ) const; 1505 1506 private: 1507 size_t _pointsize; 1508 }; 1509 1510 // GIF disposal method 1511 class MagickPPExport gifDisposeMethodImage 1512 { 1513 public: 1514 gifDisposeMethodImage( const DisposeType disposeMethod_ ); 1515 1516 void operator()( Image &image_ ) const; 1517 1518 private: 1519 DisposeType _disposeMethod; 1520 }; 1521 1522 // Type of interlacing to use 1523 class MagickPPExport interlaceTypeImage 1524 { 1525 public: 1526 interlaceTypeImage( const InterlaceType interlace_ ); 1527 1528 void operator()( Image &image_ ) const; 1529 1530 private: 1531 InterlaceType _interlace; 1532 }; 1533 1534 // File type magick identifier (.e.g "GIF") 1535 class MagickPPExport magickImage 1536 { 1537 public: 1538 magickImage( const std::string &magick_ ); 1539 1540 void operator()( Image &image_ ) const; 1541 1542 private: 1543 std::string _magick; 1544 }; 1545 1546 // Image supports transparent color 1547 class MagickPPExport alphaFlagImage 1548 { 1549 public: 1550 alphaFlagImage( const bool alphaFlag_ ); 1551 1552 void operator()( Image &image_ ) const; 1553 1554 private: 1555 bool _alphaFlag; 1556 }; 1557 1558 // Transparent color 1559 class MagickPPExport matteColorImage 1560 { 1561 public: 1562 matteColorImage( const Color &matteColor_ ); 1563 1564 void operator()( Image &image_ ) const; 1565 1566 private: 1567 Color _matteColor; 1568 }; 1569 1570 // Indicate that image is black and white 1571 class MagickPPExport monochromeImage 1572 { 1573 public: 1574 monochromeImage( const bool monochromeFlag_ ); 1575 1576 void operator()( Image &image_ ) const; 1577 1578 private: 1579 bool _monochromeFlag; 1580 }; 1581 1582 // Pen color 1583 class MagickPPExport penColorImage 1584 { 1585 public: 1586 penColorImage( const Color &penColor_ ); 1587 1588 void operator()( Image &image_ ) const; 1589 1590 private: 1591 Color _penColor; 1592 }; 1593 1594 // Pen texture image. 1595 class MagickPPExport penTextureImage 1596 { 1597 public: 1598 penTextureImage( const Image &penTexture_ ); 1599 1600 void operator()( Image &image_ ) const; 1601 1602 private: 1603 Image _penTexture; 1604 }; 1605 1606 // Set pixel color at location x & y. 1607 class MagickPPExport pixelColorImage 1608 { 1609 public: 1610 pixelColorImage( const ::ssize_t x_, 1611 const ::ssize_t y_, 1612 const Color &color_); 1613 1614 void operator()( Image &image_ ) const; 1615 1616 private: 1617 ::ssize_t _x; 1618 ::ssize_t _y; 1619 Color _color; 1620 }; 1621 1622 // Postscript page size. 1623 class MagickPPExport pageImage 1624 { 1625 public: 1626 pageImage( const Geometry &pageSize_ ); 1627 1628 void operator()( Image &image_ ) const; 1629 1630 private: 1631 Geometry _pageSize; 1632 }; 1633 1634 // JPEG/MIFF/PNG compression level (default 75). 1635 class MagickPPExport qualityImage 1636 { 1637 public: 1638 qualityImage( const size_t quality_ ); 1639 1640 void operator()( Image &image_ ) const; 1641 1642 private: 1643 size_t _quality; 1644 }; 1645 1646 // Maximum number of colors to quantize to 1647 class MagickPPExport quantizeColorsImage 1648 { 1649 public: 1650 quantizeColorsImage( const size_t colors_ ); 1651 1652 void operator()( Image &image_ ) const; 1653 1654 private: 1655 size_t _colors; 1656 }; 1657 1658 // Colorspace to quantize in. 1659 class MagickPPExport quantizeColorSpaceImage 1660 { 1661 public: 1662 quantizeColorSpaceImage( const ColorspaceType colorSpace_ ); 1663 1664 void operator()( Image &image_ ) const; 1665 1666 private: 1667 ColorspaceType _colorSpace; 1668 }; 1669 1670 // Dither image during quantization (default true). 1671 class MagickPPExport quantizeDitherImage 1672 { 1673 public: 1674 quantizeDitherImage( const bool ditherFlag_ ); 1675 1676 void operator()( Image &image_ ) const; 1677 1678 private: 1679 bool _ditherFlag; 1680 }; 1681 1682 // Quantization tree-depth 1683 class MagickPPExport quantizeTreeDepthImage 1684 { 1685 public: 1686 quantizeTreeDepthImage( const size_t treeDepth_ ); 1687 1688 void operator()( Image &image_ ) const; 1689 1690 private: 1691 size_t _treeDepth; 1692 }; 1693 1694 // The type of rendering intent 1695 class MagickPPExport renderingIntentImage 1696 { 1697 public: 1698 renderingIntentImage( const RenderingIntent renderingIntent_ ); 1699 1700 void operator()( Image &image_ ) const; 1701 1702 private: 1703 RenderingIntent _renderingIntent; 1704 }; 1705 1706 // Units of image resolution 1707 class MagickPPExport resolutionUnitsImage 1708 { 1709 public: 1710 resolutionUnitsImage( const ResolutionType resolutionUnits_ ); 1711 1712 void operator()( Image &image_ ) const; 1713 1714 private: 1715 ResolutionType _resolutionUnits; 1716 }; 1717 1718 // Image scene number 1719 class MagickPPExport sceneImage 1720 { 1721 public: 1722 sceneImage( const size_t scene_ ); 1723 1724 void operator()( Image &image_ ) const; 1725 1726 private: 1727 size_t _scene; 1728 }; 1729 1730 // adjust the image contrast with a non-linear sigmoidal contrast algorithm 1731 class MagickPPExport sigmoidalContrastImage 1732 { 1733 public: 1734 sigmoidalContrastImage( const size_t sharpen_, 1735 const double contrast, 1736 const double midpoint = QuantumRange / 2.0 ); 1737 1738 void operator()( Image &image_ ) const; 1739 1740 private: 1741 size_t _sharpen; 1742 double contrast; 1743 double midpoint; 1744 }; 1745 1746 // Width and height of a raw image 1747 class MagickPPExport sizeImage 1748 { 1749 public: 1750 sizeImage( const Geometry &geometry_ ); 1751 1752 void operator()( Image &image_ ) const; 1753 1754 private: 1755 Geometry _geometry; 1756 }; 1757 1758 // stripImage strips an image of all profiles and comments. 1759 class MagickPPExport stripImage 1760 { 1761 public: 1762 stripImage( void ); 1763 1764 void operator()( Image &image_ ) const; 1765 1766 private: 1767 }; 1768 1769 // Subimage of an image sequence 1770 class MagickPPExport subImageImage 1771 { 1772 public: 1773 subImageImage( const size_t subImage_ ); 1774 1775 void operator()( Image &image_ ) const; 1776 1777 private: 1778 size_t _subImage; 1779 }; 1780 1781 // Number of images relative to the base image 1782 class MagickPPExport subRangeImage 1783 { 1784 public: 1785 subRangeImage( const size_t subRange_ ); 1786 1787 void operator()( Image &image_ ) const; 1788 1789 private: 1790 size_t _subRange; 1791 }; 1792 1793 // Anti-alias Postscript and TrueType fonts (default true) 1794 class MagickPPExport textAntiAliasImage 1795 { 1796 public: 1797 textAntiAliasImage( const bool flag_ ); 1798 1799 void operator()( Image &image_ ) const; 1800 1801 private: 1802 bool _flag; 1803 }; 1804 1805 // Image storage type 1806 class MagickPPExport typeImage 1807 { 1808 public: 1809 typeImage( const ImageType type_ ); 1810 1811 void operator()( Image &image_ ) const; 1812 1813 private: 1814 Magick::ImageType _type; 1815 }; 1816 1817 1818 // Print detailed information about the image 1819 class MagickPPExport verboseImage 1820 { 1821 public: 1822 verboseImage( const bool verbose_ ); 1823 1824 void operator()( Image &image_ ) const; 1825 1826 private: 1827 bool _verbose; 1828 }; 1829 1830 // X11 display to display to, obtain fonts from, or to capture 1831 // image from 1832 class MagickPPExport x11DisplayImage 1833 { 1834 public: 1835 x11DisplayImage( const std::string &display_ ); 1836 1837 void operator()( Image &image_ ) const; 1838 1839 private: 1840 std::string _display; 1841 }; 1842 1843 ////////////////////////////////////////////////////////// 1844 // 1845 // Implementation template definitions. Not for end-use. 1846 // 1847 ////////////////////////////////////////////////////////// 1848 1849 // Changes the channel mask of the images and places the old 1850 // values in the container. 1851 template<class InputIterator, class Container> channelMaskImages(InputIterator first_,InputIterator last_,Container * container_,const ChannelType channel_)1852 void channelMaskImages(InputIterator first_,InputIterator last_, 1853 Container *container_,const ChannelType channel_) 1854 { 1855 MagickCore::ChannelType 1856 channel_mask; 1857 1858 container_->clear(); 1859 for (InputIterator iter = first_; iter != last_; ++iter) 1860 { 1861 iter->modifyImage(); 1862 channel_mask=MagickCore::SetImageChannelMask(iter->image(),channel_); 1863 container_->push_back(channel_mask); 1864 } 1865 } 1866 1867 // Insert images in image list into existing container (appending to container) 1868 // The images should not be deleted since only the image ownership is passed. 1869 // The options are copied into the object. 1870 template<class Container> insertImages(Container * sequence_,MagickCore::Image * images_)1871 void insertImages(Container *sequence_,MagickCore::Image* images_) 1872 { 1873 MagickCore::Image 1874 *image, 1875 *next; 1876 1877 image=images_; 1878 while (image != (MagickCore::Image *) NULL) 1879 { 1880 next=image->next; 1881 image->next=(MagickCore::Image *) NULL; 1882 1883 if (next != (MagickCore::Image *) NULL) 1884 next->previous=(MagickCore::Image *) NULL; 1885 1886 sequence_->push_back(Magick::Image(image)); 1887 1888 image=next; 1889 } 1890 } 1891 1892 // Link images together into an image list based on the ordering of 1893 // the container implied by the iterator. This step is done in 1894 // preparation for use with ImageMagick functions which operate on 1895 // lists of images. 1896 // Images are selected by range, first_ to last_ so that a subset of 1897 // the container may be selected. Specify first_ via the 1898 // container's begin() method and last_ via the container's end() 1899 // method in order to specify the entire container. 1900 template<class InputIterator> linkImages(InputIterator first_,InputIterator last_)1901 bool linkImages(InputIterator first_,InputIterator last_) 1902 { 1903 MagickCore::Image 1904 *current, 1905 *previous; 1906 1907 ::ssize_t 1908 scene; 1909 1910 scene=0; 1911 previous=(MagickCore::Image *) NULL; 1912 for (InputIterator iter = first_; iter != last_; ++iter) 1913 { 1914 // Unless we reduce the reference count to one, the same image 1915 // structure may occur more than once in the container, causing 1916 // the linked list to fail. 1917 iter->modifyImage(); 1918 1919 current=iter->image(); 1920 1921 current->previous=previous; 1922 current->next=(MagickCore::Image *) NULL; 1923 current->scene=scene++; 1924 1925 if (previous != (MagickCore::Image *) NULL) 1926 previous->next=current; 1927 1928 previous=current; 1929 } 1930 return(scene > 0 ? true : false); 1931 } 1932 1933 // Restores the channel mask of the images. 1934 template<class InputIterator, class Container> restoreChannelMaskImages(InputIterator first_,InputIterator last_,Container * container_)1935 void restoreChannelMaskImages(InputIterator first_,InputIterator last_, 1936 Container *container_) 1937 { 1938 typename Container::iterator 1939 channel_mask; 1940 1941 channel_mask=container_->begin(); 1942 for (InputIterator iter = first_; iter != last_; ++iter) 1943 { 1944 iter->modifyImage(); 1945 (void) MagickCore::SetImageChannelMask(iter->image(), 1946 (const MagickCore::ChannelType) *channel_mask); 1947 channel_mask++; 1948 } 1949 } 1950 1951 // Remove links added by linkImages. This should be called after the 1952 // ImageMagick function call has completed to reset the image list 1953 // back to its pristine un-linked state. 1954 template<class InputIterator> unlinkImages(InputIterator first_,InputIterator last_)1955 void unlinkImages(InputIterator first_,InputIterator last_) 1956 { 1957 MagickCore::Image 1958 *image; 1959 1960 for (InputIterator iter = first_; iter != last_; ++iter) 1961 { 1962 image=iter->image(); 1963 image->previous=(MagickCore::Image *) NULL; 1964 image->next=(MagickCore::Image *) NULL; 1965 } 1966 } 1967 1968 /////////////////////////////////////////////////////////////////// 1969 // 1970 // Template definitions for documented API 1971 // 1972 /////////////////////////////////////////////////////////////////// 1973 1974 template <class InputIterator> animateImages(InputIterator first_,InputIterator last_)1975 void animateImages( InputIterator first_,InputIterator last_) 1976 { 1977 if (linkImages(first_,last_) == false) 1978 return; 1979 GetPPException; 1980 MagickCore::AnimateImages(first_->imageInfo(),first_->image(), 1981 exceptionInfo); 1982 unlinkImages(first_,last_); 1983 ThrowPPException(first_->quiet()); 1984 } 1985 1986 // Append images from list into single image in either horizontal or 1987 // vertical direction. 1988 template <class InputIterator> 1989 void appendImages( Image *appendedImage_, 1990 InputIterator first_, 1991 InputIterator last_, 1992 bool stack_ = false) { 1993 if (linkImages(first_,last_) == false) 1994 return; 1995 GetPPException; 1996 MagickCore::Image* image = MagickCore::AppendImages( first_->image(), 1997 (MagickBooleanType) stack_, 1998 exceptionInfo ); 1999 unlinkImages( first_, last_ ); 2000 appendedImage_->replaceImage( image ); 2001 ThrowPPException(appendedImage_->quiet()); 2002 } 2003 2004 // Adds the names of the artifacts of the image to the container. 2005 template <class Container> artifactNames(Container * names_,const Image * image_)2006 void artifactNames(Container *names_,const Image* image_) 2007 { 2008 const char* 2009 name; 2010 2011 names_->clear(); 2012 2013 MagickCore::ResetImageArtifactIterator(image_->constImage()); 2014 name=MagickCore::GetNextImageArtifact(image_->constImage()); 2015 while (name != (const char *) NULL) 2016 { 2017 names_->push_back(std::string(name)); 2018 name=MagickCore::GetNextImageArtifact(image_->constImage()); 2019 } 2020 } 2021 2022 // Adds the names of the attributes of the image to the container. 2023 template <class Container> attributeNames(Container * names_,const Image * image_)2024 void attributeNames(Container *names_,const Image* image_) 2025 { 2026 const char* 2027 name; 2028 2029 names_->clear(); 2030 2031 MagickCore::ResetImagePropertyIterator(image_->constImage()); 2032 name=MagickCore::GetNextImageProperty(image_->constImage()); 2033 while (name != (const char *) NULL) 2034 { 2035 names_->push_back(std::string(name)); 2036 name=MagickCore::GetNextImageProperty(image_->constImage()); 2037 } 2038 } 2039 2040 // Average a set of images. 2041 // All the input images must be the same size in pixels. 2042 template <class InputIterator> averageImages(Image * averagedImage_,InputIterator first_,InputIterator last_)2043 void averageImages( Image *averagedImage_, 2044 InputIterator first_, 2045 InputIterator last_ ) { 2046 if (linkImages(first_,last_) == false) 2047 return; 2048 GetPPException; 2049 MagickCore::Image* image = MagickCore::EvaluateImages( first_->image(), 2050 MagickCore::MeanEvaluateOperator, exceptionInfo ); 2051 unlinkImages( first_, last_ ); 2052 averagedImage_->replaceImage( image ); 2053 ThrowPPException(averagedImage_->quiet()); 2054 } 2055 2056 // Merge a sequence of images. 2057 // This is useful for GIF animation sequences that have page 2058 // offsets and disposal methods. A container to contain 2059 // the updated image sequence is passed via the coalescedImages_ 2060 // option. 2061 template <class InputIterator, class Container > coalesceImages(Container * coalescedImages_,InputIterator first_,InputIterator last_)2062 void coalesceImages(Container *coalescedImages_,InputIterator first_, 2063 InputIterator last_) 2064 { 2065 bool 2066 quiet; 2067 2068 MagickCore::Image 2069 *images; 2070 2071 if (linkImages(first_,last_) == false) 2072 return; 2073 2074 GetPPException; 2075 quiet=first_->quiet(); 2076 images=MagickCore::CoalesceImages(first_->image(),exceptionInfo); 2077 2078 // Unlink image list 2079 unlinkImages(first_,last_); 2080 2081 // Ensure container is empty 2082 coalescedImages_->clear(); 2083 2084 // Move images to container 2085 insertImages(coalescedImages_,images); 2086 2087 // Report any error 2088 ThrowPPException(quiet); 2089 } 2090 2091 // Return format coders matching specified conditions. 2092 // 2093 // The default (if no match terms are supplied) is to return all 2094 // available format coders. 2095 // 2096 // For example, to return all readable formats: 2097 // list<CoderInfo> coderList; 2098 // coderInfoList( &coderList, CoderInfo::TrueMatch, CoderInfo::AnyMatch, CoderInfo::AnyMatch) 2099 // 2100 template <class Container > 2101 void coderInfoList( Container *container_, 2102 CoderInfo::MatchType isReadable_ = CoderInfo::AnyMatch, 2103 CoderInfo::MatchType isWritable_ = CoderInfo::AnyMatch, 2104 CoderInfo::MatchType isMultiFrame_ = CoderInfo::AnyMatch 2105 ) { 2106 // Obtain first entry in MagickInfo list 2107 size_t number_formats; 2108 GetPPException; 2109 char **coder_list = 2110 MagickCore::GetMagickList( "*", &number_formats, exceptionInfo ); 2111 if( !coder_list ) 2112 { 2113 throwException(exceptionInfo); 2114 throwExceptionExplicit(MagickCore::MissingDelegateError, 2115 "Coder array not returned!", 0 ); 2116 } 2117 2118 // Clear out container 2119 container_->clear(); 2120 2121 for ( ::ssize_t i=0; i < (::ssize_t) number_formats; i++) 2122 { 2123 const MagickCore::MagickInfo *magick_info = 2124 MagickCore::GetMagickInfo( coder_list[i], exceptionInfo ); 2125 coder_list[i]=(char *) 2126 MagickCore::RelinquishMagickMemory( coder_list[i] ); 2127 2128 // Skip stealth coders 2129 if ( MagickCore::GetMagickStealth(magick_info) ) 2130 continue; 2131 2132 try { 2133 CoderInfo coderInfo( magick_info->name ); 2134 2135 // Test isReadable_ 2136 if ( isReadable_ != CoderInfo::AnyMatch && 2137 (( coderInfo.isReadable() && isReadable_ != CoderInfo::TrueMatch ) || 2138 ( !coderInfo.isReadable() && isReadable_ != CoderInfo::FalseMatch )) ) 2139 continue; 2140 2141 // Test isWritable_ 2142 if ( isWritable_ != CoderInfo::AnyMatch && 2143 (( coderInfo.isWritable() && isWritable_ != CoderInfo::TrueMatch ) || 2144 ( !coderInfo.isWritable() && isWritable_ != CoderInfo::FalseMatch )) ) 2145 continue; 2146 2147 // Test isMultiFrame_ 2148 if ( isMultiFrame_ != CoderInfo::AnyMatch && 2149 (( coderInfo.isMultiFrame() && isMultiFrame_ != CoderInfo::TrueMatch ) || 2150 ( !coderInfo.isMultiFrame() && isMultiFrame_ != CoderInfo::FalseMatch )) ) 2151 continue; 2152 2153 // Append matches to container 2154 container_->push_back( coderInfo ); 2155 } 2156 // Intentionally ignore missing module errors catch(Magick::ErrorModule &)2157 catch (Magick::ErrorModule&) 2158 { 2159 continue; 2160 } 2161 } 2162 coder_list=(char **) MagickCore::RelinquishMagickMemory( coder_list ); 2163 ThrowPPException(false); 2164 } 2165 2166 // 2167 // Fill container with color histogram. 2168 // Entries are of type "std::pair<Color,size_t>". Use the pair 2169 // "first" member to access the Color and the "second" member to access 2170 // the number of times the color occurs in the image. 2171 // 2172 // For example: 2173 // 2174 // Using <map>: 2175 // 2176 // Image image("image.miff"); 2177 // map<Color,size_t> histogram; 2178 // colorHistogram( &histogram, image ); 2179 // std::map<Color,size_t>::const_iterator p=histogram.begin(); 2180 // while (p != histogram.end()) 2181 // { 2182 // cout << setw(10) << (int)p->second << ": (" 2183 // << setw(quantum_width) << (int)p->first.redQuantum() << "," 2184 // << setw(quantum_width) << (int)p->first.greenQuantum() << "," 2185 // << setw(quantum_width) << (int)p->first.blueQuantum() << ")" 2186 // << endl; 2187 // p++; 2188 // } 2189 // 2190 // Using <vector>: 2191 // 2192 // Image image("image.miff"); 2193 // std::vector<std::pair<Color,size_t> > histogram; 2194 // colorHistogram( &histogram, image ); 2195 // std::vector<std::pair<Color,size_t> >::const_iterator p=histogram.begin(); 2196 // while (p != histogram.end()) 2197 // { 2198 // cout << setw(10) << (int)p->second << ": (" 2199 // << setw(quantum_width) << (int)p->first.redQuantum() << "," 2200 // << setw(quantum_width) << (int)p->first.greenQuantum() << "," 2201 // << setw(quantum_width) << (int)p->first.blueQuantum() << ")" 2202 // << endl; 2203 // p++; 2204 // } 2205 2206 template <class Container > colorHistogram(Container * histogram_,const Image image)2207 void colorHistogram( Container *histogram_, const Image image) 2208 { 2209 GetPPException; 2210 2211 // Obtain histogram array 2212 size_t colors; 2213 MagickCore::PixelInfo *histogram_array = 2214 MagickCore::GetImageHistogram( image.constImage(), &colors, exceptionInfo ); 2215 ThrowPPException(image.quiet()); 2216 2217 // Clear out container 2218 histogram_->clear(); 2219 2220 // Transfer histogram array to container 2221 for ( size_t i=0; i < colors; i++) 2222 { 2223 histogram_->insert( histogram_->end(), std::pair<const Color,size_t> 2224 ( Color(histogram_array[i]), (size_t) histogram_array[i].count) ); 2225 } 2226 2227 // Deallocate histogram array 2228 histogram_array=(MagickCore::PixelInfo *) 2229 MagickCore::RelinquishMagickMemory(histogram_array); 2230 } 2231 2232 // Combines one or more images into a single image. The grayscale value of 2233 // the pixels of each image in the sequence is assigned in order to the 2234 // specified channels of the combined image. The typical ordering would be 2235 // image 1 => Red, 2 => Green, 3 => Blue, etc. 2236 template<class InputIterator > 2237 void combineImages(Image *combinedImage_,InputIterator first_, 2238 InputIterator last_,const ChannelType channel_, 2239 const ColorspaceType colorspace_ = MagickCore::sRGBColorspace) 2240 { 2241 MagickCore::Image 2242 *image; 2243 2244 std::vector<ChannelType> 2245 channelMask; 2246 2247 if (linkImages(first_,last_) == false) 2248 return; 2249 GetPPException; 2250 channelMaskImages(first_,last_,&channelMask,channel_); 2251 image=CombineImages(first_->image(),colorspace_,exceptionInfo); 2252 restoreChannelMaskImages(first_,last_,&channelMask); 2253 unlinkImages(first_,last_); 2254 combinedImage_->replaceImage(image); 2255 ThrowPPException(combinedImage_->quiet()); 2256 } 2257 2258 template <class Container> cropToTiles(Container * tiledImages_,const Image image_,const Geometry & geometry_)2259 void cropToTiles(Container *tiledImages_,const Image image_, 2260 const Geometry &geometry_) 2261 { 2262 GetPPException; 2263 MagickCore::Image* images=CropImageToTiles(image_.constImage(), 2264 static_cast<std::string>(geometry_).c_str(),exceptionInfo); 2265 tiledImages_->clear(); 2266 insertImages(tiledImages_,images); 2267 ThrowPPException(image_.quiet()); 2268 } 2269 2270 // Break down an image sequence into constituent parts. This is 2271 // useful for creating GIF or MNG animation sequences. 2272 template<class InputIterator,class Container> deconstructImages(Container * deconstructedImages_,InputIterator first_,InputIterator last_)2273 void deconstructImages(Container *deconstructedImages_, 2274 InputIterator first_,InputIterator last_) 2275 { 2276 bool 2277 quiet; 2278 2279 MagickCore::Image 2280 *images; 2281 2282 if (linkImages(first_,last_) == false) 2283 return; 2284 GetPPException; 2285 quiet=first_->quiet(); 2286 images=CompareImagesLayers(first_->image(),CompareAnyLayer,exceptionInfo); 2287 unlinkImages(first_,last_); 2288 2289 deconstructedImages_->clear(); 2290 insertImages(deconstructedImages_,images); 2291 2292 ThrowPPException(quiet); 2293 } 2294 2295 // 2296 // Display an image sequence 2297 // 2298 template <class InputIterator> displayImages(InputIterator first_,InputIterator last_)2299 void displayImages(InputIterator first_,InputIterator last_) 2300 { 2301 if (linkImages(first_,last_) == false) 2302 return; 2303 GetPPException; 2304 MagickCore::DisplayImages(first_->imageInfo(),first_->image(), 2305 exceptionInfo); 2306 unlinkImages(first_,last_); 2307 ThrowPPException(first_->quiet()); 2308 } 2309 2310 // Applies a value to the image with an arithmetic, relational, 2311 // or logical operator to an image. Use these operations to lighten or darken 2312 // an image, to increase or decrease contrast in an image, or to produce the 2313 // "negative" of an image. 2314 template <class InputIterator > evaluateImages(Image * evaluatedImage_,InputIterator first_,InputIterator last_,const MagickEvaluateOperator operator_)2315 void evaluateImages( Image *evaluatedImage_, 2316 InputIterator first_, 2317 InputIterator last_, 2318 const MagickEvaluateOperator operator_ ) { 2319 if (linkImages(first_,last_) == false) 2320 return; 2321 GetPPException; 2322 MagickCore::Image* image = EvaluateImages( first_->image(), operator_, exceptionInfo ); 2323 unlinkImages( first_, last_ ); 2324 evaluatedImage_->replaceImage( image ); 2325 ThrowPPException(evaluatedImage_->quiet()); 2326 } 2327 2328 // Merge a sequence of image frames which represent image layers. 2329 // This is useful for combining Photoshop layers into a single image. 2330 template <class InputIterator> flattenImages(Image * flattendImage_,InputIterator first_,InputIterator last_)2331 void flattenImages( Image *flattendImage_, 2332 InputIterator first_, 2333 InputIterator last_ ) { 2334 if (linkImages(first_,last_) == false) 2335 return; 2336 GetPPException; 2337 MagickCore::Image* image = MagickCore::MergeImageLayers( first_->image(), 2338 FlattenLayer,exceptionInfo ); 2339 unlinkImages( first_, last_ ); 2340 flattendImage_->replaceImage( image ); 2341 ThrowPPException(flattendImage_->quiet()); 2342 } 2343 2344 // Implements the discrete Fourier transform (DFT) of the image either as a 2345 // magnitude / phase or real / imaginary image pair. 2346 template <class Container > forwardFourierTransformImage(Container * fourierImages_,const Image & image_)2347 void forwardFourierTransformImage( Container *fourierImages_, 2348 const Image &image_ ) { 2349 GetPPException; 2350 2351 // Build image list 2352 MagickCore::Image* images = ForwardFourierTransformImage( 2353 image_.constImage(), MagickTrue, exceptionInfo); 2354 2355 // Ensure container is empty 2356 fourierImages_->clear(); 2357 2358 // Move images to container 2359 insertImages( fourierImages_, images ); 2360 2361 // Report any error 2362 ThrowPPException(image_.quiet()); 2363 } 2364 template <class Container > forwardFourierTransformImage(Container * fourierImages_,const Image & image_,const bool magnitude_)2365 void forwardFourierTransformImage( Container *fourierImages_, 2366 const Image &image_, const bool magnitude_ ) { 2367 GetPPException; 2368 2369 // Build image list 2370 MagickCore::Image* images = ForwardFourierTransformImage( 2371 image_.constImage(), magnitude_ == true ? MagickTrue : MagickFalse, 2372 exceptionInfo); 2373 2374 // Ensure container is empty 2375 fourierImages_->clear(); 2376 2377 // Move images to container 2378 insertImages( fourierImages_, images ); 2379 2380 // Report any error 2381 ThrowPPException(image_.quiet()); 2382 } 2383 2384 // Applies a mathematical expression to a sequence of images. 2385 template <class InputIterator> fxImages(Image * fxImage_,InputIterator first_,InputIterator last_,const std::string expression)2386 void fxImages(Image *fxImage_,InputIterator first_,InputIterator last_, 2387 const std::string expression) 2388 { 2389 MagickCore::Image 2390 *image; 2391 2392 if (linkImages(first_,last_) == false) 2393 return; 2394 GetPPException; 2395 image=FxImage(first_->constImage(),expression.c_str(),exceptionInfo); 2396 unlinkImages(first_,last_); 2397 fxImage_->replaceImage(image); 2398 ThrowPPException(fxImage_->quiet()); 2399 } 2400 2401 // Replace the colors of a sequence of images with the closest color 2402 // from a reference image. 2403 // Set dither_ to true to enable dithering. Set measureError_ to 2404 // true in order to evaluate quantization error. 2405 template<class InputIterator> 2406 void mapImages(InputIterator first_,InputIterator last_, 2407 const Image& mapImage_,bool dither_=false,bool measureError_=false) 2408 { 2409 MagickCore::Image 2410 *image; 2411 2412 MagickCore::QuantizeInfo 2413 quantizeInfo; 2414 2415 if (linkImages(first_,last_) == false) 2416 return; 2417 GetPPException; 2418 MagickCore::GetQuantizeInfo(&quantizeInfo); 2419 quantizeInfo.dither_method = dither_ ? MagickCore::RiemersmaDitherMethod : 2420 MagickCore::NoDitherMethod; 2421 MagickCore::RemapImages(&quantizeInfo,first_->image(), 2422 (mapImage_.isValid() ? mapImage_.constImage() : 2423 (const MagickCore::Image*) NULL),exceptionInfo); 2424 unlinkImages(first_,last_); 2425 if (exceptionInfo->severity != MagickCore::UndefinedException) 2426 { 2427 unlinkImages(first_,last_); 2428 throwException(exceptionInfo,mapImage_.quiet()); 2429 } 2430 2431 image=first_->image(); 2432 while(image != (MagickCore::Image *) NULL) 2433 { 2434 // Calculate quantization error 2435 if (measureError_) 2436 { 2437 MagickCore::GetImageQuantizeError(image,exceptionInfo); 2438 if (exceptionInfo->severity > MagickCore::UndefinedException) 2439 { 2440 unlinkImages(first_,last_); 2441 throwException(exceptionInfo,mapImage_.quiet()); 2442 } 2443 } 2444 2445 // Update DirectClass representation of pixels 2446 MagickCore::SyncImage(image,exceptionInfo); 2447 if (exceptionInfo->severity > MagickCore::UndefinedException) 2448 { 2449 unlinkImages(first_,last_); 2450 throwException(exceptionInfo,mapImage_.quiet()); 2451 } 2452 2453 // Next image 2454 image=image->next; 2455 } 2456 2457 unlinkImages(first_,last_); 2458 (void) MagickCore::DestroyExceptionInfo(exceptionInfo); 2459 } 2460 2461 // Composes all the image layers from the current given 2462 // image onward to produce a single image of the merged layers. 2463 template <class InputIterator > mergeImageLayers(Image * mergedImage_,InputIterator first_,InputIterator last_,const LayerMethod method_)2464 void mergeImageLayers( Image *mergedImage_, 2465 InputIterator first_, 2466 InputIterator last_, 2467 const LayerMethod method_ ) { 2468 if (linkImages(first_,last_) == false) 2469 return; 2470 GetPPException; 2471 MagickCore::Image* image = MergeImageLayers( first_->image(), method_, exceptionInfo ); 2472 unlinkImages( first_, last_ ); 2473 mergedImage_->replaceImage( image ); 2474 ThrowPPException(mergedImage_->quiet()); 2475 } 2476 2477 // Create a composite image by combining several separate images. 2478 template <class Container, class InputIterator> montageImages(Container * montageImages_,InputIterator first_,InputIterator last_,const Montage & options_)2479 void montageImages(Container *montageImages_,InputIterator first_, 2480 InputIterator last_,const Montage &options_) 2481 { 2482 bool 2483 quiet; 2484 2485 MagickCore::Image 2486 *images; 2487 2488 MagickCore::MontageInfo 2489 *montageInfo; 2490 2491 if (linkImages(first_,last_) == false) 2492 return; 2493 2494 montageInfo=static_cast<MagickCore::MontageInfo*>( 2495 MagickCore::AcquireMagickMemory(sizeof(MagickCore::MontageInfo))); 2496 2497 // Update montage options with those set in montageOpts_ 2498 options_.updateMontageInfo(*montageInfo); 2499 2500 // Update options which must transfer to image options 2501 if (options_.label().length() != 0) 2502 first_->label(options_.label()); 2503 2504 // Do montage 2505 GetPPException; 2506 quiet=first_->quiet(); 2507 images=MagickCore::MontageImages(first_->image(),montageInfo, 2508 exceptionInfo); 2509 2510 // Unlink linked image list 2511 unlinkImages(first_,last_); 2512 2513 // Reset output container to pristine state 2514 montageImages_->clear(); 2515 2516 if (images != (MagickCore::Image *) NULL) 2517 insertImages(montageImages_,images); 2518 2519 // Clean up any allocated data in montageInfo 2520 MagickCore::DestroyMontageInfo(montageInfo); 2521 2522 // Report any montage error 2523 ThrowPPException(quiet); 2524 2525 // Apply transparency to montage images 2526 if (montageImages_->size() > 0 && options_.transparentColor().isValid()) 2527 for_each(montageImages_->begin(),montageImages_->end(),transparentImage( 2528 options_.transparentColor())); 2529 } 2530 2531 // Morph a set of images 2532 template <class InputIterator, class Container > morphImages(Container * morphedImages_,InputIterator first_,InputIterator last_,size_t frames_)2533 void morphImages(Container *morphedImages_,InputIterator first_, 2534 InputIterator last_,size_t frames_) 2535 { 2536 bool 2537 quiet; 2538 2539 MagickCore::Image 2540 *images; 2541 2542 if (linkImages(first_,last_) == false) 2543 return; 2544 2545 GetPPException; 2546 quiet=first_->quiet(); 2547 images=MagickCore::MorphImages(first_->image(),frames_,exceptionInfo); 2548 2549 // Unlink image list 2550 unlinkImages(first_,last_); 2551 2552 // Ensure container is empty 2553 morphedImages_->clear(); 2554 2555 // Move images to container 2556 insertImages(morphedImages_,images); 2557 2558 // Report any error 2559 ThrowPPException(quiet); 2560 } 2561 2562 // Inlay a number of images to form a single coherent picture. 2563 template <class InputIterator> mosaicImages(Image * mosaicImage_,InputIterator first_,InputIterator last_)2564 void mosaicImages( Image *mosaicImage_, 2565 InputIterator first_, 2566 InputIterator last_ ) { 2567 if (linkImages(first_,last_) == false) 2568 return; 2569 GetPPException; 2570 MagickCore::Image* image = MagickCore::MergeImageLayers( first_->image(), 2571 MosaicLayer,exceptionInfo ); 2572 unlinkImages( first_, last_ ); 2573 mosaicImage_->replaceImage( image ); 2574 ThrowPPException(mosaicImage_->quiet()); 2575 } 2576 2577 // Compares each image the GIF disposed forms of the previous image in 2578 // the sequence. From this it attempts to select the smallest cropped 2579 // image to replace each frame, while preserving the results of the 2580 // GIF animation. 2581 template <class InputIterator, class Container > optimizeImageLayers(Container * optimizedImages_,InputIterator first_,InputIterator last_)2582 void optimizeImageLayers(Container *optimizedImages_,InputIterator first_, 2583 InputIterator last_) 2584 { 2585 bool 2586 quiet; 2587 2588 MagickCore::Image 2589 *images; 2590 2591 if (linkImages(first_,last_) == false) 2592 return; 2593 2594 GetPPException; 2595 quiet=first_->quiet(); 2596 images=OptimizeImageLayers(first_->image(),exceptionInfo); 2597 2598 unlinkImages(first_,last_); 2599 2600 optimizedImages_->clear(); 2601 2602 insertImages(optimizedImages_,images); 2603 2604 ThrowPPException(quiet); 2605 } 2606 2607 // optimizeImagePlusLayers is exactly as optimizeImageLayers, but may 2608 // also add or even remove extra frames in the animation, if it improves 2609 // the total number of pixels in the resulting GIF animation. 2610 template <class InputIterator, class Container > optimizePlusImageLayers(Container * optimizedImages_,InputIterator first_,InputIterator last_)2611 void optimizePlusImageLayers(Container *optimizedImages_, 2612 InputIterator first_,InputIterator last_ ) 2613 { 2614 bool 2615 quiet; 2616 2617 MagickCore::Image 2618 *images; 2619 2620 if (linkImages(first_,last_) == false) 2621 return; 2622 2623 GetPPException; 2624 quiet=first_->quiet(); 2625 images=OptimizePlusImageLayers(first_->image(),exceptionInfo); 2626 2627 unlinkImages(first_,last_); 2628 2629 optimizedImages_->clear(); 2630 2631 insertImages(optimizedImages_,images); 2632 2633 ThrowPPException(quiet); 2634 } 2635 2636 // Compares each image the GIF disposed forms of the previous image in the 2637 // sequence. Any pixel that does not change the displayed result is replaced 2638 // with transparency. 2639 template<class InputIterator> optimizeTransparency(InputIterator first_,InputIterator last_)2640 void optimizeTransparency(InputIterator first_,InputIterator last_) 2641 { 2642 if (linkImages(first_,last_) == false) 2643 return; 2644 GetPPException; 2645 OptimizeImageTransparency(first_->image(),exceptionInfo); 2646 unlinkImages(first_,last_ ); 2647 2648 ThrowPPException(first_->quiet()); 2649 } 2650 2651 // Ping images into existing container (appending to container) 2652 template<class Container> pingImages(Container * sequence_,const std::string & imageSpec_,ReadOptions & options)2653 void pingImages(Container *sequence_,const std::string &imageSpec_, 2654 ReadOptions &options) 2655 { 2656 options.ping(true); 2657 readImages(sequence_,imageSpec_,options); 2658 } 2659 2660 template<class Container> pingImages(Container * sequence_,const std::string & imageSpec_)2661 void pingImages(Container *sequence_,const std::string &imageSpec_) 2662 { 2663 ReadOptions options; 2664 pingImages(sequence_,imageSpec_,options); 2665 } 2666 2667 template<class Container> pingImages(Container * sequence_,const Blob & blob_,ReadOptions & options)2668 void pingImages(Container *sequence_,const Blob &blob_,ReadOptions &options) 2669 { 2670 options.ping(true); 2671 readImages(sequence_,blob_,options); 2672 } 2673 2674 template<class Container> pingImages(Container * sequence_,const Blob & blob_)2675 void pingImages(Container *sequence_,const Blob &blob_) 2676 { 2677 ReadOptions options; 2678 pingImages(sequence_,blob_,options); 2679 } 2680 2681 // Adds the names of the profiles of the image to the container. 2682 template <class Container> profileNames(Container * names_,const Image * image_)2683 void profileNames(Container *names_,const Image* image_) 2684 { 2685 const char* 2686 name; 2687 2688 names_->clear(); 2689 2690 MagickCore::ResetImageProfileIterator(image_->constImage()); 2691 name=MagickCore::GetNextImageProfile(image_->constImage()); 2692 while (name != (const char *) NULL) 2693 { 2694 names_->push_back(std::string(name)); 2695 name=MagickCore::GetNextImageProfile(image_->constImage()); 2696 } 2697 } 2698 2699 // Quantize colors in images using current quantization settings 2700 // Set measureError_ to true in order to measure quantization error 2701 template <class InputIterator> 2702 void quantizeImages(InputIterator first_,InputIterator last_, 2703 bool measureError_ = false) 2704 { 2705 if (linkImages(first_,last_) == false) 2706 return; 2707 GetPPException; 2708 MagickCore::QuantizeImages(first_->quantizeInfo(),first_->image(), 2709 exceptionInfo); 2710 unlinkImages(first_,last_); 2711 2712 MagickCore::Image *image=first_->image(); 2713 while (image != (MagickCore::Image *) NULL) 2714 { 2715 // Calculate quantization error 2716 if (measureError_) 2717 MagickCore::GetImageQuantizeError(image,exceptionInfo); 2718 2719 // Update DirectClass representation of pixels 2720 MagickCore::SyncImage(image,exceptionInfo); 2721 2722 image=image->next; 2723 } 2724 unlinkImages(first_,last_); 2725 ThrowPPException(first_->quiet()); 2726 } 2727 2728 // Read images into existing container (appending to container) 2729 template<class Container> readImages(Container * sequence_,const std::string & imageSpec_,ReadOptions & options)2730 void readImages(Container *sequence_,const std::string &imageSpec_, 2731 ReadOptions &options) 2732 { 2733 MagickCore::Image 2734 *images; 2735 2736 MagickCore::ImageInfo 2737 *imageInfo; 2738 2739 imageInfo=options.imageInfo(); 2740 imageSpec_.copy(imageInfo->filename,MagickPathExtent-1); 2741 imageInfo->filename[imageSpec_.length()] = 0; 2742 GetPPException; 2743 images=MagickCore::ReadImage(imageInfo,exceptionInfo); 2744 insertImages(sequence_,images); 2745 ThrowPPException(options.quiet()); 2746 } 2747 2748 template<class Container> readImages(Container * sequence_,const std::string & imageSpec_)2749 void readImages(Container *sequence_,const std::string &imageSpec_) 2750 { 2751 ReadOptions options; 2752 readImages(sequence_,imageSpec_,options); 2753 } 2754 2755 template<class Container> readImages(Container * sequence_,const Blob & blob_,ReadOptions & options)2756 void readImages(Container *sequence_,const Blob &blob_,ReadOptions &options) 2757 { 2758 MagickCore::Image 2759 *images; 2760 2761 GetPPException; 2762 images=MagickCore::BlobToImage(options.imageInfo(),blob_.data(), 2763 blob_.length(),exceptionInfo); 2764 insertImages(sequence_,images); 2765 ThrowPPException(options.quiet()); 2766 } 2767 2768 template<class Container> readImages(Container * sequence_,const Blob & blob_)2769 void readImages(Container *sequence_,const Blob &blob_) 2770 { 2771 ReadOptions options; 2772 readImages(sequence_,blob_,options); 2773 } 2774 2775 // Returns a separate grayscale image for each channel specified. 2776 template<class Container> separateImages(Container * separatedImages_,Image & image_,const ChannelType channel_)2777 void separateImages(Container *separatedImages_,Image &image_, 2778 const ChannelType channel_) 2779 { 2780 MagickCore::ChannelType 2781 channel_mask; 2782 2783 MagickCore::Image 2784 *images; 2785 2786 GetPPException; 2787 channel_mask=MagickCore::SetImageChannelMask(image_.image(),channel_); 2788 images=SeparateImages(image_.constImage(),exceptionInfo); 2789 MagickCore::SetPixelChannelMask(image_.image(),channel_mask); 2790 2791 separatedImages_->clear(); 2792 insertImages(separatedImages_,images); 2793 2794 ThrowPPException(image_.quiet()); 2795 } 2796 2797 // Smush images from list into single image in either horizontal or 2798 // vertical direction. 2799 template<class InputIterator> 2800 void smushImages(Image *smushedImage_,InputIterator first_, 2801 InputIterator last_,const ssize_t offset_,bool stack_=false) 2802 { 2803 MagickCore::Image 2804 *newImage; 2805 2806 if (linkImages(first_,last_) == false) 2807 return; 2808 GetPPException; 2809 newImage=MagickCore::SmushImages(first_->constImage(), 2810 (MagickBooleanType) stack_,offset_,exceptionInfo); 2811 unlinkImages(first_,last_); 2812 smushedImage_->replaceImage(newImage); 2813 ThrowPPException(smushedImage_->quiet()); 2814 } 2815 2816 // Write Images 2817 template <class InputIterator> 2818 void writeImages( InputIterator first_, 2819 InputIterator last_, 2820 const std::string &imageSpec_, 2821 bool adjoin_ = true ) { 2822 2823 if (linkImages(first_,last_) == false) 2824 return; 2825 2826 first_->adjoin( adjoin_ ); 2827 2828 GetPPException; 2829 ::ssize_t errorStat = MagickCore::WriteImages( first_->constImageInfo(), 2830 first_->image(), 2831 imageSpec_.c_str(), 2832 exceptionInfo ); 2833 unlinkImages( first_, last_ ); 2834 2835 if ( errorStat != false ) 2836 { 2837 (void) MagickCore::DestroyExceptionInfo( exceptionInfo ); 2838 return; 2839 } 2840 2841 ThrowPPException(first_->quiet()); 2842 } 2843 // Write images to BLOB 2844 template <class InputIterator> 2845 void writeImages( InputIterator first_, 2846 InputIterator last_, 2847 Blob *blob_, 2848 bool adjoin_ = true) { 2849 if (linkImages(first_,last_) == false) 2850 return; 2851 2852 first_->adjoin( adjoin_ ); 2853 2854 GetPPException; 2855 size_t length = 2048; // Efficient size for small images 2856 void* data = MagickCore::ImagesToBlob( first_->imageInfo(), 2857 first_->image(), 2858 &length, 2859 exceptionInfo); 2860 blob_->updateNoCopy( data, length, Magick::Blob::MallocAllocator ); 2861 2862 unlinkImages( first_, last_ ); 2863 2864 ThrowPPException(first_->quiet()); 2865 } 2866 2867 } // namespace Magick 2868 2869 #endif // Magick_STL_header 2870