Home | History | Annotate | Download | only in Magick++
      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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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>
   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 >
   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
   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 >
   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_)
   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>
   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>
   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>
   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 >
   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>
   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 >
   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 >
   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>
   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 >
   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>
   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 >
   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>
   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 >
   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 >
   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>
   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>
   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>
   2661   void pingImages(Container *sequence_,const std::string &imageSpec_)
   2662   {
   2663     ReadOptions options;
   2664     pingImages(sequence_,imageSpec_,options);
   2665   }
   2666 
   2667   template<class Container>
   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>
   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>
   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>
   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>
   2749   void readImages(Container *sequence_,const std::string &imageSpec_)
   2750   {
   2751     ReadOptions options;
   2752     readImages(sequence_,imageSpec_,options);
   2753   }
   2754 
   2755   template<class Container>
   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>
   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>
   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