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