]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
Use SetImageColorMetric() rather than IsImagesEqual()
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                                 Cristy                                      %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include <MagickCore/MagickCore.h>
57 #include "EXTERN.h"
58 #include "perl.h"
59 #include "XSUB.h"
60 #include <math.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264        {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "Sans", { {"matrix", ArrayReference} } },
535     { "Color", { {"color", StringReference} } },
536     { "Mode", { {"geometry", StringReference},
537       {"width", IntegerReference},{"height", IntegerReference},
538       {"channel", MagickChannelOptions} } },
539     { "Statistic", { {"geometry", StringReference},
540       {"width", IntegerReference},{"height", IntegerReference},
541       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
542     { "Perceptible", { {"epsilon", RealReference},
543       {"channel", MagickChannelOptions} } },
544     { "Poly", { {"terms", ArrayReference},
545       {"channel", MagickChannelOptions} } },
546     { "Grayscale", { {"method", MagickNoiseOptions} } },
547     { "CannyEdge", { {"geometry", StringReference},
548       {"radius", RealReference}, {"sigma", RealReference},
549       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
550     { "HoughLine", { {"geometry", StringReference},
551       {"width", IntegerReference}, {"height", IntegerReference},
552       {"threshold", IntegerReference} } },
553     { "MeanShift", { {"geometry", StringReference},
554       {"width", IntegerReference}, {"height", IntegerReference},
555       {"distance", RealReference} } },
556     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
557       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
558     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
559     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
560       {"width", IntegerReference}, {"height", IntegerReference},
561       {"x", IntegerReference}, {"y", IntegerReference},
562       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
563       {"dx", IntegerReference}, {"dy", IntegerReference} } },
564   };
565
566 static SplayTreeInfo
567   *magick_registry = (SplayTreeInfo *) NULL;
568 \f
569 /*
570   Forward declarations.
571 */
572 static Image
573   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
574
575 static ssize_t
576   strEQcase(const char *,const char *);
577 \f
578 /*
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 %                                                                             %
581 %                                                                             %
582 %                                                                             %
583 %   C l o n e P a c k a g e I n f o                                           %
584 %                                                                             %
585 %                                                                             %
586 %                                                                             %
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 %
589 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
590 %  a new one.
591 %
592 %  The format of the ClonePackageInfo routine is:
593 %
594 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
595 %        exception)
596 %
597 %  A description of each parameter follows:
598 %
599 %    o info: a structure of type info.
600 %
601 %    o exception: Return any errors or warnings in this structure.
602 %
603 */
604 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
605   ExceptionInfo *exception)
606 {
607   struct PackageInfo
608     *clone_info;
609
610   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
611   if (clone_info == (struct PackageInfo *) NULL)
612     {
613       ThrowPerlException(exception,ResourceLimitError,
614         "UnableToClonePackageInfo",PackageName);
615       return((struct PackageInfo *) NULL);
616     }
617   if (info == (struct PackageInfo *) NULL)
618     {
619       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
620       return(clone_info);
621     }
622   *clone_info=(*info);
623   clone_info->image_info=CloneImageInfo(info->image_info);
624   return(clone_info);
625 }
626 \f
627 /*
628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 %                                                                             %
630 %                                                                             %
631 %                                                                             %
632 %   c o n s t a n t                                                           %
633 %                                                                             %
634 %                                                                             %
635 %                                                                             %
636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637 %
638 %  constant() returns a double value for the specified name.
639 %
640 %  The format of the constant routine is:
641 %
642 %      double constant(char *name,ssize_t sans)
643 %
644 %  A description of each parameter follows:
645 %
646 %    o value: Method constant returns a double value for the specified name.
647 %
648 %    o name: The name of the constant.
649 %
650 %    o sans: This integer value is not used.
651 %
652 */
653 static double constant(char *name,ssize_t sans)
654 {
655   (void) sans;
656   errno=0;
657   switch (*name)
658   {
659     case 'B':
660     {
661       if (strEQ(name,"BlobError"))
662         return(BlobError);
663       if (strEQ(name,"BlobWarning"))
664         return(BlobWarning);
665       break;
666     }
667     case 'C':
668     {
669       if (strEQ(name,"CacheError"))
670         return(CacheError);
671       if (strEQ(name,"CacheWarning"))
672         return(CacheWarning);
673       if (strEQ(name,"CoderError"))
674         return(CoderError);
675       if (strEQ(name,"CoderWarning"))
676         return(CoderWarning);
677       if (strEQ(name,"ConfigureError"))
678         return(ConfigureError);
679       if (strEQ(name,"ConfigureWarning"))
680         return(ConfigureWarning);
681       if (strEQ(name,"CorruptImageError"))
682         return(CorruptImageError);
683       if (strEQ(name,"CorruptImageWarning"))
684         return(CorruptImageWarning);
685       break;
686     }
687     case 'D':
688     {
689       if (strEQ(name,"DelegateError"))
690         return(DelegateError);
691       if (strEQ(name,"DelegateWarning"))
692         return(DelegateWarning);
693       if (strEQ(name,"DrawError"))
694         return(DrawError);
695       if (strEQ(name,"DrawWarning"))
696         return(DrawWarning);
697       break;
698     }
699     case 'E':
700     {
701       if (strEQ(name,"ErrorException"))
702         return(ErrorException);
703       if (strEQ(name,"ExceptionError"))
704         return(CoderError);
705       if (strEQ(name,"ExceptionWarning"))
706         return(CoderWarning);
707       break;
708     }
709     case 'F':
710     {
711       if (strEQ(name,"FatalErrorException"))
712         return(FatalErrorException);
713       if (strEQ(name,"FileOpenError"))
714         return(FileOpenError);
715       if (strEQ(name,"FileOpenWarning"))
716         return(FileOpenWarning);
717       break;
718     }
719     case 'I':
720     {
721       if (strEQ(name,"ImageError"))
722         return(ImageError);
723       if (strEQ(name,"ImageWarning"))
724         return(ImageWarning);
725       break;
726     }
727     case 'M':
728     {
729       if (strEQ(name,"MaxRGB"))
730         return(QuantumRange);
731       if (strEQ(name,"MissingDelegateError"))
732         return(MissingDelegateError);
733       if (strEQ(name,"MissingDelegateWarning"))
734         return(MissingDelegateWarning);
735       if (strEQ(name,"ModuleError"))
736         return(ModuleError);
737       if (strEQ(name,"ModuleWarning"))
738         return(ModuleWarning);
739       break;
740     }
741     case 'O':
742     {
743       if (strEQ(name,"Opaque"))
744         return(OpaqueAlpha);
745       if (strEQ(name,"OptionError"))
746         return(OptionError);
747       if (strEQ(name,"OptionWarning"))
748         return(OptionWarning);
749       break;
750     }
751     case 'Q':
752     {
753       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
754         return(MAGICKCORE_QUANTUM_DEPTH);
755       if (strEQ(name,"QuantumDepth"))
756         return(MAGICKCORE_QUANTUM_DEPTH);
757       if (strEQ(name,"QuantumRange"))
758         return(QuantumRange);
759       break;
760     }
761     case 'R':
762     {
763       if (strEQ(name,"ResourceLimitError"))
764         return(ResourceLimitError);
765       if (strEQ(name,"ResourceLimitWarning"))
766         return(ResourceLimitWarning);
767       if (strEQ(name,"RegistryError"))
768         return(RegistryError);
769       if (strEQ(name,"RegistryWarning"))
770         return(RegistryWarning);
771       break;
772     }
773     case 'S':
774     {
775       if (strEQ(name,"StreamError"))
776         return(StreamError);
777       if (strEQ(name,"StreamWarning"))
778         return(StreamWarning);
779       if (strEQ(name,"Success"))
780         return(0);
781       break;
782     }
783     case 'T':
784     {
785       if (strEQ(name,"Transparent"))
786         return(TransparentAlpha);
787       if (strEQ(name,"TypeError"))
788         return(TypeError);
789       if (strEQ(name,"TypeWarning"))
790         return(TypeWarning);
791       break;
792     }
793     case 'W':
794     {
795       if (strEQ(name,"WarningException"))
796         return(WarningException);
797       break;
798     }
799     case 'X':
800     {
801       if (strEQ(name,"XServerError"))
802         return(XServerError);
803       if (strEQ(name,"XServerWarning"))
804         return(XServerWarning);
805       break;
806     }
807   }
808   errno=EINVAL;
809   return(0);
810 }
811 \f
812 /*
813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 %                                                                             %
815 %                                                                             %
816 %                                                                             %
817 %   D e s t r o y P a c k a g e I n f o                                       %
818 %                                                                             %
819 %                                                                             %
820 %                                                                             %
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %
823 %  Method DestroyPackageInfo frees a previously created info structure.
824 %
825 %  The format of the DestroyPackageInfo routine is:
826 %
827 %      DestroyPackageInfo(struct PackageInfo *info)
828 %
829 %  A description of each parameter follows:
830 %
831 %    o info: a structure of type info.
832 %
833 */
834 static void DestroyPackageInfo(struct PackageInfo *info)
835 {
836   info->image_info=DestroyImageInfo(info->image_info);
837   info=(struct PackageInfo *) RelinquishMagickMemory(info);
838 }
839 \f
840 /*
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842 %                                                                             %
843 %                                                                             %
844 %                                                                             %
845 %   G e t L i s t                                                             %
846 %                                                                             %
847 %                                                                             %
848 %                                                                             %
849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 %
851 %  Method GetList is recursively called by SetupList to traverse the
852 %  Image__Magick reference.  If building an reference_vector (see SetupList),
853 %  *current is the current position in *reference_vector and *last is the final
854 %  entry in *reference_vector.
855 %
856 %  The format of the GetList routine is:
857 %
858 %      GetList(info)
859 %
860 %  A description of each parameter follows:
861 %
862 %    o info: a structure of type info.
863 %
864 */
865 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
866   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
867 {
868   Image
869     *image;
870
871   if (reference == (SV *) NULL)
872     return(NULL);
873   switch (SvTYPE(reference))
874   {
875     case SVt_PVAV:
876     {
877       AV
878         *av;
879
880       Image
881         *head,
882         *previous;
883
884       register ssize_t
885         i;
886
887       ssize_t
888         n;
889
890       /*
891         Array of images.
892       */
893       previous=(Image *) NULL;
894       head=(Image *) NULL;
895       av=(AV *) reference;
896       n=av_len(av);
897       for (i=0; i <= n; i++)
898       {
899         SV
900           **rv;
901
902         rv=av_fetch(av,i,0);
903         if (rv && *rv && sv_isobject(*rv))
904           {
905             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
906               exception);
907             if (image == (Image *) NULL)
908               continue;
909             if (image == previous)
910               {
911                 image=CloneImage(image,0,0,MagickTrue,exception);
912                 if (image == (Image *) NULL)
913                   return(NULL);
914               }
915             image->previous=previous;
916             *(previous ? &previous->next : &head)=image;
917             for (previous=image; previous->next; previous=previous->next) ;
918           }
919       }
920       return(head);
921     }
922     case SVt_PVMG:
923     {
924       /*
925         Blessed scalar, one image.
926       */
927       image=INT2PTR(Image *,SvIV(reference));
928       if (image == (Image *) NULL)
929         return(NULL);
930       image->previous=(Image *) NULL;
931       image->next=(Image *) NULL;
932       if (reference_vector)
933         {
934           if (*current == *last)
935             {
936               *last+=256;
937               if (*reference_vector == (SV **) NULL)
938                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
939                   sizeof(*reference_vector));
940               else
941                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
942                   *last,sizeof(*reference_vector));
943             }
944           if (*reference_vector == (SV **) NULL)
945             {
946               ThrowPerlException(exception,ResourceLimitError,
947                 "MemoryAllocationFailed",PackageName);
948               return((Image *) NULL);
949             }
950           (*reference_vector)[*current]=reference;
951           (*reference_vector)[++(*current)]=NULL;
952         }
953       return(image);
954     }
955     default:
956       break;
957   }
958   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
959     (double) SvTYPE(reference));
960   return((Image *) NULL);
961 }
962 \f
963 /*
964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 %                                                                             %
966 %                                                                             %
967 %                                                                             %
968 %   G e t P a c k a g e I n f o                                               %
969 %                                                                             %
970 %                                                                             %
971 %                                                                             %
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973 %
974 %  Method GetPackageInfo looks up or creates an info structure for the given
975 %  Image__Magick reference.  If it does create a new one, the information in
976 %  package_info is used to initialize it.
977 %
978 %  The format of the GetPackageInfo routine is:
979 %
980 %      struct PackageInfo *GetPackageInfo(void *reference,
981 %        struct PackageInfo *package_info,ExceptionInfo *exception)
982 %
983 %  A description of each parameter follows:
984 %
985 %    o info: a structure of type info.
986 %
987 %    o exception: Return any errors or warnings in this structure.
988 %
989 */
990 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
991   struct PackageInfo *package_info,ExceptionInfo *exception)
992 {
993   char
994     message[MagickPathExtent];
995
996   struct PackageInfo
997     *clone_info;
998
999   SV
1000     *sv;
1001
1002   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1003     PackageName,XS_VERSION,reference);
1004   sv=perl_get_sv(message,(TRUE | 0x02));
1005   if (sv == (SV *) NULL)
1006     {
1007       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1008         message);
1009       return(package_info);
1010     }
1011   if (SvREFCNT(sv) == 0)
1012     (void) SvREFCNT_inc(sv);
1013   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1014     return(clone_info);
1015   clone_info=ClonePackageInfo(package_info,exception);
1016   sv_setiv(sv,PTR2IV(clone_info));
1017   return(clone_info);
1018 }
1019 \f
1020 /*
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 %                                                                             %
1023 %                                                                             %
1024 %                                                                             %
1025 %   S e t A t t r i b u t e                                                   %
1026 %                                                                             %
1027 %                                                                             %
1028 %                                                                             %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %
1031 %  SetAttribute() sets the attribute to the value in sval.  This can change
1032 %  either or both of image or info.
1033 %
1034 %  The format of the SetAttribute routine is:
1035 %
1036 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1037 %        SV *sval,ExceptionInfo *exception)
1038 %
1039 %  A description of each parameter follows:
1040 %
1041 %    o list: a list of strings.
1042 %
1043 %    o string: a character string.
1044 %
1045 */
1046
1047 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1048 {
1049   char
1050     *q;
1051
1052   double
1053     value;
1054
1055   value=InterpretSiPrefixValue(string,&q);
1056   if (*q == '%')
1057     value*=interval/100.0;
1058   return(value);
1059 }
1060
1061 static inline double StringToDouble(const char *string,char **sentinal)
1062 {
1063   return(InterpretLocaleValue(string,sentinal));
1064 }
1065
1066 static double StringToDoubleInterval(const char *string,const double interval)
1067 {
1068   char
1069     *q;
1070
1071   double
1072     value;
1073
1074   value=InterpretLocaleValue(string,&q);
1075   if (*q == '%')
1076     value*=interval/100.0;
1077   return(value);
1078 }
1079
1080 static inline ssize_t StringToLong(const char *value)
1081 {
1082   return(strtol(value,(char **) NULL,10));
1083 }
1084
1085 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1086   const char *attribute,SV *sval,ExceptionInfo *exception)
1087 {
1088   GeometryInfo
1089     geometry_info;
1090
1091   long
1092     x,
1093     y;
1094
1095   PixelInfo
1096     pixel;
1097
1098   MagickStatusType
1099     flags;
1100
1101   PixelInfo
1102     *color,
1103     target_color;
1104
1105   ssize_t
1106     sp;
1107
1108   switch (*attribute)
1109   {
1110     case 'A':
1111     case 'a':
1112     {
1113       if (LocaleCompare(attribute,"adjoin") == 0)
1114         {
1115           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1116             SvPV(sval,na)) : SvIV(sval);
1117           if (sp < 0)
1118             {
1119               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1120                 SvPV(sval,na));
1121               break;
1122             }
1123           if (info)
1124             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1125           break;
1126         }
1127       if (LocaleCompare(attribute,"alpha") == 0)
1128         {
1129           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1130             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1131           if (sp < 0)
1132             {
1133               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1134                 SvPV(sval,na));
1135               break;
1136             }
1137           for ( ; image; image=image->next)
1138             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1139               exception);
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"antialias") == 0)
1143         {
1144           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1145             SvPV(sval,na)) : SvIV(sval);
1146           if (sp < 0)
1147             {
1148               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1149                 SvPV(sval,na));
1150               break;
1151             }
1152           if (info)
1153             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1154           break;
1155         }
1156       if (LocaleCompare(attribute,"area-limit") == 0)
1157         {
1158           MagickSizeType
1159             limit;
1160
1161           limit=MagickResourceInfinity;
1162           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1163             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1164               100.0);
1165           (void) SetMagickResourceLimit(AreaResource,limit);
1166           break;
1167         }
1168       if (LocaleCompare(attribute,"attenuate") == 0)
1169         {
1170           if (info)
1171             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1172           break;
1173         }
1174       if (LocaleCompare(attribute,"authenticate") == 0)
1175         {
1176           if (info)
1177             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1178           break;
1179         }
1180       if (info)
1181         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1182       for ( ; image; image=image->next)
1183         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1184       break;
1185     }
1186     case 'B':
1187     case 'b':
1188     {
1189       if (LocaleCompare(attribute,"background") == 0)
1190         {
1191           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1192             exception);
1193           if (info)
1194             info->image_info->background_color=target_color;
1195           for ( ; image; image=image->next)
1196             image->background_color=target_color;
1197           break;
1198         }
1199       if (LocaleCompare(attribute,"blue-primary") == 0)
1200         {
1201           for ( ; image; image=image->next)
1202           {
1203             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1204             image->chromaticity.blue_primary.x=geometry_info.rho;
1205             image->chromaticity.blue_primary.y=geometry_info.sigma;
1206             if ((flags & SigmaValue) == 0)
1207               image->chromaticity.blue_primary.y=
1208                 image->chromaticity.blue_primary.x;
1209           }
1210           break;
1211         }
1212       if (LocaleCompare(attribute,"bordercolor") == 0)
1213         {
1214           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1215             exception);
1216           if (info)
1217             info->image_info->border_color=target_color;
1218           for ( ; image; image=image->next)
1219             image->border_color=target_color;
1220           break;
1221         }
1222       if (info)
1223         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1224       for ( ; image; image=image->next)
1225         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1226       break;
1227     }
1228     case 'C':
1229     case 'c':
1230     {
1231       if (LocaleCompare(attribute,"cache-threshold") == 0)
1232         {
1233           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1234             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1235           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1236             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1237           break;
1238         }
1239       if (LocaleCompare(attribute,"clip-mask") == 0)
1240         {
1241           Image
1242             *clip_mask;
1243
1244           clip_mask=(Image *) NULL;
1245           if (SvPOK(sval))
1246             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1247           for ( ; image; image=image->next)
1248             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1249           break;
1250         }
1251       if (LocaleNCompare(attribute,"colormap",8) == 0)
1252         {
1253           for ( ; image; image=image->next)
1254           {
1255             int
1256               items;
1257
1258             long
1259               i;
1260
1261             if (image->storage_class == DirectClass)
1262               continue;
1263             i=0;
1264             items=sscanf(attribute,"%*[^[][%ld",&i);
1265             (void) items;
1266             if (i > (ssize_t) image->colors)
1267               i%=image->colors;
1268             if ((strchr(SvPV(sval,na),',') == 0) ||
1269                 (strchr(SvPV(sval,na),')') != 0))
1270               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1271                 image->colormap+i,exception);
1272             else
1273               {
1274                 color=image->colormap+i;
1275                 pixel.red=color->red;
1276                 pixel.green=color->green;
1277                 pixel.blue=color->blue;
1278                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1279                 pixel.red=geometry_info.rho;
1280                 pixel.green=geometry_info.sigma;
1281                 pixel.blue=geometry_info.xi;
1282                 color->red=ClampToQuantum(pixel.red);
1283                 color->green=ClampToQuantum(pixel.green);
1284                 color->blue=ClampToQuantum(pixel.blue);
1285               }
1286           }
1287           break;
1288         }
1289       if (LocaleCompare(attribute,"colorspace") == 0)
1290         {
1291           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1292             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1293           if (sp < 0)
1294             {
1295               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1296                 SvPV(sval,na));
1297               break;
1298             }
1299           for ( ; image; image=image->next)
1300             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1301               exception);
1302           break;
1303         }
1304       if (LocaleCompare(attribute,"comment") == 0)
1305         {
1306           for ( ; image; image=image->next)
1307             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1308               info ? info->image_info : (ImageInfo *) NULL,image,
1309               SvPV(sval,na),exception),exception);
1310           break;
1311         }
1312       if (LocaleCompare(attribute,"compression") == 0)
1313         {
1314           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1315             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1316           if (sp < 0)
1317             {
1318               ThrowPerlException(exception,OptionError,
1319                 "UnrecognizedImageCompression",SvPV(sval,na));
1320               break;
1321             }
1322           if (info)
1323             info->image_info->compression=(CompressionType) sp;
1324           for ( ; image; image=image->next)
1325             image->compression=(CompressionType) sp;
1326           break;
1327         }
1328       if (info)
1329         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1330       for ( ; image; image=image->next)
1331         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1332       break;
1333     }
1334     case 'D':
1335     case 'd':
1336     {
1337       if (LocaleCompare(attribute,"debug") == 0)
1338         {
1339           SetLogEventMask(SvPV(sval,na));
1340           break;
1341         }
1342       if (LocaleCompare(attribute,"delay") == 0)
1343         {
1344           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1345           for ( ; image; image=image->next)
1346           {
1347             image->delay=(size_t) floor(geometry_info.rho+0.5);
1348             if ((flags & SigmaValue) != 0)
1349               image->ticks_per_second=(ssize_t)
1350                 floor(geometry_info.sigma+0.5);
1351           }
1352           break;
1353         }
1354       if (LocaleCompare(attribute,"disk-limit") == 0)
1355         {
1356           MagickSizeType
1357             limit;
1358
1359           limit=MagickResourceInfinity;
1360           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1361             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1362               100.0);
1363           (void) SetMagickResourceLimit(DiskResource,limit);
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"density") == 0)
1367         {
1368           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1369             {
1370               ThrowPerlException(exception,OptionError,"MissingGeometry",
1371                 SvPV(sval,na));
1372               break;
1373             }
1374           if (info)
1375             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1376           for ( ; image; image=image->next)
1377           {
1378             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1379             image->resolution.x=geometry_info.rho;
1380             image->resolution.y=geometry_info.sigma;
1381             if ((flags & SigmaValue) == 0)
1382               image->resolution.y=image->resolution.x;
1383           }
1384           break;
1385         }
1386       if (LocaleCompare(attribute,"depth") == 0)
1387         {
1388           if (info)
1389             info->image_info->depth=SvIV(sval);
1390           for ( ; image; image=image->next)
1391             (void) SetImageDepth(image,SvIV(sval),exception);
1392           break;
1393         }
1394       if (LocaleCompare(attribute,"dispose") == 0)
1395         {
1396           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1397             SvPV(sval,na)) : SvIV(sval);
1398           if (sp < 0)
1399             {
1400               ThrowPerlException(exception,OptionError,
1401                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1402               break;
1403             }
1404           for ( ; image; image=image->next)
1405             image->dispose=(DisposeType) sp;
1406           break;
1407         }
1408       if (LocaleCompare(attribute,"dither") == 0)
1409         {
1410           if (info)
1411             {
1412               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1413                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1414               if (sp < 0)
1415                 {
1416                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1417                     SvPV(sval,na));
1418                   break;
1419                 }
1420               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1421             }
1422           break;
1423         }
1424       if (LocaleCompare(attribute,"display") == 0)
1425         {
1426           display:
1427           if (info)
1428             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1429           break;
1430         }
1431       if (info)
1432         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1433       for ( ; image; image=image->next)
1434         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1435       break;
1436     }
1437     case 'E':
1438     case 'e':
1439     {
1440       if (LocaleCompare(attribute,"endian") == 0)
1441         {
1442           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1443             SvPV(sval,na)) : SvIV(sval);
1444           if (sp < 0)
1445             {
1446               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1447                 SvPV(sval,na));
1448               break;
1449             }
1450           if (info)
1451             info->image_info->endian=(EndianType) sp;
1452           for ( ; image; image=image->next)
1453             image->endian=(EndianType) sp;
1454           break;
1455         }
1456       if (LocaleCompare(attribute,"extract") == 0)
1457         {
1458           /*
1459             Set image extract geometry.
1460           */
1461           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1462           break;
1463         }
1464       if (info)
1465         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1466       for ( ; image; image=image->next)
1467         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1468       break;
1469     }
1470     case 'F':
1471     case 'f':
1472     {
1473       if (LocaleCompare(attribute,"filename") == 0)
1474         {
1475           if (info)
1476             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1477               MagickPathExtent);
1478           for ( ; image; image=image->next)
1479             (void) CopyMagickString(image->filename,SvPV(sval,na),
1480               MagickPathExtent);
1481           break;
1482         }
1483       if (LocaleCompare(attribute,"file") == 0)
1484         {
1485           FILE
1486             *file;
1487
1488           PerlIO
1489             *io_info;
1490
1491           if (info == (struct PackageInfo *) NULL)
1492             break;
1493           io_info=IoIFP(sv_2io(sval));
1494           if (io_info == (PerlIO *) NULL)
1495             {
1496               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1497                 PackageName);
1498               break;
1499             }
1500           file=PerlIO_findFILE(io_info);
1501           if (file == (FILE *) NULL)
1502             {
1503               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1504                 PackageName);
1505               break;
1506             }
1507           SetImageInfoFile(info->image_info,file);
1508           break;
1509         }
1510       if (LocaleCompare(attribute,"fill") == 0)
1511         {
1512           if (info)
1513             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1514           break;
1515         }
1516       if (LocaleCompare(attribute,"font") == 0)
1517         {
1518           if (info)
1519             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1520           break;
1521         }
1522       if (LocaleCompare(attribute,"foreground") == 0)
1523         break;
1524       if (LocaleCompare(attribute,"fuzz") == 0)
1525         {
1526           if (info)
1527             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1528               QuantumRange+1.0);
1529           for ( ; image; image=image->next)
1530             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1531               QuantumRange+1.0);
1532           break;
1533         }
1534       if (info)
1535         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1536       for ( ; image; image=image->next)
1537         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1538       break;
1539     }
1540     case 'G':
1541     case 'g':
1542     {
1543       if (LocaleCompare(attribute,"gamma") == 0)
1544         {
1545           for ( ; image; image=image->next)
1546             image->gamma=SvNV(sval);
1547           break;
1548         }
1549       if (LocaleCompare(attribute,"gravity") == 0)
1550         {
1551           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1552             SvPV(sval,na)) : SvIV(sval);
1553           if (sp < 0)
1554             {
1555               ThrowPerlException(exception,OptionError,
1556                 "UnrecognizedGravityType",SvPV(sval,na));
1557               break;
1558             }
1559           if (info)
1560             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1561           for ( ; image; image=image->next)
1562             image->gravity=(GravityType) sp;
1563           break;
1564         }
1565       if (LocaleCompare(attribute,"green-primary") == 0)
1566         {
1567           for ( ; image; image=image->next)
1568           {
1569             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1570             image->chromaticity.green_primary.x=geometry_info.rho;
1571             image->chromaticity.green_primary.y=geometry_info.sigma;
1572             if ((flags & SigmaValue) == 0)
1573               image->chromaticity.green_primary.y=
1574                 image->chromaticity.green_primary.x;
1575           }
1576           break;
1577         }
1578       if (info)
1579         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1580       for ( ; image; image=image->next)
1581         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1582       break;
1583     }
1584     case 'I':
1585     case 'i':
1586     {
1587       if (LocaleNCompare(attribute,"index",5) == 0)
1588         {
1589           int
1590             items;
1591
1592           long
1593             index;
1594
1595           register Quantum
1596             *q;
1597
1598           CacheView
1599             *image_view;
1600
1601           for ( ; image; image=image->next)
1602           {
1603             if (image->storage_class != PseudoClass)
1604               continue;
1605             x=0;
1606             y=0;
1607             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1608             (void) items;
1609             image_view=AcquireAuthenticCacheView(image,exception);
1610             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1611             if (q != (Quantum *) NULL)
1612               {
1613                 items=sscanf(SvPV(sval,na),"%ld",&index);
1614                 if ((index >= 0) && (index < (ssize_t) image->colors))
1615                   SetPixelIndex(image,index,q);
1616                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1617               }
1618             image_view=DestroyCacheView(image_view);
1619           }
1620           break;
1621         }
1622       if (LocaleCompare(attribute,"iterations") == 0)
1623         {
1624   iterations:
1625           for ( ; image; image=image->next)
1626             image->iterations=SvIV(sval);
1627           break;
1628         }
1629       if (LocaleCompare(attribute,"interlace") == 0)
1630         {
1631           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1632             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1633           if (sp < 0)
1634             {
1635               ThrowPerlException(exception,OptionError,
1636                 "UnrecognizedInterlaceType",SvPV(sval,na));
1637               break;
1638             }
1639           if (info)
1640             info->image_info->interlace=(InterlaceType) sp;
1641           for ( ; image; image=image->next)
1642             image->interlace=(InterlaceType) sp;
1643           break;
1644         }
1645       if (info)
1646         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1647       for ( ; image; image=image->next)
1648         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1649       break;
1650     }
1651     case 'L':
1652     case 'l':
1653     {
1654       if (LocaleCompare(attribute,"label") == 0)
1655         {
1656           for ( ; image; image=image->next)
1657             (void) SetImageProperty(image,"label",InterpretImageProperties(
1658               info ? info->image_info : (ImageInfo *) NULL,image,
1659               SvPV(sval,na),exception),exception);
1660           break;
1661         }
1662       if (LocaleCompare(attribute,"loop") == 0)
1663         goto iterations;
1664       if (info)
1665         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1666       for ( ; image; image=image->next)
1667         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1668       break;
1669     }
1670     case 'M':
1671     case 'm':
1672     {
1673       if (LocaleCompare(attribute,"magick") == 0)
1674         {
1675           if (info)
1676             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1677               "%s:",SvPV(sval,na));
1678           for ( ; image; image=image->next)
1679             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1680           break;
1681         }
1682       if (LocaleCompare(attribute,"map-limit") == 0)
1683         {
1684           MagickSizeType
1685             limit;
1686
1687           limit=MagickResourceInfinity;
1688           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1689             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1690               100.0);
1691           (void) SetMagickResourceLimit(MapResource,limit);
1692           break;
1693         }
1694       if (LocaleCompare(attribute,"mask") == 0)
1695         {
1696           Image
1697             *mask;
1698
1699           mask=(Image *) NULL;
1700           if (SvPOK(sval))
1701             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1702           for ( ; image; image=image->next)
1703             SetImageMask(image,ReadPixelMask,mask,exception);
1704           break;
1705         }
1706       if (LocaleCompare(attribute,"mattecolor") == 0)
1707         {
1708           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1709             exception);
1710           if (info)
1711             info->image_info->matte_color=target_color;
1712           for ( ; image; image=image->next)
1713             image->matte_color=target_color;
1714           break;
1715         }
1716       if (LocaleCompare(attribute,"matte") == 0)
1717         {
1718           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1719             SvPV(sval,na)) : SvIV(sval);
1720           if (sp < 0)
1721             {
1722               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1723                 SvPV(sval,na));
1724               break;
1725             }
1726           for ( ; image; image=image->next)
1727             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1728           break;
1729         }
1730       if (LocaleCompare(attribute,"memory-limit") == 0)
1731         {
1732           MagickSizeType
1733             limit;
1734
1735           limit=MagickResourceInfinity;
1736           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1737             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1738               100.0);
1739           (void) SetMagickResourceLimit(MemoryResource,limit);
1740           break;
1741         }
1742       if (LocaleCompare(attribute,"monochrome") == 0)
1743         {
1744           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1745             SvPV(sval,na)) : SvIV(sval);
1746           if (sp < 0)
1747             {
1748               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1749                 SvPV(sval,na));
1750               break;
1751             }
1752           if (info)
1753             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1754           for ( ; image; image=image->next)
1755             (void) SetImageType(image,BilevelType,exception);
1756           break;
1757         }
1758       if (info)
1759         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1760       for ( ; image; image=image->next)
1761         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1762       break;
1763     }
1764     case 'O':
1765     case 'o':
1766     {
1767       if (LocaleCompare(attribute,"option") == 0)
1768         {
1769           if (info)
1770             DefineImageOption(info->image_info,SvPV(sval,na));
1771           break;
1772         }
1773       if (LocaleCompare(attribute,"orientation") == 0)
1774         {
1775           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1776             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1777           if (sp < 0)
1778             {
1779               ThrowPerlException(exception,OptionError,
1780                 "UnrecognizedOrientationType",SvPV(sval,na));
1781               break;
1782             }
1783           if (info)
1784             info->image_info->orientation=(OrientationType) sp;
1785           for ( ; image; image=image->next)
1786             image->orientation=(OrientationType) sp;
1787           break;
1788         }
1789       if (info)
1790         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1791       for ( ; image; image=image->next)
1792         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1793       break;
1794     }
1795     case 'P':
1796     case 'p':
1797     {
1798       if (LocaleCompare(attribute,"page") == 0)
1799         {
1800           char
1801             *geometry;
1802
1803           geometry=GetPageGeometry(SvPV(sval,na));
1804           if (info)
1805             (void) CloneString(&info->image_info->page,geometry);
1806           for ( ; image; image=image->next)
1807             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1808           geometry=(char *) RelinquishMagickMemory(geometry);
1809           break;
1810         }
1811       if (LocaleNCompare(attribute,"pixel",5) == 0)
1812         {
1813           int
1814             items;
1815
1816           PixelInfo
1817             pixel;
1818
1819           register Quantum
1820             *q;
1821
1822           CacheView
1823             *image_view;
1824
1825           for ( ; image; image=image->next)
1826           {
1827             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1828               break;
1829             x=0;
1830             y=0;
1831             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1832             (void) items;
1833             image_view=AcquireVirtualCacheView(image,exception);
1834             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1835             if (q != (Quantum *) NULL)
1836               {
1837                 if ((strchr(SvPV(sval,na),',') == 0) ||
1838                     (strchr(SvPV(sval,na),')') != 0))
1839                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1840                     &pixel,exception);
1841                 else
1842                   {
1843                     GetPixelInfo(image,&pixel);
1844                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1845                     pixel.red=geometry_info.rho;
1846                     if ((flags & SigmaValue) != 0)
1847                       pixel.green=geometry_info.sigma;
1848                     if ((flags & XiValue) != 0)
1849                       pixel.blue=geometry_info.xi;
1850                     if ((flags & PsiValue) != 0)
1851                       pixel.alpha=geometry_info.psi;
1852                     if ((flags & ChiValue) != 0)
1853                       pixel.black=geometry_info.chi;
1854                   }
1855                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1856                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1857                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1858                 if (image->colorspace == CMYKColorspace)
1859                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1860                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1861                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1862               }
1863             image_view=DestroyCacheView(image_view);
1864           }
1865           break;
1866         }
1867       if (LocaleCompare(attribute,"pointsize") == 0)
1868         {
1869           if (info)
1870             {
1871               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1872               info->image_info->pointsize=geometry_info.rho;
1873             }
1874           break;
1875         }
1876       if (LocaleCompare(attribute,"preview") == 0)
1877         {
1878           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1879             SvPV(sval,na)) : SvIV(sval);
1880           if (sp < 0)
1881             {
1882               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1883                 SvPV(sval,na));
1884               break;
1885             }
1886           if (info)
1887             info->image_info->preview_type=(PreviewType) sp;
1888           break;
1889         }
1890       if (info)
1891         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1892       for ( ; image; image=image->next)
1893         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1894       break;
1895     }
1896     case 'Q':
1897     case 'q':
1898     {
1899       if (LocaleCompare(attribute,"quality") == 0)
1900         {
1901           if (info)
1902             info->image_info->quality=SvIV(sval);
1903           for ( ; image; image=image->next)
1904             image->quality=SvIV(sval);
1905           break;
1906         }
1907       if (info)
1908         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1909       for ( ; image; image=image->next)
1910         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1911       break;
1912     }
1913     case 'R':
1914     case 'r':
1915     {
1916       if (LocaleCompare(attribute,"read-mask") == 0)
1917         {
1918           Image
1919             *mask;
1920
1921           mask=(Image *) NULL;
1922           if (SvPOK(sval))
1923             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1924           for ( ; image; image=image->next)
1925             SetImageMask(image,ReadPixelMask,mask,exception);
1926           break;
1927         }
1928       if (LocaleCompare(attribute,"red-primary") == 0)
1929         {
1930           for ( ; image; image=image->next)
1931           {
1932             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1933             image->chromaticity.red_primary.x=geometry_info.rho;
1934             image->chromaticity.red_primary.y=geometry_info.sigma;
1935             if ((flags & SigmaValue) == 0)
1936               image->chromaticity.red_primary.y=
1937                 image->chromaticity.red_primary.x;
1938           }
1939           break;
1940         }
1941       if (LocaleCompare(attribute,"render") == 0)
1942         {
1943           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1944             SvPV(sval,na)) : SvIV(sval);
1945           if (sp < 0)
1946             {
1947               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1948                 SvPV(sval,na));
1949               break;
1950             }
1951          for ( ; image; image=image->next)
1952            image->rendering_intent=(RenderingIntent) sp;
1953          break;
1954        }
1955       if (LocaleCompare(attribute,"repage") == 0)
1956         {
1957           RectangleInfo
1958             geometry;
1959
1960           for ( ; image; image=image->next)
1961           {
1962             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1963             if ((flags & WidthValue) != 0)
1964               {
1965                 if ((flags & HeightValue) == 0)
1966                   geometry.height=geometry.width;
1967                 image->page.width=geometry.width;
1968                 image->page.height=geometry.height;
1969               }
1970             if ((flags & AspectValue) != 0)
1971               {
1972                 if ((flags & XValue) != 0)
1973                   image->page.x+=geometry.x;
1974                 if ((flags & YValue) != 0)
1975                   image->page.y+=geometry.y;
1976               }
1977             else
1978               {
1979                 if ((flags & XValue) != 0)
1980                   {
1981                     image->page.x=geometry.x;
1982                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1983                       image->page.width=image->columns+geometry.x;
1984                   }
1985                 if ((flags & YValue) != 0)
1986                   {
1987                     image->page.y=geometry.y;
1988                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1989                       image->page.height=image->rows+geometry.y;
1990                   }
1991               }
1992           }
1993           break;
1994         }
1995       if (info)
1996         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1997       for ( ; image; image=image->next)
1998         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1999       break;
2000     }
2001     case 'S':
2002     case 's':
2003     {
2004       if (LocaleCompare(attribute,"sampling-factor") == 0)
2005         {
2006           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2007             {
2008               ThrowPerlException(exception,OptionError,"MissingGeometry",
2009                 SvPV(sval,na));
2010               break;
2011             }
2012           if (info)
2013             (void) CloneString(&info->image_info->sampling_factor,
2014               SvPV(sval,na));
2015           break;
2016         }
2017       if (LocaleCompare(attribute,"scene") == 0)
2018         {
2019           for ( ; image; image=image->next)
2020             image->scene=SvIV(sval);
2021           break;
2022         }
2023       if (LocaleCompare(attribute,"server") == 0)
2024         goto display;
2025       if (LocaleCompare(attribute,"size") == 0)
2026         {
2027           if (info)
2028             {
2029               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2030                 {
2031                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2032                     SvPV(sval,na));
2033                   break;
2034                 }
2035               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2036             }
2037           break;
2038         }
2039       if (LocaleCompare(attribute,"stroke") == 0)
2040         {
2041           if (info)
2042             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2043           break;
2044         }
2045       if (info)
2046         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2047       for ( ; image; image=image->next)
2048         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2049       break;
2050     }
2051     case 'T':
2052     case 't':
2053     {
2054       if (LocaleCompare(attribute,"texture") == 0)
2055         {
2056           if (info)
2057             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2058           break;
2059         }
2060       if (LocaleCompare(attribute,"thread-limit") == 0)
2061         {
2062           MagickSizeType
2063             limit;
2064
2065           limit=MagickResourceInfinity;
2066           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2067             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2068               100.0);
2069           (void) SetMagickResourceLimit(ThreadResource,limit);
2070           break;
2071         }
2072       if (LocaleCompare(attribute,"tile-offset") == 0)
2073         {
2074           char
2075             *geometry;
2076
2077           geometry=GetPageGeometry(SvPV(sval,na));
2078           if (info)
2079             (void) CloneString(&info->image_info->page,geometry);
2080           for ( ; image; image=image->next)
2081             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2082               exception);
2083           geometry=(char *) RelinquishMagickMemory(geometry);
2084           break;
2085         }
2086       if (LocaleCompare(attribute,"time-limit") == 0)
2087         {
2088           MagickSizeType
2089             limit;
2090
2091           limit=MagickResourceInfinity;
2092           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2093             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2094               100.0);
2095           (void) SetMagickResourceLimit(TimeResource,limit);
2096           break;
2097         }
2098       if (LocaleCompare(attribute,"transparent-color") == 0)
2099         {
2100           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2101             exception);
2102           if (info)
2103             info->image_info->transparent_color=target_color;
2104           for ( ; image; image=image->next)
2105             image->transparent_color=target_color;
2106           break;
2107         }
2108       if (LocaleCompare(attribute,"type") == 0)
2109         {
2110           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2111             SvPV(sval,na)) : SvIV(sval);
2112           if (sp < 0)
2113             {
2114               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2115                 SvPV(sval,na));
2116               break;
2117             }
2118           if (info)
2119             info->image_info->type=(ImageType) sp;
2120           for ( ; image; image=image->next)
2121             SetImageType(image,(ImageType) sp,exception);
2122           break;
2123         }
2124       if (info)
2125         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2126       for ( ; image; image=image->next)
2127         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2128       break;
2129     }
2130     case 'U':
2131     case 'u':
2132     {
2133       if (LocaleCompare(attribute,"units") == 0)
2134         {
2135           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2136             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2137           if (sp < 0)
2138             {
2139               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2140                 SvPV(sval,na));
2141               break;
2142             }
2143           if (info)
2144             info->image_info->units=(ResolutionType) sp;
2145           for ( ; image; image=image->next)
2146           {
2147             ResolutionType
2148               units;
2149
2150             units=(ResolutionType) sp;
2151             if (image->units != units)
2152               switch (image->units)
2153               {
2154                 case UndefinedResolution:
2155                 case PixelsPerInchResolution:
2156                 {
2157                   if (units == PixelsPerCentimeterResolution)
2158                     {
2159                       image->resolution.x*=2.54;
2160                       image->resolution.y*=2.54;
2161                     }
2162                   break;
2163                 }
2164                 case PixelsPerCentimeterResolution:
2165                 {
2166                   if (units == PixelsPerInchResolution)
2167                     {
2168                       image->resolution.x/=2.54;
2169                       image->resolution.y/=2.54;
2170                     }
2171                   break;
2172                 }
2173               }
2174             image->units=units;
2175           }
2176           break;
2177         }
2178       if (info)
2179         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2180       for ( ; image; image=image->next)
2181         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2182       break;
2183     }
2184     case 'V':
2185     case 'v':
2186     {
2187       if (LocaleCompare(attribute,"verbose") == 0)
2188         {
2189           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2190             SvPV(sval,na)) : SvIV(sval);
2191           if (sp < 0)
2192             {
2193               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2194                 SvPV(sval,na));
2195               break;
2196             }
2197           if (info)
2198             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2199           break;
2200         }
2201       if (LocaleCompare(attribute,"view") == 0)
2202         {
2203           if (info)
2204             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2205           break;
2206         }
2207       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2208         {
2209           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2210             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2211           if (sp < 0)
2212             {
2213               ThrowPerlException(exception,OptionError,
2214                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2215               break;
2216             }
2217           for ( ; image; image=image->next)
2218             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2219           break;
2220         }
2221       if (info)
2222         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2223       for ( ; image; image=image->next)
2224         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2225       break;
2226     }
2227     case 'W':
2228     case 'w':
2229     {
2230       if (LocaleCompare(attribute,"white-point") == 0)
2231         {
2232           for ( ; image; image=image->next)
2233           {
2234             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2235             image->chromaticity.white_point.x=geometry_info.rho;
2236             image->chromaticity.white_point.y=geometry_info.sigma;
2237             if ((flags & SigmaValue) == 0)
2238               image->chromaticity.white_point.y=
2239                 image->chromaticity.white_point.x;
2240           }
2241           break;
2242         }
2243       if (LocaleCompare(attribute,"write-mask") == 0)
2244         {
2245           Image
2246             *mask;
2247
2248           mask=(Image *) NULL;
2249           if (SvPOK(sval))
2250             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2251           for ( ; image; image=image->next)
2252             SetImageMask(image,WritePixelMask,mask,exception);
2253           break;
2254         }
2255       if (info)
2256         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2257       for ( ; image; image=image->next)
2258         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2259       break;
2260     }
2261     default:
2262     {
2263       if (info)
2264         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2265       for ( ; image; image=image->next)
2266         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2267       break;
2268     }
2269   }
2270 }
2271 \f
2272 /*
2273 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2274 %                                                                             %
2275 %                                                                             %
2276 %                                                                             %
2277 %   S e t u p L i s t                                                         %
2278 %                                                                             %
2279 %                                                                             %
2280 %                                                                             %
2281 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2282 %
2283 %  Method SetupList returns the list of all the images linked by their
2284 %  image->next and image->previous link lists for use with ImageMagick.  If
2285 %  info is non-NULL, an info structure is returned in *info.  If
2286 %  reference_vector is non-NULL,an array of SV* are returned in
2287 %  *reference_vector.  Reference_vector is used when the images are going to be
2288 %  replaced with new Image*'s.
2289 %
2290 %  The format of the SetupList routine is:
2291 %
2292 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2293 %        SV ***reference_vector,ExceptionInfo *exception)
2294 %
2295 %  A description of each parameter follows:
2296 %
2297 %    o list: a list of strings.
2298 %
2299 %    o string: a character string.
2300 %
2301 %    o exception: Return any errors or warnings in this structure.
2302 %
2303 */
2304 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2305   SV ***reference_vector,ExceptionInfo *exception)
2306 {
2307   Image
2308     *image;
2309
2310   ssize_t
2311     current,
2312     last;
2313
2314   if (reference_vector)
2315     *reference_vector=NULL;
2316   if (info)
2317     *info=NULL;
2318   current=0;
2319   last=0;
2320   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2321   if (info && (SvTYPE(reference) == SVt_PVAV))
2322     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2323       exception);
2324   return(image);
2325 }
2326 \f
2327 /*
2328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2329 %                                                                             %
2330 %                                                                             %
2331 %                                                                             %
2332 %   s t r E Q c a s e                                                         %
2333 %                                                                             %
2334 %                                                                             %
2335 %                                                                             %
2336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2337 %
2338 %  strEQcase() compares two strings and returns 0 if they are the
2339 %  same or if the second string runs out first.  The comparison is case
2340 %  insensitive.
2341 %
2342 %  The format of the strEQcase routine is:
2343 %
2344 %      ssize_t strEQcase(const char *p,const char *q)
2345 %
2346 %  A description of each parameter follows:
2347 %
2348 %    o p: a character string.
2349 %
2350 %    o q: a character string.
2351 %
2352 %
2353 */
2354 static ssize_t strEQcase(const char *p,const char *q)
2355 {
2356   char
2357     c;
2358
2359   register ssize_t
2360     i;
2361
2362   for (i=0 ; (c=(*q)) != 0; i++)
2363   {
2364     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2365         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2366       return(0);
2367     p++;
2368     q++;
2369   }
2370   return(((*q == 0) && (*p == 0)) ? i : 0);
2371 }
2372 \f
2373 /*
2374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2375 %                                                                             %
2376 %                                                                             %
2377 %                                                                             %
2378 %   I m a g e : : M a g i c k                                                 %
2379 %                                                                             %
2380 %                                                                             %
2381 %                                                                             %
2382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2383 %
2384 %
2385 */
2386 MODULE = Image::Magick PACKAGE = Image::Magick
2387
2388 PROTOTYPES: ENABLE
2389
2390 BOOT:
2391   MagickCoreGenesis("PerlMagick",MagickFalse);
2392   SetWarningHandler(NULL);
2393   SetErrorHandler(NULL);
2394   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2395     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2396
2397 void
2398 UNLOAD()
2399   PPCODE:
2400   {
2401     if (magick_registry != (SplayTreeInfo *) NULL)
2402       magick_registry=DestroySplayTree(magick_registry);
2403     MagickCoreTerminus();
2404   }
2405
2406 double
2407 constant(name,argument)
2408   char *name
2409   ssize_t argument
2410 \f
2411 #
2412 ###############################################################################
2413 #                                                                             #
2414 #                                                                             #
2415 #                                                                             #
2416 #   A n i m a t e                                                             #
2417 #                                                                             #
2418 #                                                                             #
2419 #                                                                             #
2420 ###############################################################################
2421 #
2422 #
2423 void
2424 Animate(ref,...)
2425   Image::Magick ref=NO_INIT
2426   ALIAS:
2427     AnimateImage  = 1
2428     animate       = 2
2429     animateimage  = 3
2430   PPCODE:
2431   {
2432     ExceptionInfo
2433       *exception;
2434
2435     Image
2436       *image;
2437
2438     register ssize_t
2439       i;
2440
2441     struct PackageInfo
2442       *info,
2443       *package_info;
2444
2445     SV
2446       *perl_exception,
2447       *reference;
2448
2449     PERL_UNUSED_VAR(ref);
2450     PERL_UNUSED_VAR(ix);
2451     exception=AcquireExceptionInfo();
2452     perl_exception=newSVpv("",0);
2453     package_info=(struct PackageInfo *) NULL;
2454     if (sv_isobject(ST(0)) == 0)
2455       {
2456         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2457           PackageName);
2458         goto PerlException;
2459       }
2460     reference=SvRV(ST(0));
2461     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2462     if (image == (Image *) NULL)
2463       {
2464         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2465           PackageName);
2466         goto PerlException;
2467       }
2468     package_info=ClonePackageInfo(info,exception);
2469     if (items == 2)
2470       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2471     else
2472       if (items > 2)
2473         for (i=2; i < items; i+=2)
2474           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2475             exception);
2476     (void) AnimateImages(package_info->image_info,image,exception);
2477     (void) CatchImageException(image);
2478
2479   PerlException:
2480     if (package_info != (struct PackageInfo *) NULL)
2481       DestroyPackageInfo(package_info);
2482     InheritPerlException(exception,perl_exception);
2483     exception=DestroyExceptionInfo(exception);
2484     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2485     SvPOK_on(perl_exception);
2486     ST(0)=sv_2mortal(perl_exception);
2487     XSRETURN(1);
2488   }
2489 \f
2490 #
2491 ###############################################################################
2492 #                                                                             #
2493 #                                                                             #
2494 #                                                                             #
2495 #   A p p e n d                                                               #
2496 #                                                                             #
2497 #                                                                             #
2498 #                                                                             #
2499 ###############################################################################
2500 #
2501 #
2502 void
2503 Append(ref,...)
2504   Image::Magick ref=NO_INIT
2505   ALIAS:
2506     AppendImage  = 1
2507     append       = 2
2508     appendimage  = 3
2509   PPCODE:
2510   {
2511     AV
2512       *av;
2513
2514     char
2515       *attribute;
2516
2517     ExceptionInfo
2518       *exception;
2519
2520     HV
2521       *hv;
2522
2523     Image
2524       *image;
2525
2526     register ssize_t
2527       i;
2528
2529     ssize_t
2530       stack;
2531
2532     struct PackageInfo
2533       *info;
2534
2535     SV
2536       *av_reference,
2537       *perl_exception,
2538       *reference,
2539       *rv,
2540       *sv;
2541
2542     PERL_UNUSED_VAR(ref);
2543     PERL_UNUSED_VAR(ix);
2544     exception=AcquireExceptionInfo();
2545     perl_exception=newSVpv("",0);
2546     sv=NULL;
2547     attribute=NULL;
2548     av=NULL;
2549     if (sv_isobject(ST(0)) == 0)
2550       {
2551         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2552           PackageName);
2553         goto PerlException;
2554       }
2555     reference=SvRV(ST(0));
2556     hv=SvSTASH(reference);
2557     av=newAV();
2558     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2559     SvREFCNT_dec(av);
2560     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2561     if (image == (Image *) NULL)
2562       {
2563         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2564           PackageName);
2565         goto PerlException;
2566       }
2567     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2568     /*
2569       Get options.
2570     */
2571     stack=MagickTrue;
2572     for (i=2; i < items; i+=2)
2573     {
2574       attribute=(char *) SvPV(ST(i-1),na);
2575       switch (*attribute)
2576       {
2577         case 'S':
2578         case 's':
2579         {
2580           if (LocaleCompare(attribute,"stack") == 0)
2581             {
2582               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2583                 SvPV(ST(i),na));
2584               if (stack < 0)
2585                 {
2586                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2587                     SvPV(ST(i),na));
2588                   return;
2589                 }
2590               break;
2591             }
2592           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2593             attribute);
2594           break;
2595         }
2596         default:
2597         {
2598           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2599             attribute);
2600           break;
2601         }
2602       }
2603     }
2604     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2605     if (image == (Image *) NULL)
2606       goto PerlException;
2607     for ( ; image; image=image->next)
2608     {
2609       AddImageToRegistry(sv,image);
2610       rv=newRV(sv);
2611       av_push(av,sv_bless(rv,hv));
2612       SvREFCNT_dec(sv);
2613     }
2614     exception=DestroyExceptionInfo(exception);
2615     ST(0)=av_reference;
2616     SvREFCNT_dec(perl_exception);
2617     XSRETURN(1);
2618
2619   PerlException:
2620     InheritPerlException(exception,perl_exception);
2621     exception=DestroyExceptionInfo(exception);
2622     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2623     SvPOK_on(perl_exception);
2624     ST(0)=sv_2mortal(perl_exception);
2625     XSRETURN(1);
2626   }
2627 \f
2628 #
2629 ###############################################################################
2630 #                                                                             #
2631 #                                                                             #
2632 #                                                                             #
2633 #   A v e r a g e                                                             #
2634 #                                                                             #
2635 #                                                                             #
2636 #                                                                             #
2637 ###############################################################################
2638 #
2639 #
2640 void
2641 Average(ref)
2642   Image::Magick ref=NO_INIT
2643   ALIAS:
2644     AverageImage   = 1
2645     average        = 2
2646     averageimage   = 3
2647   PPCODE:
2648   {
2649     AV
2650       *av;
2651
2652     char
2653       *p;
2654
2655     ExceptionInfo
2656       *exception;
2657
2658     HV
2659       *hv;
2660
2661     Image
2662       *image;
2663
2664     struct PackageInfo
2665       *info;
2666
2667     SV
2668       *perl_exception,
2669       *reference,
2670       *rv,
2671       *sv;
2672
2673     PERL_UNUSED_VAR(ref);
2674     PERL_UNUSED_VAR(ix);
2675     exception=AcquireExceptionInfo();
2676     perl_exception=newSVpv("",0);
2677     sv=NULL;
2678     if (sv_isobject(ST(0)) == 0)
2679       {
2680         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2681           PackageName);
2682         goto PerlException;
2683       }
2684     reference=SvRV(ST(0));
2685     hv=SvSTASH(reference);
2686     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2687     if (image == (Image *) NULL)
2688       {
2689         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2690           PackageName);
2691         goto PerlException;
2692       }
2693     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2694     if (image == (Image *) NULL)
2695       goto PerlException;
2696     /*
2697       Create blessed Perl array for the returned image.
2698     */
2699     av=newAV();
2700     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2701     SvREFCNT_dec(av);
2702     AddImageToRegistry(sv,image);
2703     rv=newRV(sv);
2704     av_push(av,sv_bless(rv,hv));
2705     SvREFCNT_dec(sv);
2706     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2707     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2708       "average-%.*s",(int) (MagickPathExtent-9),
2709       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2710     (void) CopyMagickString(image->filename,info->image_info->filename,
2711       MagickPathExtent);
2712     SetImageInfo(info->image_info,0,exception);
2713     exception=DestroyExceptionInfo(exception);
2714     SvREFCNT_dec(perl_exception);
2715     XSRETURN(1);
2716
2717   PerlException:
2718     InheritPerlException(exception,perl_exception);
2719     exception=DestroyExceptionInfo(exception);
2720     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2721     SvPOK_on(perl_exception);
2722     ST(0)=sv_2mortal(perl_exception);
2723     XSRETURN(1);
2724   }
2725 \f
2726 #
2727 ###############################################################################
2728 #                                                                             #
2729 #                                                                             #
2730 #                                                                             #
2731 #   B l o b T o I m a g e                                                     #
2732 #                                                                             #
2733 #                                                                             #
2734 #                                                                             #
2735 ###############################################################################
2736 #
2737 #
2738 void
2739 BlobToImage(ref,...)
2740   Image::Magick ref=NO_INIT
2741   ALIAS:
2742     BlobToImage  = 1
2743     blobtoimage  = 2
2744     blobto       = 3
2745   PPCODE:
2746   {
2747     AV
2748       *av;
2749
2750     char
2751       **keep,
2752       **list;
2753
2754     ExceptionInfo
2755       *exception;
2756
2757     HV
2758       *hv;
2759
2760     Image
2761       *image;
2762
2763     register char
2764       **p;
2765
2766     register ssize_t
2767       i;
2768
2769     ssize_t
2770       ac,
2771       n,
2772       number_images;
2773
2774     STRLEN
2775       *length;
2776
2777     struct PackageInfo
2778       *info;
2779
2780     SV
2781       *perl_exception,
2782       *reference,
2783       *rv,
2784       *sv;
2785
2786     PERL_UNUSED_VAR(ref);
2787     PERL_UNUSED_VAR(ix);
2788     exception=AcquireExceptionInfo();
2789     perl_exception=newSVpv("",0);
2790     sv=NULL;
2791     number_images=0;
2792     ac=(items < 2) ? 1 : items-1;
2793     length=(STRLEN *) NULL;
2794     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2795     if (list == (char **) NULL)
2796       {
2797         ThrowPerlException(exception,ResourceLimitError,
2798           "MemoryAllocationFailed",PackageName);
2799         goto PerlException;
2800       }
2801     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2802     if (length == (STRLEN *) NULL)
2803       {
2804         ThrowPerlException(exception,ResourceLimitError,
2805           "MemoryAllocationFailed",PackageName);
2806         goto PerlException;
2807       }
2808     if (sv_isobject(ST(0)) == 0)
2809       {
2810         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2811           PackageName);
2812         goto PerlException;
2813       }
2814     reference=SvRV(ST(0));
2815     hv=SvSTASH(reference);
2816     if (SvTYPE(reference) != SVt_PVAV)
2817       {
2818         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2819           PackageName);
2820         goto PerlException;
2821       }
2822     av=(AV *) reference;
2823     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2824       exception);
2825     n=1;
2826     if (items <= 1)
2827       {
2828         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2829         goto PerlException;
2830       }
2831     for (n=0, i=0; i < ac; i++)
2832     {
2833       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2834       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2835         {
2836           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2837           continue;
2838         }
2839       n++;
2840     }
2841     list[n]=(char *) NULL;
2842     keep=list;
2843     for (i=number_images=0; i < n; i++)
2844     {
2845       image=BlobToImage(info->image_info,list[i],length[i],exception);
2846       if (image == (Image *) NULL)
2847         break;
2848       for ( ; image; image=image->next)
2849       {
2850         AddImageToRegistry(sv,image);
2851         rv=newRV(sv);
2852         av_push(av,sv_bless(rv,hv));
2853         SvREFCNT_dec(sv);
2854         number_images++;
2855       }
2856     }
2857     /*
2858       Free resources.
2859     */
2860     for (i=0; i < n; i++)
2861       if (list[i] != (char *) NULL)
2862         for (p=keep; list[i] != *p++; )
2863           if (*p == (char *) NULL)
2864             {
2865               list[i]=(char *) RelinquishMagickMemory(list[i]);
2866               break;
2867             }
2868
2869   PerlException:
2870     if (list)
2871       list=(char **) RelinquishMagickMemory(list);
2872     if (length)
2873       length=(STRLEN *) RelinquishMagickMemory(length);
2874     InheritPerlException(exception,perl_exception);
2875     exception=DestroyExceptionInfo(exception);
2876     sv_setiv(perl_exception,(IV) number_images);
2877     SvPOK_on(perl_exception);
2878     ST(0)=sv_2mortal(perl_exception);
2879     XSRETURN(1);
2880   }
2881 \f
2882 #
2883 ###############################################################################
2884 #                                                                             #
2885 #                                                                             #
2886 #                                                                             #
2887 #   C h a n n e l F x                                                         #
2888 #                                                                             #
2889 #                                                                             #
2890 #                                                                             #
2891 ###############################################################################
2892 #
2893 #
2894 void
2895 ChannelFx(ref,...)
2896   Image::Magick ref=NO_INIT
2897   ALIAS:
2898     ChannelFxImage  = 1
2899     channelfx       = 2
2900     channelfximage  = 3
2901   PPCODE:
2902   {
2903     AV
2904       *av;
2905
2906     char
2907       *attribute,
2908       expression[MagickPathExtent];
2909
2910     ChannelType
2911       channel,
2912       channel_mask;
2913
2914     ExceptionInfo
2915       *exception;
2916
2917     HV
2918       *hv;
2919
2920     Image
2921       *image;
2922
2923     register ssize_t
2924       i;
2925
2926     struct PackageInfo
2927       *info;
2928
2929     SV
2930       *av_reference,
2931       *perl_exception,
2932       *reference,
2933       *rv,
2934       *sv;
2935
2936     PERL_UNUSED_VAR(ref);
2937     PERL_UNUSED_VAR(ix);
2938     exception=AcquireExceptionInfo();
2939     perl_exception=newSVpv("",0);
2940     sv=NULL;
2941     attribute=NULL;
2942     av=NULL;
2943     if (sv_isobject(ST(0)) == 0)
2944       {
2945         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2946           PackageName);
2947         goto PerlException;
2948       }
2949     reference=SvRV(ST(0));
2950     hv=SvSTASH(reference);
2951     av=newAV();
2952     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2953     SvREFCNT_dec(av);
2954     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2955     if (image == (Image *) NULL)
2956       {
2957         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2958           PackageName);
2959         goto PerlException;
2960       }
2961     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2962     /*
2963       Get options.
2964     */
2965     channel=DefaultChannels;
2966     (void) CopyMagickString(expression,"u",MagickPathExtent);
2967     if (items == 2)
2968       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2969     else
2970       for (i=2; i < items; i+=2)
2971       {
2972         attribute=(char *) SvPV(ST(i-1),na);
2973         switch (*attribute)
2974         {
2975           case 'C':
2976           case 'c':
2977           {
2978             if (LocaleCompare(attribute,"channel") == 0)
2979               {
2980                 ssize_t
2981                   option;
2982
2983                 option=ParseChannelOption(SvPV(ST(i),na));
2984                 if (option < 0)
2985                   {
2986                     ThrowPerlException(exception,OptionError,
2987                       "UnrecognizedType",SvPV(ST(i),na));
2988                     return;
2989                   }
2990                 channel=(ChannelType) option;
2991                 break;
2992               }
2993             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2994               attribute);
2995             break;
2996           }
2997           case 'E':
2998           case 'e':
2999           {
3000             if (LocaleCompare(attribute,"expression") == 0)
3001               {
3002                 (void) CopyMagickString(expression,SvPV(ST(i),na),
3003                   MagickPathExtent);
3004                 break;
3005               }
3006             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3007               attribute);
3008             break;
3009           }
3010           default:
3011           {
3012             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3013               attribute);
3014             break;
3015           }
3016         }
3017       }
3018     channel_mask=SetImageChannelMask(image,channel);
3019     image=ChannelFxImage(image,expression,exception);
3020     if (image != (Image *) NULL)
3021       (void) SetImageChannelMask(image,channel_mask);
3022     if (image == (Image *) NULL)
3023       goto PerlException;
3024     for ( ; image; image=image->next)
3025     {
3026       AddImageToRegistry(sv,image);
3027       rv=newRV(sv);
3028       av_push(av,sv_bless(rv,hv));
3029       SvREFCNT_dec(sv);
3030     }
3031     exception=DestroyExceptionInfo(exception);
3032     ST(0)=av_reference;
3033     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3034     XSRETURN(1);
3035
3036   PerlException:
3037     InheritPerlException(exception,perl_exception);
3038     exception=DestroyExceptionInfo(exception);
3039     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3040     SvPOK_on(perl_exception);
3041     ST(0)=sv_2mortal(perl_exception);
3042     XSRETURN(1);
3043   }
3044 \f
3045 #
3046 ###############################################################################
3047 #                                                                             #
3048 #                                                                             #
3049 #                                                                             #
3050 #   C l o n e                                                                 #
3051 #                                                                             #
3052 #                                                                             #
3053 #                                                                             #
3054 ###############################################################################
3055 #
3056 #
3057 void
3058 Clone(ref)
3059   Image::Magick ref=NO_INIT
3060   ALIAS:
3061     CopyImage   = 1
3062     copy        = 2
3063     copyimage   = 3
3064     CloneImage  = 4
3065     clone       = 5
3066     cloneimage  = 6
3067     Clone       = 7
3068   PPCODE:
3069   {
3070     AV
3071       *av;
3072
3073     ExceptionInfo
3074       *exception;
3075
3076     HV
3077       *hv;
3078
3079     Image
3080       *clone,
3081       *image;
3082
3083     struct PackageInfo
3084       *info;
3085
3086     SV
3087       *perl_exception,
3088       *reference,
3089       *rv,
3090       *sv;
3091
3092     PERL_UNUSED_VAR(ref);
3093     PERL_UNUSED_VAR(ix);
3094     exception=AcquireExceptionInfo();
3095     perl_exception=newSVpv("",0);
3096     sv=NULL;
3097     if (sv_isobject(ST(0)) == 0)
3098       {
3099         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3100           PackageName);
3101         goto PerlException;
3102       }
3103     reference=SvRV(ST(0));
3104     hv=SvSTASH(reference);
3105     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3106     if (image == (Image *) NULL)
3107       {
3108         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3109           PackageName);
3110         goto PerlException;
3111       }
3112     /*
3113       Create blessed Perl array for the returned image.
3114     */
3115     av=newAV();
3116     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3117     SvREFCNT_dec(av);
3118     for ( ; image; image=image->next)
3119     {
3120       clone=CloneImage(image,0,0,MagickTrue,exception);
3121       if (clone == (Image *) NULL)
3122         break;
3123       AddImageToRegistry(sv,clone);
3124       rv=newRV(sv);
3125       av_push(av,sv_bless(rv,hv));
3126       SvREFCNT_dec(sv);
3127     }
3128     exception=DestroyExceptionInfo(exception);
3129     SvREFCNT_dec(perl_exception);
3130     XSRETURN(1);
3131
3132   PerlException:
3133     InheritPerlException(exception,perl_exception);
3134     exception=DestroyExceptionInfo(exception);
3135     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3136     SvPOK_on(perl_exception);
3137     ST(0)=sv_2mortal(perl_exception);
3138     XSRETURN(1);
3139   }
3140 \f
3141 #
3142 ###############################################################################
3143 #                                                                             #
3144 #                                                                             #
3145 #                                                                             #
3146 #   C L O N E                                                                 #
3147 #                                                                             #
3148 #                                                                             #
3149 #                                                                             #
3150 ###############################################################################
3151 #
3152 #
3153 void
3154 CLONE(ref,...)
3155   SV *ref;
3156   CODE:
3157   {
3158     PERL_UNUSED_VAR(ref);
3159     if (magick_registry != (SplayTreeInfo *) NULL)
3160       {
3161         register Image
3162           *p;
3163
3164         ResetSplayTreeIterator(magick_registry);
3165         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3166         while (p != (Image *) NULL)
3167         {
3168           ReferenceImage(p);
3169           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3170         }
3171       }
3172   }
3173 \f
3174 #
3175 ###############################################################################
3176 #                                                                             #
3177 #                                                                             #
3178 #                                                                             #
3179 #   C o a l e s c e                                                           #
3180 #                                                                             #
3181 #                                                                             #
3182 #                                                                             #
3183 ###############################################################################
3184 #
3185 #
3186 void
3187 Coalesce(ref)
3188   Image::Magick ref=NO_INIT
3189   ALIAS:
3190     CoalesceImage   = 1
3191     coalesce        = 2
3192     coalesceimage   = 3
3193   PPCODE:
3194   {
3195     AV
3196       *av;
3197
3198     ExceptionInfo
3199       *exception;
3200
3201     HV
3202       *hv;
3203
3204     Image
3205       *image;
3206
3207     struct PackageInfo
3208       *info;
3209
3210     SV
3211       *av_reference,
3212       *perl_exception,
3213       *reference,
3214       *rv,
3215       *sv;
3216
3217     PERL_UNUSED_VAR(ref);
3218     PERL_UNUSED_VAR(ix);
3219     exception=AcquireExceptionInfo();
3220     perl_exception=newSVpv("",0);
3221     sv=NULL;
3222     if (sv_isobject(ST(0)) == 0)
3223       {
3224         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3225           PackageName);
3226         goto PerlException;
3227       }
3228     reference=SvRV(ST(0));
3229     hv=SvSTASH(reference);
3230     av=newAV();
3231     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3232     SvREFCNT_dec(av);
3233     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3234     if (image == (Image *) NULL)
3235       {
3236         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3237           PackageName);
3238         goto PerlException;
3239       }
3240     image=CoalesceImages(image,exception);
3241     if (image == (Image *) NULL)
3242       goto PerlException;
3243     for ( ; image; image=image->next)
3244     {
3245       AddImageToRegistry(sv,image);
3246       rv=newRV(sv);
3247       av_push(av,sv_bless(rv,hv));
3248       SvREFCNT_dec(sv);
3249     }
3250     exception=DestroyExceptionInfo(exception);
3251     ST(0)=av_reference;
3252     SvREFCNT_dec(perl_exception);
3253     XSRETURN(1);
3254
3255   PerlException:
3256     InheritPerlException(exception,perl_exception);
3257     exception=DestroyExceptionInfo(exception);
3258     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3259     SvPOK_on(perl_exception);
3260     ST(0)=sv_2mortal(perl_exception);
3261     XSRETURN(1);
3262   }
3263 \f
3264 #
3265 ###############################################################################
3266 #                                                                             #
3267 #                                                                             #
3268 #                                                                             #
3269 #   C o m p a r e                                                             #
3270 #                                                                             #
3271 #                                                                             #
3272 #                                                                             #
3273 ###############################################################################
3274 #
3275 #
3276 void
3277 Compare(ref,...)
3278   Image::Magick ref=NO_INIT
3279   ALIAS:
3280     CompareImages = 1
3281     compare      = 2
3282     compareimage = 3
3283   PPCODE:
3284   {
3285     AV
3286       *av;
3287
3288     char
3289       *attribute;
3290
3291     double
3292       distortion;
3293
3294     ExceptionInfo
3295       *exception;
3296
3297     HV
3298       *hv;
3299
3300     Image
3301       *difference_image,
3302       *image,
3303       *reconstruct_image;
3304
3305     MetricType
3306       metric;
3307
3308     register ssize_t
3309       i;
3310
3311     ssize_t
3312       option;
3313
3314     struct PackageInfo
3315       *info;
3316
3317     SV
3318       *av_reference,
3319       *perl_exception,
3320       *reference,
3321       *rv,
3322       *sv;
3323
3324     PERL_UNUSED_VAR(ref);
3325     PERL_UNUSED_VAR(ix);
3326     exception=AcquireExceptionInfo();
3327     perl_exception=newSVpv("",0);
3328     sv=NULL;
3329     av=NULL;
3330     attribute=NULL;
3331     if (sv_isobject(ST(0)) == 0)
3332       {
3333         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3334           PackageName);
3335         goto PerlException;
3336       }
3337     reference=SvRV(ST(0));
3338     hv=SvSTASH(reference);
3339     av=newAV();
3340     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3341     SvREFCNT_dec(av);
3342     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3343     if (image == (Image *) NULL)
3344       {
3345         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3346           PackageName);
3347         goto PerlException;
3348       }
3349     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3350     /*
3351       Get attribute.
3352     */
3353     reconstruct_image=image;
3354     metric=RootMeanSquaredErrorMetric;
3355     for (i=2; i < items; i+=2)
3356     {
3357       attribute=(char *) SvPV(ST(i-1),na);
3358       switch (*attribute)
3359       {
3360         case 'C':
3361         case 'c':
3362         {
3363           if (LocaleCompare(attribute,"channel") == 0)
3364             {
3365               ssize_t
3366                 option;
3367
3368               option=ParseChannelOption(SvPV(ST(i),na));
3369               if (option < 0)
3370                 {
3371                   ThrowPerlException(exception,OptionError,
3372                     "UnrecognizedType",SvPV(ST(i),na));
3373                   return;
3374                 }
3375               (void) SetPixelChannelMask(image,(ChannelType) option);
3376               break;
3377             }
3378           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3379             attribute);
3380           break;
3381         }
3382         case 'F':
3383         case 'f':
3384         {
3385           if (LocaleCompare(attribute,"fuzz") == 0)
3386             {
3387               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3388               break;
3389             }
3390           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3391             attribute);
3392           break;
3393         }
3394         case 'I':
3395         case 'i':
3396         {
3397           if (LocaleCompare(attribute,"image") == 0)
3398             {
3399               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3400                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3401               break;
3402             }
3403           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3404             attribute);
3405           break;
3406         }
3407         case 'M':
3408         case 'm':
3409         {
3410           if (LocaleCompare(attribute,"metric") == 0)
3411             {
3412               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3413                 SvPV(ST(i),na));
3414               if (option < 0)
3415                 {
3416                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3417                     SvPV(ST(i),na));
3418                   break;
3419                 }
3420               metric=(MetricType) option;
3421               break;
3422             }
3423           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3424             attribute);
3425           break;
3426         }
3427         default:
3428         {
3429           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3430             attribute);
3431           break;
3432         }
3433       }
3434     }
3435     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3436       exception);
3437     if (difference_image != (Image *) NULL)
3438       {
3439         difference_image->error.mean_error_per_pixel=distortion;
3440         AddImageToRegistry(sv,difference_image);
3441         rv=newRV(sv);
3442         av_push(av,sv_bless(rv,hv));
3443         SvREFCNT_dec(sv);
3444       }
3445     exception=DestroyExceptionInfo(exception);
3446     ST(0)=av_reference;
3447     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3448     XSRETURN(1);
3449
3450   PerlException:
3451     InheritPerlException(exception,perl_exception);
3452     exception=DestroyExceptionInfo(exception);
3453     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3454     SvPOK_on(perl_exception);
3455     ST(0)=sv_2mortal(perl_exception);
3456     XSRETURN(1);
3457   }
3458 \f
3459 #
3460 ###############################################################################
3461 #                                                                             #
3462 #                                                                             #
3463 #                                                                             #
3464 #   C o m p l e x I m a g e s                                                 #
3465 #                                                                             #
3466 #                                                                             #
3467 #                                                                             #
3468 ###############################################################################
3469 #
3470 #
3471 void
3472 ComplexImages(ref)
3473   Image::Magick ref=NO_INIT
3474   ALIAS:
3475     ComplexImages   = 1
3476     compleximages   = 2
3477   PPCODE:
3478   {
3479     AV
3480       *av;
3481
3482     char
3483       *attribute,
3484       *p;
3485
3486     ComplexOperator
3487       op;
3488
3489     ExceptionInfo
3490       *exception;
3491
3492     HV
3493       *hv;
3494
3495     Image
3496       *image;
3497
3498     register ssize_t
3499       i;
3500
3501     struct PackageInfo
3502       *info;
3503
3504     SV
3505       *perl_exception,
3506       *reference,
3507       *rv,
3508       *sv;
3509
3510     PERL_UNUSED_VAR(ref);
3511     PERL_UNUSED_VAR(ix);
3512     exception=AcquireExceptionInfo();
3513     perl_exception=newSVpv("",0);
3514     sv=NULL;
3515     if (sv_isobject(ST(0)) == 0)
3516       {
3517         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3518           PackageName);
3519         goto PerlException;
3520       }
3521     reference=SvRV(ST(0));
3522     hv=SvSTASH(reference);
3523     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3524     if (image == (Image *) NULL)
3525       {
3526         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3527           PackageName);
3528         goto PerlException;
3529       }
3530     op=UndefinedComplexOperator;
3531     if (items == 2)
3532       {
3533         ssize_t
3534           in;
3535
3536         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3537           SvPV(ST(1),na));
3538         if (in < 0)
3539           {
3540             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3541               SvPV(ST(1),na));
3542             return;
3543           }
3544         op=(ComplexOperator) in;
3545       }
3546     else
3547       for (i=2; i < items; i+=2)
3548       {
3549         attribute=(char *) SvPV(ST(i-1),na);
3550         switch (*attribute)
3551         {
3552           case 'O':
3553           case 'o':
3554           {
3555             if (LocaleCompare(attribute,"operator") == 0)
3556               {
3557                 ssize_t
3558                   in;
3559
3560                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3561                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3562                 if (in < 0)
3563                   {
3564                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3565                       SvPV(ST(i),na));
3566                     return;
3567                   }
3568                 op=(ComplexOperator) in;
3569                 break;
3570               }
3571             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3572               attribute);
3573             break;
3574           }
3575           default:
3576           {
3577             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3578               attribute);
3579             break;
3580           }
3581         }
3582       }
3583     image=ComplexImages(image,op,exception);
3584     if (image == (Image *) NULL)
3585       goto PerlException;
3586     /*
3587       Create blessed Perl array for the returned image.
3588     */
3589     av=newAV();
3590     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3591     SvREFCNT_dec(av);
3592     AddImageToRegistry(sv,image);
3593     rv=newRV(sv);
3594     av_push(av,sv_bless(rv,hv));
3595     SvREFCNT_dec(sv);
3596     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3597     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3598       "complex-%.*s",(int) (MagickPathExtent-9),
3599       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3600     (void) CopyMagickString(image->filename,info->image_info->filename,
3601       MagickPathExtent);
3602     SetImageInfo(info->image_info,0,exception);
3603     exception=DestroyExceptionInfo(exception);
3604     SvREFCNT_dec(perl_exception);
3605     XSRETURN(1);
3606
3607   PerlException:
3608     InheritPerlException(exception,perl_exception);
3609     exception=DestroyExceptionInfo(exception);
3610     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3611     SvPOK_on(perl_exception);
3612     ST(0)=sv_2mortal(perl_exception);
3613     XSRETURN(1);
3614   }
3615 \f
3616 #
3617 ###############################################################################
3618 #                                                                             #
3619 #                                                                             #
3620 #                                                                             #
3621 #   C o m p a r e L a y e r s                                                 #
3622 #                                                                             #
3623 #                                                                             #
3624 #                                                                             #
3625 ###############################################################################
3626 #
3627 #
3628 void
3629 CompareLayers(ref)
3630   Image::Magick ref=NO_INIT
3631   ALIAS:
3632     CompareImagesLayers   = 1
3633     comparelayers        = 2
3634     compareimagelayers   = 3
3635   PPCODE:
3636   {
3637     AV
3638       *av;
3639
3640     char
3641       *attribute;
3642
3643     ExceptionInfo
3644       *exception;
3645
3646     HV
3647       *hv;
3648
3649     Image
3650       *image;
3651
3652     LayerMethod
3653       method;
3654
3655     register ssize_t
3656       i;
3657
3658     ssize_t
3659       option;
3660
3661     struct PackageInfo
3662       *info;
3663
3664     SV
3665       *av_reference,
3666       *perl_exception,
3667       *reference,
3668       *rv,
3669       *sv;
3670
3671     PERL_UNUSED_VAR(ref);
3672     PERL_UNUSED_VAR(ix);
3673     exception=AcquireExceptionInfo();
3674     perl_exception=newSVpv("",0);
3675     sv=NULL;
3676     if (sv_isobject(ST(0)) == 0)
3677       {
3678         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3679           PackageName);
3680         goto PerlException;
3681       }
3682     reference=SvRV(ST(0));
3683     hv=SvSTASH(reference);
3684     av=newAV();
3685     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3686     SvREFCNT_dec(av);
3687     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3688     if (image == (Image *) NULL)
3689       {
3690         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3691           PackageName);
3692         goto PerlException;
3693       }
3694     method=CompareAnyLayer;
3695     for (i=2; i < items; i+=2)
3696     {
3697       attribute=(char *) SvPV(ST(i-1),na);
3698       switch (*attribute)
3699       {
3700         case 'M':
3701         case 'm':
3702         {
3703           if (LocaleCompare(attribute,"method") == 0)
3704             {
3705               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3706                 SvPV(ST(i),na));
3707               if (option < 0)
3708                 {
3709                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3710                     SvPV(ST(i),na));
3711                   break;
3712                 }
3713                method=(LayerMethod) option;
3714               break;
3715             }
3716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3717             attribute);
3718           break;
3719         }
3720         default:
3721         {
3722           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3723             attribute);
3724           break;
3725         }
3726       }
3727     }
3728     image=CompareImagesLayers(image,method,exception);
3729     if (image == (Image *) NULL)
3730       goto PerlException;
3731     for ( ; image; image=image->next)
3732     {
3733       AddImageToRegistry(sv,image);
3734       rv=newRV(sv);
3735       av_push(av,sv_bless(rv,hv));
3736       SvREFCNT_dec(sv);
3737     }
3738     exception=DestroyExceptionInfo(exception);
3739     ST(0)=av_reference;
3740     SvREFCNT_dec(perl_exception);
3741     XSRETURN(1);
3742
3743   PerlException:
3744     InheritPerlException(exception,perl_exception);
3745     exception=DestroyExceptionInfo(exception);
3746     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3747     SvPOK_on(perl_exception);
3748     ST(0)=sv_2mortal(perl_exception);
3749     XSRETURN(1);
3750   }
3751 \f
3752 #
3753 ###############################################################################
3754 #                                                                             #
3755 #                                                                             #
3756 #                                                                             #
3757 #   D e s t r o y                                                             #
3758 #                                                                             #
3759 #                                                                             #
3760 #                                                                             #
3761 ###############################################################################
3762 #
3763 #
3764 void
3765 DESTROY(ref)
3766   Image::Magick ref=NO_INIT
3767   PPCODE:
3768   {
3769     SV
3770       *reference;
3771
3772     PERL_UNUSED_VAR(ref);
3773     if (sv_isobject(ST(0)) == 0)
3774       croak("ReferenceIsNotMyType");
3775     reference=SvRV(ST(0));
3776     switch (SvTYPE(reference))
3777     {
3778       case SVt_PVAV:
3779       {
3780         char
3781           message[MagickPathExtent];
3782
3783         const SV
3784           *key;
3785
3786         HV
3787           *hv;
3788
3789         GV
3790           **gvp;
3791
3792         struct PackageInfo
3793           *info;
3794
3795         SV
3796           *sv;
3797
3798         /*
3799           Array (AV *) reference
3800         */
3801         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3802           XS_VERSION,reference);
3803         hv=gv_stashpv(PackageName, FALSE);
3804         if (!hv)
3805           break;
3806         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3807         if (!gvp)
3808           break;
3809         sv=GvSV(*gvp);
3810         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3811           {
3812             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3813             DestroyPackageInfo(info);
3814           }
3815         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3816         (void) key;
3817         break;
3818       }
3819       case SVt_PVMG:
3820       {
3821         Image
3822           *image;
3823
3824         /*
3825           Blessed scalar = (Image *) SvIV(reference)
3826         */
3827         image=INT2PTR(Image *,SvIV(reference));
3828         if (image != (Image *) NULL)
3829           DeleteImageFromRegistry(reference,image);
3830         break;
3831       }
3832       default:
3833         break;
3834     }
3835   }
3836 \f
3837 #
3838 ###############################################################################
3839 #                                                                             #
3840 #                                                                             #
3841 #                                                                             #
3842 #   D i s p l a y                                                             #
3843 #                                                                             #
3844 #                                                                             #
3845 #                                                                             #
3846 ###############################################################################
3847 #
3848 #
3849 void
3850 Display(ref,...)
3851   Image::Magick ref=NO_INIT
3852   ALIAS:
3853     DisplayImage  = 1
3854     display       = 2
3855     displayimage  = 3
3856   PPCODE:
3857   {
3858     ExceptionInfo
3859       *exception;
3860
3861     Image
3862       *image;
3863
3864     register ssize_t
3865       i;
3866
3867     struct PackageInfo
3868       *info,
3869       *package_info;
3870
3871     SV
3872       *perl_exception,
3873       *reference;
3874
3875     PERL_UNUSED_VAR(ref);
3876     PERL_UNUSED_VAR(ix);
3877     exception=AcquireExceptionInfo();
3878     perl_exception=newSVpv("",0);
3879     package_info=(struct PackageInfo *) NULL;
3880     if (sv_isobject(ST(0)) == 0)
3881       {
3882         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3883           PackageName);
3884         goto PerlException;
3885       }
3886     reference=SvRV(ST(0));
3887     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3888     if (image == (Image *) NULL)
3889       {
3890         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3891           PackageName);
3892         goto PerlException;
3893       }
3894     package_info=ClonePackageInfo(info,exception);
3895     if (items == 2)
3896       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3897     else
3898       if (items > 2)
3899         for (i=2; i < items; i+=2)
3900           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3901             exception);
3902     (void) DisplayImages(package_info->image_info,image,exception);
3903     (void) CatchImageException(image);
3904
3905   PerlException:
3906     if (package_info != (struct PackageInfo *) NULL)
3907       DestroyPackageInfo(package_info);
3908     InheritPerlException(exception,perl_exception);
3909     exception=DestroyExceptionInfo(exception);
3910     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3911     SvPOK_on(perl_exception);
3912     ST(0)=sv_2mortal(perl_exception);
3913     XSRETURN(1);
3914   }
3915 \f
3916 #
3917 ###############################################################################
3918 #                                                                             #
3919 #                                                                             #
3920 #                                                                             #
3921 #   E v a l u a t e I m a g e s                                               #
3922 #                                                                             #
3923 #                                                                             #
3924 #                                                                             #
3925 ###############################################################################
3926 #
3927 #
3928 void
3929 EvaluateImages(ref)
3930   Image::Magick ref=NO_INIT
3931   ALIAS:
3932     EvaluateImages   = 1
3933     evaluateimages   = 2
3934   PPCODE:
3935   {
3936     AV
3937       *av;
3938
3939     char
3940       *attribute,
3941       *p;
3942
3943     ExceptionInfo
3944       *exception;
3945
3946     HV
3947       *hv;
3948
3949     Image
3950       *image;
3951
3952     MagickEvaluateOperator
3953       op;
3954
3955     register ssize_t
3956       i;
3957
3958     struct PackageInfo
3959       *info;
3960
3961     SV
3962       *perl_exception,
3963       *reference,
3964       *rv,
3965       *sv;
3966
3967     PERL_UNUSED_VAR(ref);
3968     PERL_UNUSED_VAR(ix);
3969     exception=AcquireExceptionInfo();
3970     perl_exception=newSVpv("",0);
3971     sv=NULL;
3972     if (sv_isobject(ST(0)) == 0)
3973       {
3974         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3975           PackageName);
3976         goto PerlException;
3977       }
3978     reference=SvRV(ST(0));
3979     hv=SvSTASH(reference);
3980     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3981     if (image == (Image *) NULL)
3982       {
3983         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3984           PackageName);
3985         goto PerlException;
3986       }
3987     op=MeanEvaluateOperator;
3988     if (items == 2)
3989       {
3990         ssize_t
3991           in;
3992
3993         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3994           SvPV(ST(1),na));
3995         if (in < 0)
3996           {
3997             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3998               SvPV(ST(1),na));
3999             return;
4000           }
4001         op=(MagickEvaluateOperator) in;
4002       }
4003     else
4004       for (i=2; i < items; i+=2)
4005       {
4006         attribute=(char *) SvPV(ST(i-1),na);
4007         switch (*attribute)
4008         {
4009           case 'O':
4010           case 'o':
4011           {
4012             if (LocaleCompare(attribute,"operator") == 0)
4013               {
4014                 ssize_t
4015                   in;
4016
4017                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4018                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4019                 if (in < 0)
4020                   {
4021                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4022                       SvPV(ST(i),na));
4023                     return;
4024                   }
4025                 op=(MagickEvaluateOperator) in;
4026                 break;
4027               }
4028             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4029               attribute);
4030             break;
4031           }
4032           default:
4033           {
4034             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4035               attribute);
4036             break;
4037           }
4038         }
4039       }
4040     image=EvaluateImages(image,op,exception);
4041     if (image == (Image *) NULL)
4042       goto PerlException;
4043     /*
4044       Create blessed Perl array for the returned image.
4045     */
4046     av=newAV();
4047     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4048     SvREFCNT_dec(av);
4049     AddImageToRegistry(sv,image);
4050     rv=newRV(sv);
4051     av_push(av,sv_bless(rv,hv));
4052     SvREFCNT_dec(sv);
4053     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4054     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4055       "evaluate-%.*s",(int) (MagickPathExtent-9),
4056       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4057     (void) CopyMagickString(image->filename,info->image_info->filename,
4058       MagickPathExtent);
4059     SetImageInfo(info->image_info,0,exception);
4060     exception=DestroyExceptionInfo(exception);
4061     SvREFCNT_dec(perl_exception);
4062     XSRETURN(1);
4063
4064   PerlException:
4065     InheritPerlException(exception,perl_exception);
4066     exception=DestroyExceptionInfo(exception);
4067     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4068     SvPOK_on(perl_exception);
4069     ST(0)=sv_2mortal(perl_exception);
4070     XSRETURN(1);
4071   }
4072 \f
4073 #
4074 ###############################################################################
4075 #                                                                             #
4076 #                                                                             #
4077 #                                                                             #
4078 #   F e a t u r e s                                                           #
4079 #                                                                             #
4080 #                                                                             #
4081 #                                                                             #
4082 ###############################################################################
4083 #
4084 #
4085 void
4086 Features(ref,...)
4087   Image::Magick ref=NO_INIT
4088   ALIAS:
4089     FeaturesImage = 1
4090     features      = 2
4091     featuresimage = 3
4092   PPCODE:
4093   {
4094 #define ChannelFeatures(channel,direction) \
4095 { \
4096   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4097     channel_features[channel].angular_second_moment[direction]); \
4098   PUSHs(sv_2mortal(newSVpv(message,0))); \
4099   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4100     channel_features[channel].contrast[direction]); \
4101   PUSHs(sv_2mortal(newSVpv(message,0))); \
4102   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4103     channel_features[channel].contrast[direction]); \
4104   PUSHs(sv_2mortal(newSVpv(message,0))); \
4105   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4106     channel_features[channel].variance_sum_of_squares[direction]); \
4107   PUSHs(sv_2mortal(newSVpv(message,0))); \
4108   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4109     channel_features[channel].inverse_difference_moment[direction]); \
4110   PUSHs(sv_2mortal(newSVpv(message,0))); \
4111   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4112     channel_features[channel].sum_average[direction]); \
4113   PUSHs(sv_2mortal(newSVpv(message,0))); \
4114   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4115     channel_features[channel].sum_variance[direction]); \
4116   PUSHs(sv_2mortal(newSVpv(message,0))); \
4117   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4118     channel_features[channel].sum_entropy[direction]); \
4119   PUSHs(sv_2mortal(newSVpv(message,0))); \
4120   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4121     channel_features[channel].entropy[direction]); \
4122   PUSHs(sv_2mortal(newSVpv(message,0))); \
4123   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4124     channel_features[channel].difference_variance[direction]); \
4125   PUSHs(sv_2mortal(newSVpv(message,0))); \
4126   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4127     channel_features[channel].difference_entropy[direction]); \
4128   PUSHs(sv_2mortal(newSVpv(message,0))); \
4129   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4130     channel_features[channel].measure_of_correlation_1[direction]); \
4131   PUSHs(sv_2mortal(newSVpv(message,0))); \
4132   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4133     channel_features[channel].measure_of_correlation_2[direction]); \
4134   PUSHs(sv_2mortal(newSVpv(message,0))); \
4135   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4136     channel_features[channel].maximum_correlation_coefficient[direction]); \
4137   PUSHs(sv_2mortal(newSVpv(message,0))); \
4138 }
4139
4140     AV
4141       *av;
4142
4143     char
4144       *attribute,
4145       message[MagickPathExtent];
4146
4147     ChannelFeatures
4148       *channel_features;
4149
4150     double
4151       distance;
4152
4153     ExceptionInfo
4154       *exception;
4155
4156     Image
4157       *image;
4158
4159     register ssize_t
4160       i;
4161
4162     ssize_t
4163       count;
4164
4165     struct PackageInfo
4166       *info;
4167
4168     SV
4169       *perl_exception,
4170       *reference;
4171
4172     PERL_UNUSED_VAR(ref);
4173     PERL_UNUSED_VAR(ix);
4174     exception=AcquireExceptionInfo();
4175     perl_exception=newSVpv("",0);
4176     av=NULL;
4177     if (sv_isobject(ST(0)) == 0)
4178       {
4179         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4180           PackageName);
4181         goto PerlException;
4182       }
4183     reference=SvRV(ST(0));
4184     av=newAV();
4185     SvREFCNT_dec(av);
4186     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4187     if (image == (Image *) NULL)
4188       {
4189         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4190           PackageName);
4191         goto PerlException;
4192       }
4193     distance=1.0;
4194     for (i=2; i < items; i+=2)
4195     {
4196       attribute=(char *) SvPV(ST(i-1),na);
4197       switch (*attribute)
4198       {
4199         case 'D':
4200         case 'd':
4201         {
4202           if (LocaleCompare(attribute,"distance") == 0)
4203             {
4204               distance=StringToLong((char *) SvPV(ST(1),na));
4205               break;
4206             }
4207           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4208             attribute);
4209           break;
4210         }
4211         default:
4212         {
4213           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4214             attribute);
4215           break;
4216         }
4217       }
4218     }
4219     count=0;
4220     for ( ; image; image=image->next)
4221     {
4222       channel_features=GetImageFeatures(image,distance,exception);
4223       if (channel_features == (ChannelFeatures *) NULL)
4224         continue;
4225       count++;
4226       EXTEND(sp,280*count);
4227       for (i=0; i < 4; i++)
4228       {
4229         ChannelFeatures(RedChannel,i);
4230         ChannelFeatures(GreenChannel,i);
4231         ChannelFeatures(BlueChannel,i);
4232         if (image->colorspace == CMYKColorspace)
4233           ChannelFeatures(BlackChannel,i);
4234         if (image->alpha_trait != UndefinedPixelTrait)
4235           ChannelFeatures(AlphaChannel,i);
4236       }
4237       channel_features=(ChannelFeatures *)
4238         RelinquishMagickMemory(channel_features);
4239     }
4240
4241   PerlException:
4242     InheritPerlException(exception,perl_exception);
4243     exception=DestroyExceptionInfo(exception);
4244     SvREFCNT_dec(perl_exception);
4245   }
4246 \f
4247 #
4248 ###############################################################################
4249 #                                                                             #
4250 #                                                                             #
4251 #                                                                             #
4252 #   F l a t t e n                                                             #
4253 #                                                                             #
4254 #                                                                             #
4255 #                                                                             #
4256 ###############################################################################
4257 #
4258 #
4259 void
4260 Flatten(ref)
4261   Image::Magick ref=NO_INIT
4262   ALIAS:
4263     FlattenImage   = 1
4264     flatten        = 2
4265     flattenimage   = 3
4266   PPCODE:
4267   {
4268     AV
4269       *av;
4270
4271     char
4272       *attribute,
4273       *p;
4274
4275     ExceptionInfo
4276       *exception;
4277
4278     HV
4279       *hv;
4280
4281     Image
4282       *image;
4283
4284     PixelInfo
4285       background_color;
4286
4287     register ssize_t
4288       i;
4289
4290     struct PackageInfo
4291       *info;
4292
4293     SV
4294       *perl_exception,
4295       *reference,
4296       *rv,
4297       *sv;
4298
4299     PERL_UNUSED_VAR(ref);
4300     PERL_UNUSED_VAR(ix);
4301     exception=AcquireExceptionInfo();
4302     perl_exception=newSVpv("",0);
4303     sv=NULL;
4304     if (sv_isobject(ST(0)) == 0)
4305       {
4306         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4307           PackageName);
4308         goto PerlException;
4309       }
4310     reference=SvRV(ST(0));
4311     hv=SvSTASH(reference);
4312     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4313     if (image == (Image *) NULL)
4314       {
4315         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4316           PackageName);
4317         goto PerlException;
4318       }
4319     background_color=image->background_color;
4320     if (items == 2)
4321       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4322         &background_color,exception);
4323     else
4324       for (i=2; i < items; i+=2)
4325       {
4326         attribute=(char *) SvPV(ST(i-1),na);
4327         switch (*attribute)
4328         {
4329           case 'B':
4330           case 'b':
4331           {
4332             if (LocaleCompare(attribute,"background") == 0)
4333               {
4334                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4335                   AllCompliance,&background_color,exception);
4336                 break;
4337               }
4338             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4339               attribute);
4340             break;
4341           }
4342           default:
4343           {
4344             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4345               attribute);
4346             break;
4347           }
4348         }
4349       }
4350     image->background_color=background_color;
4351     image=MergeImageLayers(image,FlattenLayer,exception);
4352     if (image == (Image *) NULL)
4353       goto PerlException;
4354     /*
4355       Create blessed Perl array for the returned image.
4356     */
4357     av=newAV();
4358     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4359     SvREFCNT_dec(av);
4360     AddImageToRegistry(sv,image);
4361     rv=newRV(sv);
4362     av_push(av,sv_bless(rv,hv));
4363     SvREFCNT_dec(sv);
4364     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4365     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4366       "flatten-%.*s",(int) (MagickPathExtent-9),
4367       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4368     (void) CopyMagickString(image->filename,info->image_info->filename,
4369       MagickPathExtent);
4370     SetImageInfo(info->image_info,0,exception);
4371     exception=DestroyExceptionInfo(exception);
4372     SvREFCNT_dec(perl_exception);
4373     XSRETURN(1);
4374
4375   PerlException:
4376     InheritPerlException(exception,perl_exception);
4377     exception=DestroyExceptionInfo(exception);
4378     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4379     SvPOK_on(perl_exception);  /* return messages in string context */
4380     ST(0)=sv_2mortal(perl_exception);
4381     XSRETURN(1);
4382   }
4383 \f
4384 #
4385 ###############################################################################
4386 #                                                                             #
4387 #                                                                             #
4388 #                                                                             #
4389 #   F x                                                                       #
4390 #                                                                             #
4391 #                                                                             #
4392 #                                                                             #
4393 ###############################################################################
4394 #
4395 #
4396 void
4397 Fx(ref,...)
4398   Image::Magick ref=NO_INIT
4399   ALIAS:
4400     FxImage  = 1
4401     fx       = 2
4402     fximage  = 3
4403   PPCODE:
4404   {
4405     AV
4406       *av;
4407
4408     char
4409       *attribute,
4410       expression[MagickPathExtent];
4411
4412     ChannelType
4413       channel,
4414       channel_mask;
4415
4416     ExceptionInfo
4417       *exception;
4418
4419     HV
4420       *hv;
4421
4422     Image
4423       *image;
4424
4425     register ssize_t
4426       i;
4427
4428     struct PackageInfo
4429       *info;
4430
4431     SV
4432       *av_reference,
4433       *perl_exception,
4434       *reference,
4435       *rv,
4436       *sv;
4437
4438     PERL_UNUSED_VAR(ref);
4439     PERL_UNUSED_VAR(ix);
4440     exception=AcquireExceptionInfo();
4441     perl_exception=newSVpv("",0);
4442     sv=NULL;
4443     attribute=NULL;
4444     av=NULL;
4445     if (sv_isobject(ST(0)) == 0)
4446       {
4447         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4448           PackageName);
4449         goto PerlException;
4450       }
4451     reference=SvRV(ST(0));
4452     hv=SvSTASH(reference);
4453     av=newAV();
4454     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4455     SvREFCNT_dec(av);
4456     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4457     if (image == (Image *) NULL)
4458       {
4459         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4460           PackageName);
4461         goto PerlException;
4462       }
4463     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4464     /*
4465       Get options.
4466     */
4467     channel=DefaultChannels;
4468     (void) CopyMagickString(expression,"u",MagickPathExtent);
4469     if (items == 2)
4470       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4471     else
4472       for (i=2; i < items; i+=2)
4473       {
4474         attribute=(char *) SvPV(ST(i-1),na);
4475         switch (*attribute)
4476         {
4477           case 'C':
4478           case 'c':
4479           {
4480             if (LocaleCompare(attribute,"channel") == 0)
4481               {
4482                 ssize_t
4483                   option;
4484
4485                 option=ParseChannelOption(SvPV(ST(i),na));
4486                 if (option < 0)
4487                   {
4488                     ThrowPerlException(exception,OptionError,
4489                       "UnrecognizedType",SvPV(ST(i),na));
4490                     return;
4491                   }
4492                 channel=(ChannelType) option;
4493                 break;
4494               }
4495             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4496               attribute);
4497             break;
4498           }
4499           case 'E':
4500           case 'e':
4501           {
4502             if (LocaleCompare(attribute,"expression") == 0)
4503               {
4504                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4505                   MagickPathExtent);
4506                 break;
4507               }
4508             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4509               attribute);
4510             break;
4511           }
4512           default:
4513           {
4514             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4515               attribute);
4516             break;
4517           }
4518         }
4519       }
4520     channel_mask=SetImageChannelMask(image,channel);
4521     image=FxImage(image,expression,exception);
4522     if (image != (Image *) NULL)
4523       (void) SetImageChannelMask(image,channel_mask);
4524     if (image == (Image *) NULL)
4525       goto PerlException;
4526     for ( ; image; image=image->next)
4527     {
4528       AddImageToRegistry(sv,image);
4529       rv=newRV(sv);
4530       av_push(av,sv_bless(rv,hv));
4531       SvREFCNT_dec(sv);
4532     }
4533     exception=DestroyExceptionInfo(exception);
4534     ST(0)=av_reference;
4535     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4536     XSRETURN(1);
4537
4538   PerlException:
4539     InheritPerlException(exception,perl_exception);
4540     exception=DestroyExceptionInfo(exception);
4541     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4542     SvPOK_on(perl_exception);
4543     ST(0)=sv_2mortal(perl_exception);
4544     XSRETURN(1);
4545   }
4546 \f
4547 #
4548 ###############################################################################
4549 #                                                                             #
4550 #                                                                             #
4551 #                                                                             #
4552 #   G e t                                                                     #
4553 #                                                                             #
4554 #                                                                             #
4555 #                                                                             #
4556 ###############################################################################
4557 #
4558 #
4559 void
4560 Get(ref,...)
4561   Image::Magick ref=NO_INIT
4562   ALIAS:
4563     GetAttributes = 1
4564     GetAttribute  = 2
4565     get           = 3
4566     getattributes = 4
4567     getattribute  = 5
4568   PPCODE:
4569   {
4570     char
4571       *attribute,
4572       color[MagickPathExtent];
4573
4574     const char
4575       *value;
4576
4577     ExceptionInfo
4578       *exception;
4579
4580     Image
4581       *image;
4582
4583     long
4584       j;
4585
4586     register ssize_t
4587       i;
4588
4589     struct PackageInfo
4590       *info;
4591
4592     SV
4593       *perl_exception,
4594       *reference,
4595       *s;
4596
4597     PERL_UNUSED_VAR(ref);
4598     PERL_UNUSED_VAR(ix);
4599     exception=AcquireExceptionInfo();
4600     perl_exception=newSVpv("",0);
4601     if (sv_isobject(ST(0)) == 0)
4602       {
4603         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4604           PackageName);
4605         XSRETURN_EMPTY;
4606       }
4607     reference=SvRV(ST(0));
4608     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4609     if (image == (Image *) NULL && !info)
4610       XSRETURN_EMPTY;
4611     EXTEND(sp,items);
4612     for (i=1; i < items; i++)
4613     {
4614       attribute=(char *) SvPV(ST(i),na);
4615       s=NULL;
4616       switch (*attribute)
4617       {
4618         case 'A':
4619         case 'a':
4620         {
4621           if (LocaleCompare(attribute,"adjoin") == 0)
4622             {
4623               if (info)
4624                 s=newSViv((ssize_t) info->image_info->adjoin);
4625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626               continue;
4627             }
4628           if (LocaleCompare(attribute,"antialias") == 0)
4629             {
4630               if (info)
4631                 s=newSViv((ssize_t) info->image_info->antialias);
4632               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4633               continue;
4634             }
4635           if (LocaleCompare(attribute,"area") == 0)
4636             {
4637               s=newSViv(GetMagickResource(AreaResource));
4638               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4639               continue;
4640             }
4641           if (LocaleCompare(attribute,"attenuate") == 0)
4642             {
4643               const char
4644                 *value;
4645
4646               value=GetImageProperty(image,attribute,exception);
4647               if (value != (const char *) NULL)
4648                 s=newSVpv(value,0);
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           if (LocaleCompare(attribute,"authenticate") == 0)
4653             {
4654               if (info)
4655                 {
4656                   const char
4657                     *option;
4658
4659                   option=GetImageOption(info->image_info,attribute);
4660                   if (option != (const char *) NULL)
4661                     s=newSVpv(option,0);
4662                 }
4663               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4664               continue;
4665             }
4666           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4667             attribute);
4668           break;
4669         }
4670         case 'B':
4671         case 'b':
4672         {
4673           if (LocaleCompare(attribute,"background") == 0)
4674             {
4675               if (image == (Image *) NULL)
4676                 break;
4677               (void) FormatLocaleString(color,MagickPathExtent,
4678                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4679                 (double) image->background_color.green,
4680                 (double) image->background_color.blue,
4681                 (double) image->background_color.alpha);
4682               s=newSVpv(color,0);
4683               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4684               continue;
4685             }
4686           if (LocaleCompare(attribute,"base-columns") == 0)
4687             {
4688               if (image != (Image *) NULL)
4689                 s=newSViv((ssize_t) image->magick_columns);
4690               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4691               continue;
4692             }
4693           if (LocaleCompare(attribute,"base-filename") == 0)
4694             {
4695               if (image != (Image *) NULL)
4696                 s=newSVpv(image->magick_filename,0);
4697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4698               continue;
4699             }
4700           if (LocaleCompare(attribute,"base-height") == 0)
4701             {
4702               if (image != (Image *) NULL)
4703                 s=newSViv((ssize_t) image->magick_rows);
4704               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4705               continue;
4706             }
4707           if (LocaleCompare(attribute,"base-rows") == 0)
4708             {
4709               if (image != (Image *) NULL)
4710                 s=newSViv((ssize_t) image->magick_rows);
4711               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4712               continue;
4713             }
4714           if (LocaleCompare(attribute,"base-width") == 0)
4715             {
4716               if (image != (Image *) NULL)
4717                 s=newSViv((ssize_t) image->magick_columns);
4718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4719               continue;
4720             }
4721           if (LocaleCompare(attribute,"blue-primary") == 0)
4722             {
4723               if (image == (Image *) NULL)
4724                 break;
4725               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4726                 image->chromaticity.blue_primary.x,
4727                 image->chromaticity.blue_primary.y);
4728               s=newSVpv(color,0);
4729               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4730               continue;
4731             }
4732           if (LocaleCompare(attribute,"bordercolor") == 0)
4733             {
4734               if (image == (Image *) NULL)
4735                 break;
4736               (void) FormatLocaleString(color,MagickPathExtent,
4737                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4738                 (double) image->border_color.green,
4739                 (double) image->border_color.blue,
4740                 (double) image->border_color.alpha);
4741               s=newSVpv(color,0);
4742               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4743               continue;
4744             }
4745           if (LocaleCompare(attribute,"bounding-box") == 0)
4746             {
4747               char
4748                 geometry[MagickPathExtent];
4749
4750               RectangleInfo
4751                 page;
4752
4753               if (image == (Image *) NULL)
4754                 break;
4755               page=GetImageBoundingBox(image,exception);
4756               (void) FormatLocaleString(geometry,MagickPathExtent,
4757                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4758                 page.height,(double) page.x,(double) page.y);
4759               s=newSVpv(geometry,0);
4760               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4761               continue;
4762             }
4763           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4764             attribute);
4765           break;
4766         }
4767         case 'C':
4768         case 'c':
4769         {
4770           if (LocaleCompare(attribute,"class") == 0)
4771             {
4772               if (image == (Image *) NULL)
4773                 break;
4774               s=newSViv(image->storage_class);
4775               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4776                 image->storage_class));
4777               SvIOK_on(s);
4778               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4779               continue;
4780             }
4781           if (LocaleCompare(attribute,"clip-mask") == 0)
4782             {
4783               if (image != (Image *) NULL)
4784                 {
4785                   Image
4786                     *mask_image;
4787
4788                   SV
4789                     *sv;
4790
4791                   sv=NULL;
4792                   if (image->read_mask == MagickFalse)
4793                     ClipImage(image,exception);
4794                   mask_image=GetImageMask(image,exception);
4795                   if (mask_image != (Image *) NULL)
4796                     {
4797                       AddImageToRegistry(sv,mask_image);
4798                       s=sv_bless(newRV(sv),SvSTASH(reference));
4799                     }
4800                 }
4801               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4802               continue;
4803             }
4804           if (LocaleCompare(attribute,"clip-path") == 0)
4805             {
4806               if (image != (Image *) NULL)
4807                 {
4808                   Image
4809                     *mask_image;
4810
4811                   SV
4812                     *sv;
4813
4814                   sv=NULL;
4815                   if (image->read_mask != MagickFalse)
4816                     ClipImage(image,exception);
4817                   mask_image=GetImageMask(image,exception);
4818                   if (mask_image != (Image *) NULL)
4819                     {
4820                       AddImageToRegistry(sv,mask_image);
4821                       s=sv_bless(newRV(sv),SvSTASH(reference));
4822                     }
4823                 }
4824               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4825               continue;
4826             }
4827           if (LocaleCompare(attribute,"compression") == 0)
4828             {
4829               j=info ? info->image_info->compression : image ?
4830                 image->compression : UndefinedCompression;
4831               if (info)
4832                 if (info->image_info->compression == UndefinedCompression)
4833                   j=image->compression;
4834               s=newSViv(j);
4835               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4836                 j));
4837               SvIOK_on(s);
4838               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4839               continue;
4840             }
4841           if (LocaleCompare(attribute,"colorspace") == 0)
4842             {
4843               j=image ? image->colorspace : RGBColorspace;
4844               s=newSViv(j);
4845               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4846                 j));
4847               SvIOK_on(s);
4848               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4849               continue;
4850             }
4851           if (LocaleCompare(attribute,"colors") == 0)
4852             {
4853               if (image != (Image *) NULL)
4854                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4855                   exception));
4856               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4857               continue;
4858             }
4859           if (LocaleNCompare(attribute,"colormap",8) == 0)
4860             {
4861               int
4862                 items;
4863
4864               if (image == (Image *) NULL || !image->colormap)
4865                 break;
4866               j=0;
4867               items=sscanf(attribute,"%*[^[][%ld",&j);
4868               (void) items;
4869               if (j > (ssize_t) image->colors)
4870                 j%=image->colors;
4871               (void) FormatLocaleString(color,MagickPathExtent,
4872                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4873                 (double) image->colormap[j].green,
4874                 (double) image->colormap[j].blue,
4875                 (double) image->colormap[j].alpha);
4876               s=newSVpv(color,0);
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           if (LocaleCompare(attribute,"columns") == 0)
4881             {
4882               if (image != (Image *) NULL)
4883                 s=newSViv((ssize_t) image->columns);
4884               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885               continue;
4886             }
4887           if (LocaleCompare(attribute,"comment") == 0)
4888             {
4889               const char
4890                 *value;
4891
4892               value=GetImageProperty(image,attribute,exception);
4893               if (value != (const char *) NULL)
4894                 s=newSVpv(value,0);
4895               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896               continue;
4897             }
4898           if (LocaleCompare(attribute,"copyright") == 0)
4899             {
4900               s=newSVpv(GetMagickCopyright(),0);
4901               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4902               continue;
4903             }
4904           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4905             attribute);
4906           break;
4907         }
4908         case 'D':
4909         case 'd':
4910         {
4911           if (LocaleCompare(attribute,"density") == 0)
4912             {
4913               char
4914                 geometry[MagickPathExtent];
4915
4916               if (image == (Image *) NULL)
4917                 break;
4918               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4919                 image->resolution.x,image->resolution.y);
4920               s=newSVpv(geometry,0);
4921               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4922               continue;
4923             }
4924           if (LocaleCompare(attribute,"delay") == 0)
4925             {
4926               if (image != (Image *) NULL)
4927                 s=newSViv((ssize_t) image->delay);
4928               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4929               continue;
4930             }
4931           if (LocaleCompare(attribute,"depth") == 0)
4932             {
4933               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4934               if (image != (Image *) NULL)
4935                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4936               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4937               continue;
4938             }
4939           if (LocaleCompare(attribute,"directory") == 0)
4940             {
4941               if (image && image->directory)
4942                 s=newSVpv(image->directory,0);
4943               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4944               continue;
4945             }
4946           if (LocaleCompare(attribute,"dispose") == 0)
4947             {
4948               if (image == (Image *) NULL)
4949                 break;
4950
4951               s=newSViv(image->dispose);
4952               (void) sv_setpv(s,
4953                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4954               SvIOK_on(s);
4955               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4956               continue;
4957             }
4958           if (LocaleCompare(attribute,"disk") == 0)
4959             {
4960               s=newSViv(GetMagickResource(DiskResource));
4961               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4962               continue;
4963             }
4964           if (LocaleCompare(attribute,"dither") == 0)
4965             {
4966               if (info)
4967                 s=newSViv((ssize_t) info->image_info->dither);
4968               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4969               continue;
4970             }
4971           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4972             {
4973               if (info && info->image_info->server_name)
4974                 s=newSVpv(info->image_info->server_name,0);
4975               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4976               continue;
4977             }
4978           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4979             attribute);
4980           break;
4981         }
4982         case 'E':
4983         case 'e':
4984         {
4985           if (LocaleCompare(attribute,"elapsed-time") == 0)
4986             {
4987               if (image != (Image *) NULL)
4988                 s=newSVnv(GetElapsedTime(&image->timer));
4989               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4990               continue;
4991             }
4992           if (LocaleCompare(attribute,"endian") == 0)
4993             {
4994               j=info ? info->image_info->endian : image ? image->endian :
4995                 UndefinedEndian;
4996               s=newSViv(j);
4997               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4998               SvIOK_on(s);
4999               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5000               continue;
5001             }
5002           if (LocaleCompare(attribute,"error") == 0)
5003             {
5004               if (image != (Image *) NULL)
5005                 s=newSVnv(image->error.mean_error_per_pixel);
5006               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5007               continue;
5008             }
5009           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5010             attribute);
5011           break;
5012         }
5013         case 'F':
5014         case 'f':
5015         {
5016           if (LocaleCompare(attribute,"filesize") == 0)
5017             {
5018               if (image != (Image *) NULL)
5019                 s=newSViv((ssize_t) GetBlobSize(image));
5020               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5021               continue;
5022             }
5023           if (LocaleCompare(attribute,"filename") == 0)
5024             {
5025               if (info && info->image_info->filename &&
5026                   *info->image_info->filename)
5027                 s=newSVpv(info->image_info->filename,0);
5028               if (image != (Image *) NULL)
5029                 s=newSVpv(image->filename,0);
5030               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5031               continue;
5032             }
5033           if (LocaleCompare(attribute,"filter") == 0)
5034             {
5035               s=image ? newSViv(image->filter) : newSViv(0);
5036               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5037                 image->filter));
5038               SvIOK_on(s);
5039               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5040               continue;
5041             }
5042           if (LocaleCompare(attribute,"font") == 0)
5043             {
5044               if (info && info->image_info->font)
5045                 s=newSVpv(info->image_info->font,0);
5046               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047               continue;
5048             }
5049           if (LocaleCompare(attribute,"foreground") == 0)
5050             continue;
5051           if (LocaleCompare(attribute,"format") == 0)
5052             {
5053               const MagickInfo
5054                 *magick_info;
5055
5056               magick_info=(const MagickInfo *) NULL;
5057               if (info && (*info->image_info->magick != '\0'))
5058                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5059               if (image != (Image *) NULL)
5060                 magick_info=GetMagickInfo(image->magick,exception);
5061               if ((magick_info != (const MagickInfo *) NULL) &&
5062                   (*magick_info->description != '\0'))
5063                 s=newSVpv((char *) magick_info->description,0);
5064               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5065               continue;
5066             }
5067           if (LocaleCompare(attribute,"fuzz") == 0)
5068             {
5069               if (info)
5070                 s=newSVnv(info->image_info->fuzz);
5071               if (image != (Image *) NULL)
5072                 s=newSVnv(image->fuzz);
5073               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074               continue;
5075             }
5076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5077             attribute);
5078           break;
5079         }
5080         case 'G':
5081         case 'g':
5082         {
5083           if (LocaleCompare(attribute,"gamma") == 0)
5084             {
5085               if (image != (Image *) NULL)
5086                 s=newSVnv(image->gamma);
5087               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5088               continue;
5089             }
5090           if (LocaleCompare(attribute,"geometry") == 0)
5091             {
5092               if (image && image->geometry)
5093                 s=newSVpv(image->geometry,0);
5094               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5095               continue;
5096             }
5097           if (LocaleCompare(attribute,"gravity") == 0)
5098             {
5099               s=image ? newSViv(image->gravity) : newSViv(0);
5100               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5101                 image->gravity));
5102               SvIOK_on(s);
5103               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5104               continue;
5105             }
5106           if (LocaleCompare(attribute,"green-primary") == 0)
5107             {
5108               if (image == (Image *) NULL)
5109                 break;
5110               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5111                 image->chromaticity.green_primary.x,
5112                 image->chromaticity.green_primary.y);
5113               s=newSVpv(color,0);
5114               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5115               continue;
5116             }
5117           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5118             attribute);
5119           break;
5120         }
5121         case 'H':
5122         case 'h':
5123         {
5124           if (LocaleCompare(attribute,"height") == 0)
5125             {
5126               if (image != (Image *) NULL)
5127                 s=newSViv((ssize_t) image->rows);
5128               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5129               continue;
5130             }
5131           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5132             attribute);
5133           break;
5134         }
5135         case 'I':
5136         case 'i':
5137         {
5138           if (LocaleCompare(attribute,"icc") == 0)
5139             {
5140               if (image != (Image *) NULL)
5141                 {
5142                   const StringInfo
5143                     *profile;
5144
5145                   profile=GetImageProfile(image,"icc");
5146                   if (profile != (StringInfo *) NULL)
5147                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5148                       GetStringInfoLength(profile));
5149                 }
5150               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5151               continue;
5152             }
5153           if (LocaleCompare(attribute,"icm") == 0)
5154             {
5155               if (image != (Image *) NULL)
5156                 {
5157                   const StringInfo
5158                     *profile;
5159
5160                   profile=GetImageProfile(image,"icm");
5161                   if (profile != (const StringInfo *) NULL)
5162                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5163                       GetStringInfoLength(profile));
5164                 }
5165               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5166               continue;
5167             }
5168           if (LocaleCompare(attribute,"id") == 0)
5169             {
5170               if (image != (Image *) NULL)
5171                 {
5172                   char
5173                     key[MagickPathExtent];
5174
5175                   MagickBooleanType
5176                     status;
5177
5178                   static ssize_t
5179                     id = 0;
5180
5181                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5182                     id);
5183                   status=SetImageRegistry(ImageRegistryType,key,image,
5184                     exception);
5185                   (void) status;
5186                   s=newSViv(id++);
5187                 }
5188               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5189               continue;
5190             }
5191           if (LocaleNCompare(attribute,"index",5) == 0)
5192             {
5193               char
5194                 name[MagickPathExtent];
5195
5196               int
5197                 items;
5198
5199               long
5200                 x,
5201                 y;
5202
5203               register const Quantum
5204                 *p;
5205
5206               CacheView
5207                 *image_view;
5208
5209               if (image == (Image *) NULL)
5210                 break;
5211               if (image->storage_class != PseudoClass)
5212                 break;
5213               x=0;
5214               y=0;
5215               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5216               (void) items;
5217               image_view=AcquireVirtualCacheView(image,exception);
5218               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5219               if (p != (const Quantum *) NULL)
5220                 {
5221                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5222                     GetPixelIndex(image,p));
5223                   s=newSVpv(name,0);
5224                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5225                 }
5226               image_view=DestroyCacheView(image_view);
5227               continue;
5228             }
5229           if (LocaleCompare(attribute,"iptc") == 0)
5230             {
5231               if (image != (Image *) NULL)
5232                 {
5233                   const StringInfo
5234                     *profile;
5235
5236                   profile=GetImageProfile(image,"iptc");
5237                   if (profile != (const StringInfo *) NULL)
5238                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5239                       GetStringInfoLength(profile));
5240                 }
5241               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5242               continue;
5243             }
5244           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5245             {
5246               if (image != (Image *) NULL)
5247                 s=newSViv((ssize_t) image->iterations);
5248               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5249               continue;
5250             }
5251           if (LocaleCompare(attribute,"interlace") == 0)
5252             {
5253               j=info ? info->image_info->interlace : image ? image->interlace :
5254                 UndefinedInterlace;
5255               s=newSViv(j);
5256               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5257                 j));
5258               SvIOK_on(s);
5259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5260               continue;
5261             }
5262           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5263             attribute);
5264           break;
5265         }
5266         case 'L':
5267         case 'l':
5268         {
5269           if (LocaleCompare(attribute,"label") == 0)
5270             {
5271               const char
5272                 *value;
5273
5274               if (image == (Image *) NULL)
5275                 break;
5276               value=GetImageProperty(image,"Label",exception);
5277               if (value != (const char *) NULL)
5278                 s=newSVpv(value,0);
5279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5280               continue;
5281             }
5282           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5283             {
5284               if (image != (Image *) NULL)
5285                 s=newSViv((ssize_t) image->iterations);
5286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5287               continue;
5288             }
5289           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5290             attribute);
5291           break;
5292         }
5293         case 'M':
5294         case 'm':
5295         {
5296           if (LocaleCompare(attribute,"magick") == 0)
5297             {
5298               if (info && *info->image_info->magick)
5299                 s=newSVpv(info->image_info->magick,0);
5300               if (image != (Image *) NULL)
5301                 s=newSVpv(image->magick,0);
5302               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5303               continue;
5304             }
5305           if (LocaleCompare(attribute,"map") == 0)
5306             {
5307               s=newSViv(GetMagickResource(MapResource));
5308               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5309               continue;
5310             }
5311           if (LocaleCompare(attribute,"maximum-error") == 0)
5312             {
5313               if (image != (Image *) NULL)
5314                 s=newSVnv(image->error.normalized_maximum_error);
5315               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5316               continue;
5317             }
5318           if (LocaleCompare(attribute,"memory") == 0)
5319             {
5320               s=newSViv(GetMagickResource(MemoryResource));
5321               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5322               continue;
5323             }
5324           if (LocaleCompare(attribute,"mean-error") == 0)
5325             {
5326               if (image != (Image *) NULL)
5327                 s=newSVnv(image->error.normalized_mean_error);
5328               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5329               continue;
5330             }
5331           if (LocaleCompare(attribute,"mime") == 0)
5332             {
5333               if (info && *info->image_info->magick)
5334                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5335               if (image != (Image *) NULL)
5336                 s=newSVpv(MagickToMime(image->magick),0);
5337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5338               continue;
5339             }
5340           if (LocaleCompare(attribute,"mattecolor") == 0)
5341             {
5342               if (image == (Image *) NULL)
5343                 break;
5344               (void) FormatLocaleString(color,MagickPathExtent,
5345                 "%.20g,%.20g,%.20g,%.20g",(double) image->matte_color.red,
5346                 (double) image->matte_color.green,
5347                 (double) image->matte_color.blue,
5348                 (double) image->matte_color.alpha);
5349               s=newSVpv(color,0);
5350               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5351               continue;
5352             }
5353           if (LocaleCompare(attribute,"matte") == 0)
5354             {
5355               if (image != (Image *) NULL)
5356                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5357                   1 : 0);
5358               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5359               continue;
5360             }
5361           if (LocaleCompare(attribute,"mime") == 0)
5362             {
5363               const char
5364                 *magick;
5365
5366               magick=NULL;
5367               if (info && *info->image_info->magick)
5368                 magick=info->image_info->magick;
5369               if (image != (Image *) NULL)
5370                 magick=image->magick;
5371               if (magick)
5372                 {
5373                   char
5374                     *mime;
5375
5376                   mime=MagickToMime(magick);
5377                   s=newSVpv(mime,0);
5378                   mime=(char *) RelinquishMagickMemory(mime);
5379                 }
5380               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5381               continue;
5382             }
5383           if (LocaleCompare(attribute,"monochrome") == 0)
5384             {
5385               if (image == (Image *) NULL)
5386                 continue;
5387               j=info ? info->image_info->monochrome :
5388                 SetImageMonochrome(image,exception);
5389               s=newSViv(j);
5390               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5391               continue;
5392             }
5393           if (LocaleCompare(attribute,"montage") == 0)
5394             {
5395               if (image && image->montage)
5396                 s=newSVpv(image->montage,0);
5397               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5398               continue;
5399             }
5400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5401             attribute);
5402           break;
5403         }
5404         case 'O':
5405         case 'o':
5406         {
5407           if (LocaleCompare(attribute,"orientation") == 0)
5408             {
5409               j=info ? info->image_info->orientation : image ?
5410                 image->orientation : UndefinedOrientation;
5411               s=newSViv(j);
5412               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5413                 j));
5414               SvIOK_on(s);
5415               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416               continue;
5417             }
5418           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5419             attribute);
5420           break;
5421         }
5422         case 'P':
5423         case 'p':
5424         {
5425           if (LocaleCompare(attribute,"page") == 0)
5426             {
5427               if (info && info->image_info->page)
5428                 s=newSVpv(info->image_info->page,0);
5429               if (image != (Image *) NULL)
5430                 {
5431                   char
5432                     geometry[MagickPathExtent];
5433
5434                   (void) FormatLocaleString(geometry,MagickPathExtent,
5435                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5436                     (double) image->page.height,(double) image->page.x,(double)
5437                     image->page.y);
5438                   s=newSVpv(geometry,0);
5439                 }
5440               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5441               continue;
5442             }
5443           if (LocaleCompare(attribute,"page.x") == 0)
5444             {
5445               if (image != (Image *) NULL)
5446                 s=newSViv((ssize_t) image->page.x);
5447               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5448               continue;
5449             }
5450           if (LocaleCompare(attribute,"page.y") == 0)
5451             {
5452               if (image != (Image *) NULL)
5453                 s=newSViv((ssize_t) image->page.y);
5454               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5455               continue;
5456             }
5457           if (LocaleNCompare(attribute,"pixel",5) == 0)
5458             {
5459               char
5460                 tuple[MagickPathExtent];
5461
5462               int
5463                 items;
5464
5465               long
5466                 x,
5467                 y;
5468
5469               register const Quantum
5470                 *p;
5471
5472               if (image == (Image *) NULL)
5473                 break;
5474               x=0;
5475               y=0;
5476               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5477               (void) items;
5478               p=GetVirtualPixels(image,x,y,1,1,exception);
5479               if (image->colorspace != CMYKColorspace)
5480                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5481                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5482                   GetPixelRed(image,p),GetPixelGreen(image,p),
5483                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5484               else
5485                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5486                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5487                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5488                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5489                   GetPixelAlpha(image,p));
5490               s=newSVpv(tuple,0);
5491               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5492               continue;
5493             }
5494           if (LocaleCompare(attribute,"pointsize") == 0)
5495             {
5496               if (info)
5497                 s=newSViv((ssize_t) info->image_info->pointsize);
5498               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5499               continue;
5500             }
5501           if (LocaleCompare(attribute,"preview") == 0)
5502             {
5503               s=newSViv(info->image_info->preview_type);
5504               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5505                 info->image_info->preview_type));
5506               SvIOK_on(s);
5507               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5508               continue;
5509             }
5510           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5511             attribute);
5512           break;
5513         }
5514         case 'Q':
5515         case 'q':
5516         {
5517           if (LocaleCompare(attribute,"quality") == 0)
5518             {
5519               if (info)
5520                 s=newSViv((ssize_t) info->image_info->quality);
5521               if (image != (Image *) NULL)
5522                 s=newSViv((ssize_t) image->quality);
5523               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5524               continue;
5525             }
5526           if (LocaleCompare(attribute,"quantum") == 0)
5527             {
5528               if (info)
5529                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5530               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5531               continue;
5532             }
5533           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5534             attribute);
5535           break;
5536         }
5537         case 'R':
5538         case 'r':
5539         {
5540           if (LocaleCompare(attribute,"rendering-intent") == 0)
5541             {
5542               s=newSViv(image->rendering_intent);
5543               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5544                 image->rendering_intent));
5545               SvIOK_on(s);
5546               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5547               continue;
5548             }
5549           if (LocaleCompare(attribute,"red-primary") == 0)
5550             {
5551               if (image == (Image *) NULL)
5552                 break;
5553               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5554                 image->chromaticity.red_primary.x,
5555                 image->chromaticity.red_primary.y);
5556               s=newSVpv(color,0);
5557               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5558               continue;
5559             }
5560           if (LocaleCompare(attribute,"rows") == 0)
5561             {
5562               if (image != (Image *) NULL)
5563                 s=newSViv((ssize_t) image->rows);
5564               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5565               continue;
5566             }
5567           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5568             attribute);
5569           break;
5570         }
5571         case 'S':
5572         case 's':
5573         {
5574           if (LocaleCompare(attribute,"sampling-factor") == 0)
5575             {
5576               if (info && info->image_info->sampling_factor)
5577                 s=newSVpv(info->image_info->sampling_factor,0);
5578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5579               continue;
5580             }
5581           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5582             {
5583               if (info && info->image_info->server_name)
5584                 s=newSVpv(info->image_info->server_name,0);
5585               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5586               continue;
5587             }
5588           if (LocaleCompare(attribute,"size") == 0)
5589             {
5590               if (info && info->image_info->size)
5591                 s=newSVpv(info->image_info->size,0);
5592               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5593               continue;
5594             }
5595           if (LocaleCompare(attribute,"scene") == 0)
5596             {
5597               if (image != (Image *) NULL)
5598                 s=newSViv((ssize_t) image->scene);
5599               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5600               continue;
5601             }
5602           if (LocaleCompare(attribute,"scenes") == 0)
5603             {
5604               if (image != (Image *) NULL)
5605                 s=newSViv((ssize_t) info->image_info->number_scenes);
5606               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5607               continue;
5608             }
5609           if (LocaleCompare(attribute,"signature") == 0)
5610             {
5611               const char
5612                 *value;
5613
5614               if (image == (Image *) NULL)
5615                 break;
5616               (void) SignatureImage(image,exception);
5617               value=GetImageProperty(image,"Signature",exception);
5618               if (value != (const char *) NULL)
5619                 s=newSVpv(value,0);
5620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5621               continue;
5622             }
5623           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5624             attribute);
5625           break;
5626         }
5627         case 'T':
5628         case 't':
5629         {
5630           if (LocaleCompare(attribute,"taint") == 0)
5631             {
5632               if (image != (Image *) NULL)
5633                 s=newSViv((ssize_t) IsTaintImage(image));
5634               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5635               continue;
5636             }
5637           if (LocaleCompare(attribute,"texture") == 0)
5638             {
5639               if (info && info->image_info->texture)
5640                 s=newSVpv(info->image_info->texture,0);
5641               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5642               continue;
5643             }
5644           if (LocaleCompare(attribute,"total-ink-density") == 0)
5645             {
5646               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5647               if (image != (Image *) NULL)
5648                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5650               continue;
5651             }
5652           if (LocaleCompare(attribute,"transparent-color") == 0)
5653             {
5654               if (image == (Image *) NULL)
5655                 break;
5656               (void) FormatLocaleString(color,MagickPathExtent,
5657                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5658                 (double) image->transparent_color.green,
5659                 (double) image->transparent_color.blue,
5660                 (double) image->transparent_color.alpha);
5661               s=newSVpv(color,0);
5662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5663               continue;
5664             }
5665           if (LocaleCompare(attribute,"type") == 0)
5666             {
5667               if (image == (Image *) NULL)
5668                 break;
5669               j=(ssize_t) GetImageType(image);
5670               s=newSViv(j);
5671               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5672               SvIOK_on(s);
5673               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5674               continue;
5675             }
5676           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5677             attribute);
5678           break;
5679         }
5680         case 'U':
5681         case 'u':
5682         {
5683           if (LocaleCompare(attribute,"units") == 0)
5684             {
5685               j=info ? info->image_info->units : image ? image->units :
5686                 UndefinedResolution;
5687               if (info && (info->image_info->units == UndefinedResolution))
5688                 if (image)
5689                   j=image->units;
5690               if (j == UndefinedResolution)
5691                 s=newSVpv("undefined units",0);
5692               else
5693                 if (j == PixelsPerInchResolution)
5694                   s=newSVpv("pixels / inch",0);
5695                 else
5696                   s=newSVpv("pixels / centimeter",0);
5697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698               continue;
5699             }
5700           if (LocaleCompare(attribute,"user-time") == 0)
5701             {
5702               if (image != (Image *) NULL)
5703                 s=newSVnv(GetUserTime(&image->timer));
5704               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5705               continue;
5706             }
5707           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5708             attribute);
5709           break;
5710         }
5711         case 'V':
5712         case 'v':
5713         {
5714           if (LocaleCompare(attribute,"verbose") == 0)
5715             {
5716               if (info)
5717                 s=newSViv((ssize_t) info->image_info->verbose);
5718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5719               continue;
5720             }
5721           if (LocaleCompare(attribute,"version") == 0)
5722             {
5723               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5724               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5725               continue;
5726             }
5727           if (LocaleCompare(attribute,"view") == 0)
5728             {
5729               if (info && info->image_info->view)
5730                 s=newSVpv(info->image_info->view,0);
5731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5732               continue;
5733             }
5734           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5735             {
5736               if (image == (Image *) NULL)
5737                 break;
5738               j=(ssize_t) GetImageVirtualPixelMethod(image);
5739               s=newSViv(j);
5740               (void) sv_setpv(s,CommandOptionToMnemonic(
5741                 MagickVirtualPixelOptions,j));
5742               SvIOK_on(s);
5743               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5744               continue;
5745             }
5746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5747             attribute);
5748           break;
5749         }
5750         case 'W':
5751         case 'w':
5752         {
5753           if (LocaleCompare(attribute,"white-point") == 0)
5754             {
5755               if (image == (Image *) NULL)
5756                 break;
5757               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5758                 image->chromaticity.white_point.x,
5759                 image->chromaticity.white_point.y);
5760               s=newSVpv(color,0);
5761               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5762               continue;
5763             }
5764           if (LocaleCompare(attribute,"width") == 0)
5765             {
5766               if (image != (Image *) NULL)
5767                 s=newSViv((ssize_t) image->columns);
5768               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5769               continue;
5770             }
5771           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5772              attribute);
5773           break;
5774         }
5775         case 'X':
5776         case 'x':
5777         {
5778           if (LocaleCompare(attribute,"x-resolution") == 0)
5779             {
5780               if (image != (Image *) NULL)
5781                 s=newSVnv(image->resolution.x);
5782               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5783               continue;
5784             }
5785           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5786             attribute);
5787           break;
5788         }
5789         case 'Y':
5790         case 'y':
5791         {
5792           if (LocaleCompare(attribute,"y-resolution") == 0)
5793             {
5794               if (image != (Image *) NULL)
5795                 s=newSVnv(image->resolution.y);
5796               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5797               continue;
5798             }
5799           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5800             attribute);
5801           break;
5802         }
5803         default:
5804           break;
5805       }
5806       if (image == (Image *) NULL)
5807         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5808           attribute)
5809       else
5810         {
5811           value=GetImageProperty(image,attribute,exception);
5812           if (value != (const char *) NULL)
5813             {
5814               s=newSVpv(value,0);
5815               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5816             }
5817           else
5818             if (*attribute != '%')
5819               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5820                 attribute)
5821             else
5822               {
5823                  char
5824                    *meta;
5825
5826                  meta=InterpretImageProperties(info ? info->image_info :
5827                    (ImageInfo *) NULL,image,attribute,exception);
5828                  s=newSVpv(meta,0);
5829                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5830                  meta=(char *) RelinquishMagickMemory(meta);
5831               }
5832         }
5833     }
5834     exception=DestroyExceptionInfo(exception);
5835     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5836   }
5837 \f
5838 #
5839 ###############################################################################
5840 #                                                                             #
5841 #                                                                             #
5842 #                                                                             #
5843 #   G e t A u t h e n t i c P i x e l s                                       #
5844 #                                                                             #
5845 #                                                                             #
5846 #                                                                             #
5847 ###############################################################################
5848 #
5849 #
5850 void *
5851 GetAuthenticPixels(ref,...)
5852   Image::Magick ref = NO_INIT
5853   ALIAS:
5854     getauthenticpixels = 1
5855     GetImagePixels = 2
5856     getimagepixels = 3
5857   CODE:
5858   {
5859     char
5860       *attribute;
5861
5862     ExceptionInfo
5863       *exception;
5864
5865     Image
5866       *image;
5867
5868     RectangleInfo
5869       region;
5870
5871     ssize_t
5872       i;
5873
5874     struct PackageInfo
5875       *info;
5876
5877     SV
5878       *perl_exception,
5879       *reference;
5880
5881     void
5882       *blob = NULL;
5883
5884     PERL_UNUSED_VAR(ref);
5885     PERL_UNUSED_VAR(ix);
5886     exception=AcquireExceptionInfo();
5887     perl_exception=newSVpv("",0);
5888     if (sv_isobject(ST(0)) == 0)
5889       {
5890         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5891           PackageName);
5892         goto PerlException;
5893       }
5894     reference=SvRV(ST(0));
5895
5896     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5897     if (image == (Image *) NULL)
5898       {
5899         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5900           PackageName);
5901         goto PerlException;
5902       }
5903
5904     region.x=0;
5905     region.y=0;
5906     region.width=image->columns;
5907     region.height=1;
5908     if (items == 1)
5909       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5910     for (i=2; i < items; i+=2)
5911     {
5912       attribute=(char *) SvPV(ST(i-1),na);
5913       switch (*attribute)
5914       {
5915         case 'g':
5916         case 'G':
5917         {
5918           if (LocaleCompare(attribute,"geometry") == 0)
5919             {
5920               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5921               break;
5922             }
5923           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5924             attribute);
5925           break;
5926         }
5927         case 'H':
5928         case 'h':
5929         {
5930           if (LocaleCompare(attribute,"height") == 0)
5931             {
5932               region.height=SvIV(ST(i));
5933               continue;
5934             }
5935           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5936             attribute);
5937           break;
5938         }
5939         case 'X':
5940         case 'x':
5941         {
5942           if (LocaleCompare(attribute,"x") == 0)
5943             {
5944               region.x=SvIV(ST(i));
5945               continue;
5946             }
5947           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5948             attribute);
5949           break;
5950         }
5951         case 'Y':
5952         case 'y':
5953         {
5954           if (LocaleCompare(attribute,"y") == 0)
5955             {
5956               region.y=SvIV(ST(i));
5957               continue;
5958             }
5959           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5960             attribute);
5961           break;
5962         }
5963         case 'W':
5964         case 'w':
5965         {
5966           if (LocaleCompare(attribute,"width") == 0)
5967             {
5968               region.width=SvIV(ST(i));
5969               continue;
5970             }
5971           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5972             attribute);
5973           break;
5974         }
5975       }
5976     }
5977     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5978       region.height,exception);
5979     if (blob != (void *) NULL)
5980       goto PerlEnd;
5981
5982   PerlException:
5983     InheritPerlException(exception,perl_exception);
5984     exception=DestroyExceptionInfo(exception);
5985     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5986
5987   PerlEnd:
5988     RETVAL = blob;
5989   }
5990   OUTPUT:
5991     RETVAL
5992 \f
5993 #
5994 ###############################################################################
5995 #                                                                             #
5996 #                                                                             #
5997 #                                                                             #
5998 #   G e t V i r t u a l P i x e l s                                           #
5999 #                                                                             #
6000 #                                                                             #
6001 #                                                                             #
6002 ###############################################################################
6003 #
6004 #
6005 void *
6006 GetVirtualPixels(ref,...)
6007   Image::Magick ref = NO_INIT
6008   ALIAS:
6009     getvirtualpixels = 1
6010     AcquireImagePixels = 2
6011     acquireimagepixels = 3
6012   CODE:
6013   {
6014     char
6015       *attribute;
6016
6017     const void
6018       *blob = NULL;
6019
6020     ExceptionInfo
6021       *exception;
6022
6023     Image
6024       *image;
6025
6026     RectangleInfo
6027       region;
6028
6029     ssize_t
6030       i;
6031
6032     struct PackageInfo
6033       *info;
6034
6035     SV
6036       *perl_exception,
6037       *reference;
6038
6039     PERL_UNUSED_VAR(ref);
6040     PERL_UNUSED_VAR(ix);
6041     exception=AcquireExceptionInfo();
6042     perl_exception=newSVpv("",0);
6043     if (sv_isobject(ST(0)) == 0)
6044       {
6045         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6046           PackageName);
6047         goto PerlException;
6048       }
6049     reference=SvRV(ST(0));
6050
6051     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6052     if (image == (Image *) NULL)
6053       {
6054         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6055           PackageName);
6056         goto PerlException;
6057       }
6058
6059     region.x=0;
6060     region.y=0;
6061     region.width=image->columns;
6062     region.height=1;
6063     if (items == 1)
6064       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6065     for (i=2; i < items; i+=2)
6066     {
6067       attribute=(char *) SvPV(ST(i-1),na);
6068       switch (*attribute)
6069       {
6070         case 'g':
6071         case 'G':
6072         {
6073           if (LocaleCompare(attribute,"geometry") == 0)
6074             {
6075               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6076               break;
6077             }
6078           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6079             attribute);
6080           break;
6081         }
6082         case 'H':
6083         case 'h':
6084         {
6085           if (LocaleCompare(attribute,"height") == 0)
6086             {
6087               region.height=SvIV(ST(i));
6088               continue;
6089             }
6090           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6091             attribute);
6092           break;
6093         }
6094         case 'X':
6095         case 'x':
6096         {
6097           if (LocaleCompare(attribute,"x") == 0)
6098             {
6099               region.x=SvIV(ST(i));
6100               continue;
6101             }
6102           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6103             attribute);
6104           break;
6105         }
6106         case 'Y':
6107         case 'y':
6108         {
6109           if (LocaleCompare(attribute,"y") == 0)
6110             {
6111               region.y=SvIV(ST(i));
6112               continue;
6113             }
6114           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6115             attribute);
6116           break;
6117         }
6118         case 'W':
6119         case 'w':
6120         {
6121           if (LocaleCompare(attribute,"width") == 0)
6122             {
6123               region.width=SvIV(ST(i));
6124               continue;
6125             }
6126           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6127             attribute);
6128           break;
6129         }
6130       }
6131     }
6132     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6133       region.height,exception);
6134     if (blob != (void *) NULL)
6135       goto PerlEnd;
6136
6137   PerlException:
6138     InheritPerlException(exception,perl_exception);
6139     exception=DestroyExceptionInfo(exception);
6140     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6141
6142   PerlEnd:
6143     RETVAL = (void *) blob;
6144   }
6145   OUTPUT:
6146     RETVAL
6147 \f
6148 #
6149 ###############################################################################
6150 #                                                                             #
6151 #                                                                             #
6152 #                                                                             #
6153 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6154 #                                                                             #
6155 #                                                                             #
6156 #                                                                             #
6157 ###############################################################################
6158 #
6159 #
6160 void *
6161 GetAuthenticMetacontent(ref,...)
6162   Image::Magick ref = NO_INIT
6163   ALIAS:
6164     getauthenticmetacontent = 1
6165     GetMetacontent = 2
6166     getmetacontent = 3
6167   CODE:
6168   {
6169     ExceptionInfo
6170       *exception;
6171
6172     Image
6173       *image;
6174
6175     struct PackageInfo
6176       *info;
6177
6178     SV
6179       *perl_exception,
6180       *reference;
6181
6182     void
6183       *blob = NULL;
6184
6185     PERL_UNUSED_VAR(ref);
6186     PERL_UNUSED_VAR(ix);
6187     exception=AcquireExceptionInfo();
6188     perl_exception=newSVpv("",0);
6189     if (sv_isobject(ST(0)) == 0)
6190       {
6191         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6192           PackageName);
6193         goto PerlException;
6194       }
6195     reference=SvRV(ST(0));
6196
6197     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6198     if (image == (Image *) NULL)
6199       {
6200         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6201           PackageName);
6202         goto PerlException;
6203       }
6204
6205     blob=(void *) GetAuthenticMetacontent(image);
6206     if (blob != (void *) NULL)
6207       goto PerlEnd;
6208
6209   PerlException:
6210     InheritPerlException(exception,perl_exception);
6211     exception=DestroyExceptionInfo(exception);
6212     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6213
6214   PerlEnd:
6215     RETVAL = blob;
6216   }
6217   OUTPUT:
6218     RETVAL
6219 \f
6220 #
6221 ###############################################################################
6222 #                                                                             #
6223 #                                                                             #
6224 #                                                                             #
6225 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6226 #                                                                             #
6227 #                                                                             #
6228 #                                                                             #
6229 ###############################################################################
6230 #
6231 #
6232 void *
6233 GetVirtualMetacontent(ref,...)
6234   Image::Magick ref = NO_INIT
6235   ALIAS:
6236     getvirtualmetacontent = 1
6237   CODE:
6238   {
6239     ExceptionInfo
6240       *exception;
6241
6242     Image
6243       *image;
6244
6245     struct PackageInfo
6246       *info;
6247
6248     SV
6249       *perl_exception,
6250       *reference;
6251
6252     void
6253       *blob = NULL;
6254
6255     PERL_UNUSED_VAR(ref);
6256     PERL_UNUSED_VAR(ix);
6257     exception=AcquireExceptionInfo();
6258     perl_exception=newSVpv("",0);
6259     if (sv_isobject(ST(0)) == 0)
6260       {
6261         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6262           PackageName);
6263         goto PerlException;
6264       }
6265     reference=SvRV(ST(0));
6266
6267     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6268     if (image == (Image *) NULL)
6269       {
6270         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6271           PackageName);
6272         goto PerlException;
6273       }
6274
6275     blob=(void *) GetVirtualMetacontent(image);
6276     if (blob != (void *) NULL)
6277       goto PerlEnd;
6278
6279   PerlException:
6280     InheritPerlException(exception,perl_exception);
6281     exception=DestroyExceptionInfo(exception);
6282     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6283
6284   PerlEnd:
6285     RETVAL = blob;
6286   }
6287   OUTPUT:
6288     RETVAL
6289 \f
6290 #
6291 ###############################################################################
6292 #                                                                             #
6293 #                                                                             #
6294 #                                                                             #
6295 #   H i s t o g r a m                                                         #
6296 #                                                                             #
6297 #                                                                             #
6298 #                                                                             #
6299 ###############################################################################
6300 #
6301 #
6302 void
6303 Histogram(ref,...)
6304   Image::Magick ref=NO_INIT
6305   ALIAS:
6306     HistogramImage = 1
6307     histogram      = 2
6308     histogramimage = 3
6309   PPCODE:
6310   {
6311     AV
6312       *av;
6313
6314     char
6315       message[MagickPathExtent];
6316
6317     PixelInfo
6318       *histogram;
6319
6320     ExceptionInfo
6321       *exception;
6322
6323     Image
6324       *image;
6325
6326     register ssize_t
6327       i;
6328
6329     ssize_t
6330       count;
6331
6332     struct PackageInfo
6333       *info;
6334
6335     SV
6336       *perl_exception,
6337       *reference;
6338
6339     size_t
6340       number_colors;
6341
6342     PERL_UNUSED_VAR(ref);
6343     PERL_UNUSED_VAR(ix);
6344     exception=AcquireExceptionInfo();
6345     perl_exception=newSVpv("",0);
6346     av=NULL;
6347     if (sv_isobject(ST(0)) == 0)
6348       {
6349         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6350           PackageName);
6351         goto PerlException;
6352       }
6353     reference=SvRV(ST(0));
6354     av=newAV();
6355     SvREFCNT_dec(av);
6356     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6357     if (image == (Image *) NULL)
6358       {
6359         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6360           PackageName);
6361         goto PerlException;
6362       }
6363     count=0;
6364     for ( ; image; image=image->next)
6365     {
6366       histogram=GetImageHistogram(image,&number_colors,exception);
6367       if (histogram == (PixelInfo *) NULL)
6368         continue;
6369       count+=(ssize_t) number_colors;
6370       EXTEND(sp,6*count);
6371       for (i=0; i < (ssize_t) number_colors; i++)
6372       {
6373         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6374           histogram[i].red);
6375         PUSHs(sv_2mortal(newSVpv(message,0)));
6376         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6377           histogram[i].green);
6378         PUSHs(sv_2mortal(newSVpv(message,0)));
6379         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6380           histogram[i].blue);
6381         PUSHs(sv_2mortal(newSVpv(message,0)));
6382         if (image->colorspace == CMYKColorspace)
6383           {
6384             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6385               histogram[i].black);
6386             PUSHs(sv_2mortal(newSVpv(message,0)));
6387           }
6388         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6389           histogram[i].alpha);
6390         PUSHs(sv_2mortal(newSVpv(message,0)));
6391         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6392           histogram[i].count);
6393         PUSHs(sv_2mortal(newSVpv(message,0)));
6394       }
6395       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6396     }
6397
6398   PerlException:
6399     InheritPerlException(exception,perl_exception);
6400     exception=DestroyExceptionInfo(exception);
6401     SvREFCNT_dec(perl_exception);
6402   }
6403 \f
6404 #
6405 ###############################################################################
6406 #                                                                             #
6407 #                                                                             #
6408 #                                                                             #
6409 #   G e t P i x e l                                                           #
6410 #                                                                             #
6411 #                                                                             #
6412 #                                                                             #
6413 ###############################################################################
6414 #
6415 #
6416 void
6417 GetPixel(ref,...)
6418   Image::Magick ref=NO_INIT
6419   ALIAS:
6420     getpixel = 1
6421     getPixel = 2
6422   PPCODE:
6423   {
6424     AV
6425       *av;
6426
6427     char
6428       *attribute;
6429
6430     ExceptionInfo
6431       *exception;
6432
6433     Image
6434       *image;
6435
6436     MagickBooleanType
6437       normalize;
6438
6439     RectangleInfo
6440       region;
6441
6442     register const Quantum
6443       *p;
6444
6445     register ssize_t
6446       i;
6447
6448     ssize_t
6449       option;
6450
6451     struct PackageInfo
6452       *info;
6453
6454     SV
6455       *perl_exception,
6456       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6457
6458     PERL_UNUSED_VAR(ref);
6459     PERL_UNUSED_VAR(ix);
6460     exception=AcquireExceptionInfo();
6461     perl_exception=newSVpv("",0);
6462     reference=SvRV(ST(0));
6463     av=(AV *) reference;
6464     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6465       exception);
6466     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6467     if (image == (Image *) NULL)
6468       {
6469         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6470           PackageName);
6471         goto PerlException;
6472       }
6473     normalize=MagickTrue;
6474     region.x=0;
6475     region.y=0;
6476     region.width=image->columns;
6477     region.height=1;
6478     if (items == 1)
6479       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6480     for (i=2; i < items; i+=2)
6481     {
6482       attribute=(char *) SvPV(ST(i-1),na);
6483       switch (*attribute)
6484       {
6485         case 'C':
6486         case 'c':
6487         {
6488           if (LocaleCompare(attribute,"channel") == 0)
6489             {
6490               ssize_t
6491                 option;
6492
6493               option=ParseChannelOption(SvPV(ST(i),na));
6494               if (option < 0)
6495                 {
6496                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6497                     SvPV(ST(i),na));
6498                   return;
6499                 }
6500               (void) SetPixelChannelMask(image,(ChannelType) option);
6501               break;
6502             }
6503           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6504             attribute);
6505           break;
6506         }
6507         case 'g':
6508         case 'G':
6509         {
6510           if (LocaleCompare(attribute,"geometry") == 0)
6511             {
6512               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6513               break;
6514             }
6515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6516             attribute);
6517           break;
6518         }
6519         case 'N':
6520         case 'n':
6521         {
6522           if (LocaleCompare(attribute,"normalize") == 0)
6523             {
6524               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6525                 SvPV(ST(i),na));
6526               if (option < 0)
6527                 {
6528                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6529                     SvPV(ST(i),na));
6530                   break;
6531                 }
6532              normalize=option != 0 ? MagickTrue : MagickFalse;
6533              break;
6534             }
6535           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6536             attribute);
6537           break;
6538         }
6539         case 'x':
6540         case 'X':
6541         {
6542           if (LocaleCompare(attribute,"x") == 0)
6543             {
6544               region.x=SvIV(ST(i));
6545               break;
6546             }
6547           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6548             attribute);
6549           break;
6550         }
6551         case 'y':
6552         case 'Y':
6553         {
6554           if (LocaleCompare(attribute,"y") == 0)
6555             {
6556               region.y=SvIV(ST(i));
6557               break;
6558             }
6559           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6560             attribute);
6561           break;
6562         }
6563         default:
6564         {
6565           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6566             attribute);
6567           break;
6568         }
6569       }
6570     }
6571     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6572     if (p == (const Quantum *) NULL)
6573       PUSHs(&sv_undef);
6574     else
6575       {
6576         double
6577           scale;
6578
6579         scale=1.0;
6580         if (normalize != MagickFalse)
6581           scale=1.0/QuantumRange;
6582         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6583           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6584         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6585           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6586         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6587           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6588         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6589             (image->colorspace == CMYKColorspace))
6590           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6591         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6592           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6593       }
6594
6595   PerlException:
6596     InheritPerlException(exception,perl_exception);
6597     exception=DestroyExceptionInfo(exception);
6598     SvREFCNT_dec(perl_exception);
6599   }
6600 \f
6601 #
6602 ###############################################################################
6603 #                                                                             #
6604 #                                                                             #
6605 #                                                                             #
6606 #   G e t P i x e l s                                                         #
6607 #                                                                             #
6608 #                                                                             #
6609 #                                                                             #
6610 ###############################################################################
6611 #
6612 #
6613 void
6614 GetPixels(ref,...)
6615   Image::Magick ref=NO_INIT
6616   ALIAS:
6617     getpixels = 1
6618     getPixels = 2
6619   PPCODE:
6620   {
6621     AV
6622       *av;
6623
6624     char
6625       *attribute;
6626
6627     const char
6628       *map;
6629
6630     ExceptionInfo
6631       *exception;
6632
6633     Image
6634       *image;
6635
6636     MagickBooleanType
6637       normalize,
6638       status;
6639
6640     RectangleInfo
6641       region;
6642
6643     register ssize_t
6644       i;
6645
6646     ssize_t
6647       option;
6648
6649     struct PackageInfo
6650       *info;
6651
6652     SV
6653       *perl_exception,
6654       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6655
6656     PERL_UNUSED_VAR(ref);
6657     PERL_UNUSED_VAR(ix);
6658     exception=AcquireExceptionInfo();
6659     perl_exception=newSVpv("",0);
6660     reference=SvRV(ST(0));
6661     av=(AV *) reference;
6662     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6663       exception);
6664     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6665     if (image == (Image *) NULL)
6666       {
6667         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6668           PackageName);
6669         goto PerlException;
6670       }
6671     map="RGB";
6672     if (image->alpha_trait != UndefinedPixelTrait)
6673       map="RGBA";
6674     if (image->colorspace == CMYKColorspace)
6675       {
6676         map="CMYK";
6677         if (image->alpha_trait != UndefinedPixelTrait)
6678           map="CMYKA";
6679       }
6680     normalize=MagickFalse;
6681     region.x=0;
6682     region.y=0;
6683     region.width=image->columns;
6684     region.height=1;
6685     if (items == 1)
6686       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6687     for (i=2; i < items; i+=2)
6688     {
6689       attribute=(char *) SvPV(ST(i-1),na);
6690       switch (*attribute)
6691       {
6692         case 'g':
6693         case 'G':
6694         {
6695           if (LocaleCompare(attribute,"geometry") == 0)
6696             {
6697               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6698               break;
6699             }
6700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6701             attribute);
6702           break;
6703         }
6704         case 'H':
6705         case 'h':
6706         {
6707           if (LocaleCompare(attribute,"height") == 0)
6708             {
6709               region.height=SvIV(ST(i));
6710               break;
6711             }
6712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6713             attribute);
6714           break;
6715         }
6716         case 'M':
6717         case 'm':
6718         {
6719           if (LocaleCompare(attribute,"map") == 0)
6720             {
6721               map=SvPV(ST(i),na);
6722               break;
6723             }
6724           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6725             attribute);
6726           break;
6727         }
6728         case 'N':
6729         case 'n':
6730         {
6731           if (LocaleCompare(attribute,"normalize") == 0)
6732             {
6733               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6734                 SvPV(ST(i),na));
6735               if (option < 0)
6736                 {
6737                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6738                     SvPV(ST(i),na));
6739                   break;
6740                 }
6741              normalize=option != 0 ? MagickTrue : MagickFalse;
6742              break;
6743             }
6744           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6745             attribute);
6746           break;
6747         }
6748         case 'W':
6749         case 'w':
6750         {
6751           if (LocaleCompare(attribute,"width") == 0)
6752             {
6753               region.width=SvIV(ST(i));
6754               break;
6755             }
6756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6757             attribute);
6758           break;
6759         }
6760         case 'x':
6761         case 'X':
6762         {
6763           if (LocaleCompare(attribute,"x") == 0)
6764             {
6765               region.x=SvIV(ST(i));
6766               break;
6767             }
6768           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6769             attribute);
6770           break;
6771         }
6772         case 'y':
6773         case 'Y':
6774         {
6775           if (LocaleCompare(attribute,"y") == 0)
6776             {
6777               region.y=SvIV(ST(i));
6778               break;
6779             }
6780           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6781             attribute);
6782           break;
6783         }
6784         default:
6785         {
6786           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6787             attribute);
6788           break;
6789         }
6790       }
6791     }
6792     if (normalize != MagickFalse)
6793       {
6794         float
6795           *pixels;
6796
6797         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6798           region.height*sizeof(*pixels));
6799         if (pixels == (float *) NULL)
6800           {
6801             ThrowPerlException(exception,ResourceLimitError,
6802               "MemoryAllocationFailed",PackageName);
6803             goto PerlException;
6804           }
6805         status=ExportImagePixels(image,region.x,region.y,region.width,
6806           region.height,map,FloatPixel,pixels,exception);
6807         if (status == MagickFalse)
6808           PUSHs(&sv_undef);
6809         else
6810           {
6811             EXTEND(sp,strlen(map)*region.width*region.height);
6812             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6813               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6814           }
6815         pixels=(float *) RelinquishMagickMemory(pixels);
6816       }
6817     else
6818       {
6819         Quantum
6820           *pixels;
6821
6822         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6823           region.height*sizeof(*pixels));
6824         if (pixels == (Quantum *) NULL)
6825           {
6826             ThrowPerlException(exception,ResourceLimitError,
6827               "MemoryAllocationFailed",PackageName);
6828             goto PerlException;
6829           }
6830         status=ExportImagePixels(image,region.x,region.y,region.width,
6831           region.height,map,QuantumPixel,pixels,exception);
6832         if (status == MagickFalse)
6833           PUSHs(&sv_undef);
6834         else
6835           {
6836             EXTEND(sp,strlen(map)*region.width*region.height);
6837             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6838               PUSHs(sv_2mortal(newSViv(pixels[i])));
6839           }
6840         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6841       }
6842
6843   PerlException:
6844     InheritPerlException(exception,perl_exception);
6845     exception=DestroyExceptionInfo(exception);
6846     SvREFCNT_dec(perl_exception);
6847   }
6848 \f
6849 #
6850 ###############################################################################
6851 #                                                                             #
6852 #                                                                             #
6853 #                                                                             #
6854 #   I m a g e T o B l o b                                                     #
6855 #                                                                             #
6856 #                                                                             #
6857 #                                                                             #
6858 ###############################################################################
6859 #
6860 #
6861 void
6862 ImageToBlob(ref,...)
6863   Image::Magick ref=NO_INIT
6864   ALIAS:
6865     ImageToBlob  = 1
6866     imagetoblob  = 2
6867     toblob       = 3
6868     blob         = 4
6869   PPCODE:
6870   {
6871     char
6872       filename[MagickPathExtent];
6873
6874     ExceptionInfo
6875       *exception;
6876
6877     Image
6878       *image,
6879       *next;
6880
6881     register ssize_t
6882       i;
6883
6884     struct PackageInfo
6885       *info,
6886       *package_info;
6887
6888     size_t
6889       length;
6890
6891     ssize_t
6892       scene;
6893
6894     SV
6895       *perl_exception,
6896       *reference;
6897
6898     void
6899       *blob;
6900
6901     PERL_UNUSED_VAR(ref);
6902     PERL_UNUSED_VAR(ix);
6903     exception=AcquireExceptionInfo();
6904     perl_exception=newSVpv("",0);
6905     package_info=(struct PackageInfo *) NULL;
6906     if (sv_isobject(ST(0)) == 0)
6907       {
6908         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6909           PackageName);
6910         goto PerlException;
6911       }
6912     reference=SvRV(ST(0));
6913     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6914     if (image == (Image *) NULL)
6915       {
6916         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6917           PackageName);
6918         goto PerlException;
6919       }
6920     package_info=ClonePackageInfo(info,exception);
6921     for (i=2; i < items; i+=2)
6922       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6923     (void) CopyMagickString(filename,package_info->image_info->filename,
6924       MagickPathExtent);
6925     scene=0;
6926     for (next=image; next; next=next->next)
6927     {
6928       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6929       next->scene=scene++;
6930     }
6931     SetImageInfo(package_info->image_info,(unsigned int)
6932       GetImageListLength(image),exception);
6933     EXTEND(sp,(ssize_t) GetImageListLength(image));
6934     for ( ; image; image=image->next)
6935     {
6936       length=0;
6937       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6938       if (blob != (char *) NULL)
6939         {
6940           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6941           blob=(unsigned char *) RelinquishMagickMemory(blob);
6942         }
6943       if (package_info->image_info->adjoin)
6944         break;
6945     }
6946
6947   PerlException:
6948     if (package_info != (struct PackageInfo *) NULL)
6949       DestroyPackageInfo(package_info);
6950     InheritPerlException(exception,perl_exception);
6951     exception=DestroyExceptionInfo(exception);
6952     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6953   }
6954 \f
6955 #
6956 ###############################################################################
6957 #                                                                             #
6958 #                                                                             #
6959 #                                                                             #
6960 #   L a y e r s                                                               #
6961 #                                                                             #
6962 #                                                                             #
6963 #                                                                             #
6964 ###############################################################################
6965 #
6966 #
6967 void
6968 Layers(ref,...)
6969   Image::Magick ref=NO_INIT
6970   ALIAS:
6971     Layers                = 1
6972     layers           = 2
6973     OptimizeImageLayers   = 3
6974     optimizelayers        = 4
6975     optimizeimagelayers   = 5
6976   PPCODE:
6977   {
6978     AV
6979       *av;
6980
6981     char
6982       *attribute;
6983
6984     CompositeOperator
6985       compose;
6986
6987     ExceptionInfo
6988       *exception;
6989
6990     HV
6991       *hv;
6992
6993     Image
6994       *image,
6995       *layers;
6996
6997     LayerMethod
6998       method;
6999
7000     register ssize_t
7001       i;
7002
7003     ssize_t
7004       option,
7005       sp;
7006
7007     struct PackageInfo
7008       *info;
7009
7010     SV
7011       *av_reference,
7012       *perl_exception,
7013       *reference,
7014       *rv,
7015       *sv;
7016
7017     PERL_UNUSED_VAR(ref);
7018     PERL_UNUSED_VAR(ix);
7019     exception=AcquireExceptionInfo();
7020     perl_exception=newSVpv("",0);
7021     sv=NULL;
7022     if (sv_isobject(ST(0)) == 0)
7023       {
7024         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7025           PackageName);
7026         goto PerlException;
7027       }
7028     reference=SvRV(ST(0));
7029     hv=SvSTASH(reference);
7030     av=newAV();
7031     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7032     SvREFCNT_dec(av);
7033     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7034     if (image == (Image *) NULL)
7035       {
7036         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7037           PackageName);
7038         goto PerlException;
7039       }
7040     compose=image->compose;
7041     method=OptimizeLayer;
7042     for (i=2; i < items; i+=2)
7043     {
7044       attribute=(char *) SvPV(ST(i-1),na);
7045       switch (*attribute)
7046       {
7047         case 'C':
7048         case 'c':
7049         {
7050           if (LocaleCompare(attribute,"compose") == 0)
7051             {
7052               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7053                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7054               if (sp < 0)
7055                 {
7056                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7057                     SvPV(ST(i),na));
7058                   break;
7059                 }
7060               compose=(CompositeOperator) sp;
7061               break;
7062             }
7063           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7064             attribute);
7065           break;
7066         }
7067         case 'M':
7068         case 'm':
7069         {
7070           if (LocaleCompare(attribute,"method") == 0)
7071             {
7072               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7073                 SvPV(ST(i),na));
7074               if (option < 0)
7075                 {
7076                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7077                     SvPV(ST(i),na));
7078                   break;
7079                 }
7080               method=(LayerMethod) option;
7081               break;
7082             }
7083           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7084             attribute);
7085           break;
7086         }
7087         default:
7088         {
7089           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7090             attribute);
7091           break;
7092         }
7093       }
7094     }
7095     layers=(Image *) NULL;
7096     switch (method)
7097     {
7098       case CompareAnyLayer:
7099       case CompareClearLayer:
7100       case CompareOverlayLayer:
7101       default:
7102       {
7103         layers=CompareImagesLayers(image,method,exception);
7104         break;
7105       }
7106       case MergeLayer:
7107       case FlattenLayer:
7108       case MosaicLayer:
7109       {
7110         layers=MergeImageLayers(image,method,exception);
7111         break;
7112       }
7113       case DisposeLayer:
7114       {
7115         layers=DisposeImages(image,exception);
7116         break;
7117       }
7118       case OptimizeImageLayer:
7119       {
7120         layers=OptimizeImageLayers(image,exception);
7121         break;
7122       }
7123       case OptimizePlusLayer:
7124       {
7125         layers=OptimizePlusImageLayers(image,exception);
7126         break;
7127       }
7128       case OptimizeTransLayer:
7129       {
7130         OptimizeImageTransparency(image,exception);
7131         break;
7132       }
7133       case RemoveDupsLayer:
7134       {
7135         RemoveDuplicateLayers(&image,exception);
7136         break;
7137       }
7138       case RemoveZeroLayer:
7139       {
7140         RemoveZeroDelayLayers(&image,exception);
7141         break;
7142       }
7143       case OptimizeLayer:
7144       {
7145         QuantizeInfo
7146           *quantize_info;
7147
7148         /*
7149           General Purpose, GIF Animation Optimizer.
7150         */
7151         layers=CoalesceImages(image,exception);
7152         if (layers == (Image *) NULL)
7153           break;
7154         image=layers;
7155         layers=OptimizeImageLayers(image,exception);
7156         if (layers == (Image *) NULL)
7157           break;
7158         image=DestroyImageList(image);
7159         image=layers;
7160         layers=(Image *) NULL;
7161         OptimizeImageTransparency(image,exception);
7162         quantize_info=AcquireQuantizeInfo(info->image_info);
7163         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7164         quantize_info=DestroyQuantizeInfo(quantize_info);
7165         break;
7166       }
7167       case CompositeLayer:
7168       {
7169         Image
7170           *source;
7171
7172         RectangleInfo
7173           geometry;
7174
7175         /*
7176           Split image sequence at the first 'NULL:' image.
7177         */
7178         source=image;
7179         while (source != (Image *) NULL)
7180         {
7181           source=GetNextImageInList(source);
7182           if ((source != (Image *) NULL) &&
7183               (LocaleCompare(source->magick,"NULL") == 0))
7184             break;
7185         }
7186         if (source != (Image *) NULL)
7187           {
7188             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7189                 (GetNextImageInList(source) == (Image *) NULL))
7190               source=(Image *) NULL;
7191             else
7192               {
7193                 /*
7194                   Separate the two lists, junk the null: image.
7195                 */
7196                 source=SplitImageList(source->previous);
7197                 DeleteImageFromList(&source);
7198               }
7199           }
7200         if (source == (Image *) NULL)
7201           {
7202             (void) ThrowMagickException(exception,GetMagickModule(),
7203               OptionError,"MissingNullSeparator","layers Composite");
7204             break;
7205           }
7206         /*
7207           Adjust offset with gravity and virtual canvas.
7208         */
7209         SetGeometry(image,&geometry);
7210         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7211         geometry.width=source->page.width != 0 ? source->page.width :
7212           source->columns;
7213         geometry.height=source->page.height != 0 ? source->page.height :
7214           source->rows;
7215         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7216           image->columns,image->page.height != 0 ? image->page.height :
7217           image->rows,image->gravity,&geometry);
7218         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7219         source=DestroyImageList(source);
7220         break;
7221       }
7222     }
7223     if (layers != (Image *) NULL)
7224       image=layers;
7225     else
7226       image=CloneImage(image,0,0,MagickTrue,exception);
7227     if (image == (Image *) NULL)
7228       goto PerlException;
7229     for ( ; image; image=image->next)
7230     {
7231       AddImageToRegistry(sv,image);
7232       rv=newRV(sv);
7233       av_push(av,sv_bless(rv,hv));
7234       SvREFCNT_dec(sv);
7235     }
7236     exception=DestroyExceptionInfo(exception);
7237     ST(0)=av_reference;
7238     SvREFCNT_dec(perl_exception);
7239     XSRETURN(1);
7240
7241   PerlException:
7242     InheritPerlException(exception,perl_exception);
7243     exception=DestroyExceptionInfo(exception);
7244     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7245     SvPOK_on(perl_exception);
7246     ST(0)=sv_2mortal(perl_exception);
7247     XSRETURN(1);
7248   }
7249 \f
7250 #
7251 ###############################################################################
7252 #                                                                             #
7253 #                                                                             #
7254 #                                                                             #
7255 #   M a g i c k T o M i m e                                                   #
7256 #                                                                             #
7257 #                                                                             #
7258 #                                                                             #
7259 ###############################################################################
7260 #
7261 #
7262 SV *
7263 MagickToMime(ref,name)
7264   Image::Magick ref=NO_INIT
7265   char *name
7266   ALIAS:
7267     magicktomime = 1
7268   CODE:
7269   {
7270     char
7271       *mime;
7272
7273     PERL_UNUSED_VAR(ref);
7274     PERL_UNUSED_VAR(ix);
7275     mime=MagickToMime(name);
7276     RETVAL=newSVpv(mime,0);
7277     mime=(char *) RelinquishMagickMemory(mime);
7278   }
7279   OUTPUT:
7280     RETVAL
7281 \f
7282 #
7283 ###############################################################################
7284 #                                                                             #
7285 #                                                                             #
7286 #                                                                             #
7287 #   M o g r i f y                                                             #
7288 #                                                                             #
7289 #                                                                             #
7290 #                                                                             #
7291 ###############################################################################
7292 #
7293 #
7294 void
7295 Mogrify(ref,...)
7296   Image::Magick ref=NO_INIT
7297   ALIAS:
7298     Comment            =   1
7299     CommentImage       =   2
7300     Label              =   3
7301     LabelImage         =   4
7302     AddNoise           =   5
7303     AddNoiseImage      =   6
7304     Colorize           =   7
7305     ColorizeImage      =   8
7306     Border             =   9
7307     BorderImage        =  10
7308     Blur               =  11
7309     BlurImage          =  12
7310     Chop               =  13
7311     ChopImage          =  14
7312     Crop               =  15
7313     CropImage          =  16
7314     Despeckle          =  17
7315     DespeckleImage     =  18
7316     Edge               =  19
7317     EdgeImage          =  20
7318     Emboss             =  21
7319     EmbossImage        =  22
7320     Enhance            =  23
7321     EnhanceImage       =  24
7322     Flip               =  25
7323     FlipImage          =  26
7324     Flop               =  27
7325     FlopImage          =  28
7326     Frame              =  29
7327     FrameImage         =  30
7328     Implode            =  31
7329     ImplodeImage       =  32
7330     Magnify            =  33
7331     MagnifyImage       =  34
7332     MedianFilter       =  35
7333     MedianConvolveImage  =  36
7334     Minify             =  37
7335     MinifyImage        =  38
7336     OilPaint           =  39
7337     OilPaintImage      =  40
7338     ReduceNoise        =  41
7339     ReduceNoiseImage   =  42
7340     Roll               =  43
7341     RollImage          =  44
7342     Rotate             =  45
7343     RotateImage        =  46
7344     Sample             =  47
7345     SampleImage        =  48
7346     Scale              =  49
7347     ScaleImage         =  50
7348     Shade              =  51
7349     ShadeImage         =  52
7350     Sharpen            =  53
7351     SharpenImage       =  54
7352     Shear              =  55
7353     ShearImage         =  56
7354     Spread             =  57
7355     SpreadImage        =  58
7356     Swirl              =  59
7357     SwirlImage         =  60
7358     Resize             =  61
7359     ResizeImage        =  62
7360     Zoom               =  63
7361     ZoomImage          =  64
7362     Annotate           =  65
7363     AnnotateImage      =  66
7364     ColorFloodfill     =  67
7365     ColorFloodfillImage=  68
7366     Composite          =  69
7367     CompositeImage     =  70
7368     Contrast           =  71
7369     ContrastImage      =  72
7370     CycleColormap      =  73
7371     CycleColormapImage =  74
7372     Draw               =  75
7373     DrawImage          =  76
7374     Equalize           =  77
7375     EqualizeImage      =  78
7376     Gamma              =  79
7377     GammaImage         =  80
7378     Map                =  81
7379     MapImage           =  82
7380     MatteFloodfill     =  83
7381     MatteFloodfillImage=  84
7382     Modulate           =  85
7383     ModulateImage      =  86
7384     Negate             =  87
7385     NegateImage        =  88
7386     Normalize          =  89
7387     NormalizeImage     =  90
7388     NumberColors       =  91
7389     NumberColorsImage  =  92
7390     Opaque             =  93
7391     OpaqueImage        =  94
7392     Quantize           =  95
7393     QuantizeImage      =  96
7394     Raise              =  97
7395     RaiseImage         =  98
7396     Segment            =  99
7397     SegmentImage       = 100
7398     Signature          = 101
7399     SignatureImage     = 102
7400     Solarize           = 103
7401     SolarizeImage      = 104
7402     Sync               = 105
7403     SyncImage          = 106
7404     Texture            = 107
7405     TextureImage       = 108
7406     Evaluate           = 109
7407     EvaluateImage      = 110
7408     Transparent        = 111
7409     TransparentImage   = 112
7410     Threshold          = 113
7411     ThresholdImage     = 114
7412     Charcoal           = 115
7413     CharcoalImage      = 116
7414     Trim               = 117
7415     TrimImage          = 118
7416     Wave               = 119
7417     WaveImage          = 120
7418     Separate           = 121
7419     SeparateImage      = 122
7420     Stereo             = 125
7421     StereoImage        = 126
7422     Stegano            = 127
7423     SteganoImage       = 128
7424     Deconstruct        = 129
7425     DeconstructImage   = 130
7426     GaussianBlur       = 131
7427     GaussianBlurImage  = 132
7428     Convolve           = 133
7429     ConvolveImage      = 134
7430     Profile            = 135
7431     ProfileImage       = 136
7432     UnsharpMask        = 137
7433     UnsharpMaskImage   = 138
7434     MotionBlur         = 139
7435     MotionBlurImage    = 140
7436     OrderedDither      = 141
7437     OrderedDitherImage = 142
7438     Shave              = 143
7439     ShaveImage         = 144
7440     Level              = 145
7441     LevelImage         = 146
7442     Clip               = 147
7443     ClipImage          = 148
7444     AffineTransform    = 149
7445     AffineTransformImage = 150
7446     Difference         = 151
7447     DifferenceImage    = 152
7448     AdaptiveThreshold  = 153
7449     AdaptiveThresholdImage = 154
7450     Resample           = 155
7451     ResampleImage      = 156
7452     Describe           = 157
7453     DescribeImage      = 158
7454     BlackThreshold     = 159
7455     BlackThresholdImage= 160
7456     WhiteThreshold     = 161
7457     WhiteThresholdImage= 162
7458     RotationalBlur     = 163
7459     RotationalBlurImage= 164
7460     Thumbnail          = 165
7461     ThumbnailImage     = 166
7462     Strip              = 167
7463     StripImage         = 168
7464     Tint               = 169
7465     TintImage          = 170
7466     Channel            = 171
7467     ChannelImage       = 172
7468     Splice             = 173
7469     SpliceImage        = 174
7470     Posterize          = 175
7471     PosterizeImage     = 176
7472     Shadow             = 177
7473     ShadowImage        = 178
7474     Identify           = 179
7475     IdentifyImage      = 180
7476     SepiaTone          = 181
7477     SepiaToneImage     = 182
7478     SigmoidalContrast  = 183
7479     SigmoidalContrastImage = 184
7480     Extent             = 185
7481     ExtentImage        = 186
7482     Vignette           = 187
7483     VignetteImage      = 188
7484     ContrastStretch    = 189
7485     ContrastStretchImage = 190
7486     Sans0              = 191
7487     Sans0Image         = 192
7488     Sans1              = 193
7489     Sans1Image         = 194
7490     AdaptiveSharpen    = 195
7491     AdaptiveSharpenImage = 196
7492     Transpose          = 197
7493     TransposeImage     = 198
7494     Transverse         = 199
7495     TransverseImage    = 200
7496     AutoOrient         = 201
7497     AutoOrientImage    = 202
7498     AdaptiveBlur       = 203
7499     AdaptiveBlurImage  = 204
7500     Sketch             = 205
7501     SketchImage        = 206
7502     UniqueColors       = 207
7503     UniqueColorsImage  = 208
7504     AdaptiveResize     = 209
7505     AdaptiveResizeImage= 210
7506     ClipMask           = 211
7507     ClipMaskImage      = 212
7508     LinearStretch      = 213
7509     LinearStretchImage = 214
7510     ColorMatrix        = 215
7511     ColorMatrixImage   = 216
7512     Mask               = 217
7513     MaskImage          = 218
7514     Polaroid           = 219
7515     PolaroidImage      = 220
7516     FloodfillPaint     = 221
7517     FloodfillPaintImage= 222
7518     Distort            = 223
7519     DistortImage       = 224
7520     Clut               = 225
7521     ClutImage          = 226
7522     LiquidRescale      = 227
7523     LiquidRescaleImage = 228
7524     Encipher           = 229
7525     EncipherImage      = 230
7526     Decipher           = 231
7527     DecipherImage      = 232
7528     Deskew             = 233
7529     DeskewImage        = 234
7530     Remap              = 235
7531     RemapImage         = 236
7532     SparseColor        = 237
7533     SparseColorImage   = 238
7534     Function           = 239
7535     FunctionImage      = 240
7536     SelectiveBlur      = 241
7537     SelectiveBlurImage = 242
7538     HaldClut           = 243
7539     HaldClutImage      = 244
7540     BlueShift          = 245
7541     BlueShiftImage     = 246
7542     ForwardFourierTransform  = 247
7543     ForwardFourierTransformImage = 248
7544     InverseFourierTransform = 249
7545     InverseFourierTransformImage = 250
7546     ColorDecisionList  = 251
7547     ColorDecisionListImage = 252
7548     AutoGamma          = 253
7549     AutoGammaImage     = 254
7550     AutoLevel          = 255
7551     AutoLevelImage     = 256
7552     LevelColors        = 257
7553     LevelImageColors   = 258
7554     Clamp              = 259
7555     ClampImage         = 260
7556     BrightnessContrast = 261
7557     BrightnessContrastImage = 262
7558     Morphology         = 263
7559     MorphologyImage    = 264
7560     Color              = 265
7561     ColorImage         = 266
7562     Mode               = 267
7563     ModeImage          = 268
7564     Statistic          = 269
7565     StatisticImage     = 270
7566     Perceptible        = 271
7567     PerceptibleImage   = 272
7568     Poly               = 273
7569     PolyImage          = 274
7570     Grayscale          = 275
7571     GrayscaleImage     = 276
7572     CannyEdge          = 278
7573     CannyEdgeImage     = 279
7574     HoughLine          = 280
7575     HoughLineImage     = 281
7576     MeanShift          = 282
7577     MeanShiftImage     = 283
7578     Kuwahara           = 284
7579     KuwaharaImage      = 285
7580     ConnectedComponent = 286
7581     ConnectedComponentImage = 287
7582     CopyPixels         = 288
7583     CopyImagePixels    = 289
7584     MogrifyRegion      = 666
7585   PPCODE:
7586   {
7587     AffineMatrix
7588       affine,
7589       current;
7590
7591     char
7592       attribute_flag[MaxArguments],
7593       message[MagickPathExtent];
7594
7595     ChannelType
7596       channel,
7597       channel_mask;
7598
7599     CompositeOperator
7600       compose;
7601
7602     const char
7603       *attribute,
7604       *value;
7605
7606     double
7607       angle;
7608
7609     ExceptionInfo
7610       *exception;
7611
7612     GeometryInfo
7613       geometry_info;
7614
7615     Image
7616       *image,
7617       *next,
7618       *region_image;
7619
7620     MagickBooleanType
7621       status;
7622
7623     MagickStatusType
7624       flags;
7625
7626     PixelInfo
7627       fill_color;
7628
7629     RectangleInfo
7630       geometry,
7631       region_info;
7632
7633     register ssize_t
7634       i;
7635
7636     ssize_t
7637       base,
7638       j,
7639       number_images;
7640
7641     struct Methods
7642       *rp;
7643
7644     struct PackageInfo
7645       *info;
7646
7647     SV
7648       *perl_exception,
7649       **pv,
7650       *reference,
7651       **reference_vector;
7652
7653     struct ArgumentList
7654       argument_list[MaxArguments];
7655
7656     PERL_UNUSED_VAR(ref);
7657     PERL_UNUSED_VAR(ix);
7658     exception=AcquireExceptionInfo();
7659     perl_exception=newSVpv("",0);
7660     reference_vector=NULL;
7661     region_image=NULL;
7662     number_images=0;
7663     base=2;
7664     if (sv_isobject(ST(0)) == 0)
7665       {
7666         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7667           PackageName);
7668         goto PerlException;
7669       }
7670     reference=SvRV(ST(0));
7671     region_info.width=0;
7672     region_info.height=0;
7673     region_info.x=0;
7674     region_info.y=0;
7675     region_image=(Image *) NULL;
7676     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7677     if (ix && (ix != 666))
7678       {
7679         /*
7680           Called as Method(...)
7681         */
7682         ix=(ix+1)/2;
7683         rp=(&Methods[ix-1]);
7684         attribute=rp->name;
7685       }
7686     else
7687       {
7688         /*
7689           Called as Mogrify("Method",...)
7690         */
7691         attribute=(char *) SvPV(ST(1),na);
7692         if (ix)
7693           {
7694             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7695             attribute=(char *) SvPV(ST(2),na);
7696             base++;
7697           }
7698         for (rp=Methods; ; rp++)
7699         {
7700           if (rp >= EndOf(Methods))
7701             {
7702               ThrowPerlException(exception,OptionError,
7703                 "UnrecognizedPerlMagickMethod",attribute);
7704               goto PerlException;
7705             }
7706           if (strEQcase(attribute,rp->name))
7707             break;
7708         }
7709         ix=rp-Methods+1;
7710         base++;
7711       }
7712     if (image == (Image *) NULL)
7713       {
7714         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7715         goto PerlException;
7716       }
7717     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7718     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7719     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7720     {
7721       Arguments
7722         *pp,
7723         *qq;
7724
7725       ssize_t
7726         ssize_test;
7727
7728       struct ArgumentList
7729         *al;
7730
7731       SV
7732         *sv;
7733
7734       sv=NULL;
7735       ssize_test=0;
7736       pp=(Arguments *) NULL;
7737       qq=rp->arguments;
7738       if (i == items)
7739         {
7740           pp=rp->arguments,
7741           sv=ST(i-1);
7742         }
7743       else
7744         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7745         {
7746           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7747             break;
7748           if (strEQcase(attribute,qq->method) > ssize_test)
7749             {
7750               pp=qq;
7751               ssize_test=strEQcase(attribute,qq->method);
7752             }
7753         }
7754       if (pp == (Arguments *) NULL)
7755         {
7756           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7757             attribute);
7758           goto continue_outer_loop;
7759         }
7760       al=(&argument_list[pp-rp->arguments]);
7761       switch (pp->type)
7762       {
7763         case ArrayReference:
7764         {
7765           if (SvTYPE(sv) != SVt_RV)
7766             {
7767               (void) FormatLocaleString(message,MagickPathExtent,
7768                 "invalid %.60s value",pp->method);
7769               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7770               goto continue_outer_loop;
7771             }
7772           al->array_reference=SvRV(sv);
7773           break;
7774         }
7775         case RealReference:
7776         {
7777           al->real_reference=SvNV(sv);
7778           break;
7779         }
7780         case FileReference:
7781         {
7782           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7783           break;
7784         }
7785         case ImageReference:
7786         {
7787           if (!sv_isobject(sv) ||
7788               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7789                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7790             {
7791               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7792                 PackageName);
7793               goto PerlException;
7794             }
7795           break;
7796         }
7797         case IntegerReference:
7798         {
7799           al->integer_reference=SvIV(sv);
7800           break;
7801         }
7802         case StringReference:
7803         {
7804           al->string_reference=(char *) SvPV(sv,al->length);
7805           if (sv_isobject(sv))
7806             al->image_reference=SetupList(aTHX_ SvRV(sv),
7807               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7808           break;
7809         }
7810         default:
7811         {
7812           /*
7813             Is a string; look up name.
7814           */
7815           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7816             {
7817               al->string_reference=(char *) SvPV(sv,al->length);
7818               al->integer_reference=(-1);
7819               break;
7820             }
7821           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7822             MagickFalse,SvPV(sv,na));
7823           if (pp->type == MagickChannelOptions)
7824             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7825           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7826             {
7827               (void) FormatLocaleString(message,MagickPathExtent,
7828                 "invalid %.60s value",pp->method);
7829               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7830               goto continue_outer_loop;
7831             }
7832           break;
7833         }
7834       }
7835       attribute_flag[pp-rp->arguments]++;
7836       continue_outer_loop: ;
7837     }
7838     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7839     pv=reference_vector;
7840     SetGeometryInfo(&geometry_info);
7841     channel=DefaultChannels;
7842     for (next=image; next; next=next->next)
7843     {
7844       image=next;
7845       SetGeometry(image,&geometry);
7846       if ((region_info.width*region_info.height) != 0)
7847         {
7848           region_image=image;
7849           image=CropImage(image,&region_info,exception);
7850         }
7851       switch (ix)
7852       {
7853         default:
7854         {
7855           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7856           ThrowPerlException(exception,OptionError,
7857             "UnrecognizedPerlMagickMethod",message);
7858           goto PerlException;
7859         }
7860         case 1:  /* Comment */
7861         {
7862           if (attribute_flag[0] == 0)
7863             argument_list[0].string_reference=(char *) NULL;
7864           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7865             info ? info->image_info : (ImageInfo *) NULL,image,
7866             argument_list[0].string_reference,exception),exception);
7867           break;
7868         }
7869         case 2:  /* Label */
7870         {
7871           if (attribute_flag[0] == 0)
7872             argument_list[0].string_reference=(char *) NULL;
7873           (void) SetImageProperty(image,"label",InterpretImageProperties(
7874             info ? info->image_info : (ImageInfo *) NULL,image,
7875             argument_list[0].string_reference,exception),exception);
7876           break;
7877         }
7878         case 3:  /* AddNoise */
7879         {
7880           double
7881             attenuate;
7882
7883           if (attribute_flag[0] == 0)
7884             argument_list[0].integer_reference=UniformNoise;
7885           attenuate=1.0;
7886           if (attribute_flag[1] != 0)
7887             attenuate=argument_list[1].real_reference;
7888           if (attribute_flag[2] != 0)
7889             channel=(ChannelType) argument_list[2].integer_reference;
7890           channel_mask=SetImageChannelMask(image,channel);
7891           image=AddNoiseImage(image,(NoiseType)
7892             argument_list[0].integer_reference,attenuate,exception);
7893           if (image != (Image *) NULL)
7894             (void) SetImageChannelMask(image,channel_mask);
7895           break;
7896         }
7897         case 4:  /* Colorize */
7898         {
7899           PixelInfo
7900             target;
7901
7902           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7903             0,0,&target,exception);
7904           if (attribute_flag[0] != 0)
7905             (void) QueryColorCompliance(argument_list[0].string_reference,
7906               AllCompliance,&target,exception);
7907           if (attribute_flag[1] == 0)
7908             argument_list[1].string_reference="100%";
7909           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7910             exception);
7911           break;
7912         }
7913         case 5:  /* Border */
7914         {
7915           CompositeOperator
7916             compose;
7917
7918           geometry.width=0;
7919           geometry.height=0;
7920           if (attribute_flag[0] != 0)
7921             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7922               &geometry,exception);
7923           if (attribute_flag[1] != 0)
7924             geometry.width=argument_list[1].integer_reference;
7925           if (attribute_flag[2] != 0)
7926             geometry.height=argument_list[2].integer_reference;
7927           if (attribute_flag[3] != 0)
7928             QueryColorCompliance(argument_list[3].string_reference,
7929               AllCompliance,&image->border_color,exception);
7930           if (attribute_flag[4] != 0)
7931             QueryColorCompliance(argument_list[4].string_reference,
7932               AllCompliance,&image->border_color,exception);
7933           if (attribute_flag[5] != 0)
7934             QueryColorCompliance(argument_list[5].string_reference,
7935               AllCompliance,&image->border_color,exception);
7936           compose=image->compose;
7937           if (attribute_flag[6] != 0)
7938             compose=(CompositeOperator) argument_list[6].integer_reference;
7939           image=BorderImage(image,&geometry,compose,exception);
7940           break;
7941         }
7942         case 6:  /* Blur */
7943         {
7944           if (attribute_flag[0] != 0)
7945             {
7946               flags=ParseGeometry(argument_list[0].string_reference,
7947                 &geometry_info);
7948               if ((flags & SigmaValue) == 0)
7949                 geometry_info.sigma=1.0;
7950             }
7951           if (attribute_flag[1] != 0)
7952             geometry_info.rho=argument_list[1].real_reference;
7953           if (attribute_flag[2] != 0)
7954             geometry_info.sigma=argument_list[2].real_reference;
7955           if (attribute_flag[3] != 0)
7956             channel=(ChannelType) argument_list[3].integer_reference;
7957           channel_mask=SetImageChannelMask(image,channel);
7958           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7959             exception);
7960           if (image != (Image *) NULL)
7961             (void) SetImageChannelMask(image,channel_mask);
7962           break;
7963         }
7964         case 7:  /* Chop */
7965         {
7966           if (attribute_flag[5] != 0)
7967             image->gravity=(GravityType) argument_list[5].integer_reference;
7968           if (attribute_flag[0] != 0)
7969             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7970               &geometry,exception);
7971           if (attribute_flag[1] != 0)
7972             geometry.width=argument_list[1].integer_reference;
7973           if (attribute_flag[2] != 0)
7974             geometry.height=argument_list[2].integer_reference;
7975           if (attribute_flag[3] != 0)
7976             geometry.x=argument_list[3].integer_reference;
7977           if (attribute_flag[4] != 0)
7978             geometry.y=argument_list[4].integer_reference;
7979           image=ChopImage(image,&geometry,exception);
7980           break;
7981         }
7982         case 8:  /* Crop */
7983         {
7984           if (attribute_flag[6] != 0)
7985             image->gravity=(GravityType) argument_list[6].integer_reference;
7986           if (attribute_flag[0] != 0)
7987             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7988               &geometry,exception);
7989           if (attribute_flag[1] != 0)
7990             geometry.width=argument_list[1].integer_reference;
7991           if (attribute_flag[2] != 0)
7992             geometry.height=argument_list[2].integer_reference;
7993           if (attribute_flag[3] != 0)
7994             geometry.x=argument_list[3].integer_reference;
7995           if (attribute_flag[4] != 0)
7996             geometry.y=argument_list[4].integer_reference;
7997           if (attribute_flag[5] != 0)
7998             image->fuzz=StringToDoubleInterval(
7999               argument_list[5].string_reference,(double) QuantumRange+1.0);
8000           image=CropImage(image,&geometry,exception);
8001           break;
8002         }
8003         case 9:  /* Despeckle */
8004         {
8005           image=DespeckleImage(image,exception);
8006           break;
8007         }
8008         case 10:  /* Edge */
8009         {
8010           if (attribute_flag[0] != 0)
8011             geometry_info.rho=argument_list[0].real_reference;
8012           image=EdgeImage(image,geometry_info.rho,exception);
8013           break;
8014         }
8015         case 11:  /* Emboss */
8016         {
8017           if (attribute_flag[0] != 0)
8018             {
8019               flags=ParseGeometry(argument_list[0].string_reference,
8020                 &geometry_info);
8021               if ((flags & SigmaValue) == 0)
8022                 geometry_info.sigma=1.0;
8023             }
8024           if (attribute_flag[1] != 0)
8025             geometry_info.rho=argument_list[1].real_reference;
8026           if (attribute_flag[2] != 0)
8027             geometry_info.sigma=argument_list[2].real_reference;
8028           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8029             exception);
8030           break;
8031         }
8032         case 12:  /* Enhance */
8033         {
8034           image=EnhanceImage(image,exception);
8035           break;
8036         }
8037         case 13:  /* Flip */
8038         {
8039           image=FlipImage(image,exception);
8040           break;
8041         }
8042         case 14:  /* Flop */
8043         {
8044           image=FlopImage(image,exception);
8045           break;
8046         }
8047         case 15:  /* Frame */
8048         {
8049           CompositeOperator
8050             compose;
8051
8052           FrameInfo
8053             frame_info;
8054
8055           if (attribute_flag[0] != 0)
8056             {
8057               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8058                 &geometry,exception);
8059               frame_info.width=geometry.width;
8060               frame_info.height=geometry.height;
8061               frame_info.outer_bevel=geometry.x;
8062               frame_info.inner_bevel=geometry.y;
8063             }
8064           if (attribute_flag[1] != 0)
8065             frame_info.width=argument_list[1].integer_reference;
8066           if (attribute_flag[2] != 0)
8067             frame_info.height=argument_list[2].integer_reference;
8068           if (attribute_flag[3] != 0)
8069             frame_info.inner_bevel=argument_list[3].integer_reference;
8070           if (attribute_flag[4] != 0)
8071             frame_info.outer_bevel=argument_list[4].integer_reference;
8072           if (attribute_flag[5] != 0)
8073             QueryColorCompliance(argument_list[5].string_reference,
8074               AllCompliance,&fill_color,exception);
8075           if (attribute_flag[6] != 0)
8076             QueryColorCompliance(argument_list[6].string_reference,
8077               AllCompliance,&fill_color,exception);
8078           frame_info.x=(ssize_t) frame_info.width;
8079           frame_info.y=(ssize_t) frame_info.height;
8080           frame_info.width=image->columns+2*frame_info.x;
8081           frame_info.height=image->rows+2*frame_info.y;
8082           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8083             image->matte_color=fill_color;
8084           compose=image->compose;
8085           if (attribute_flag[7] != 0)
8086             compose=(CompositeOperator) argument_list[7].integer_reference;
8087           image=FrameImage(image,&frame_info,compose,exception);
8088           break;
8089         }
8090         case 16:  /* Implode */
8091         {
8092           PixelInterpolateMethod
8093             method;
8094
8095           if (attribute_flag[0] == 0)
8096             argument_list[0].real_reference=0.5;
8097           method=UndefinedInterpolatePixel;
8098           if (attribute_flag[1] != 0)
8099             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8100           image=ImplodeImage(image,argument_list[0].real_reference,
8101             method,exception);
8102           break;
8103         }
8104         case 17:  /* Magnify */
8105         {
8106           image=MagnifyImage(image,exception);
8107           break;
8108         }
8109         case 18:  /* MedianFilter */
8110         {
8111           if (attribute_flag[0] != 0)
8112             {
8113               flags=ParseGeometry(argument_list[0].string_reference,
8114                 &geometry_info);
8115               if ((flags & SigmaValue) == 0)
8116                 geometry_info.sigma=geometry_info.rho;
8117             }
8118           if (attribute_flag[1] != 0)
8119             geometry_info.rho=argument_list[1].real_reference;
8120           if (attribute_flag[2] != 0)
8121             geometry_info.sigma=argument_list[2].real_reference;
8122           if (attribute_flag[3] != 0)
8123             channel=(ChannelType) argument_list[3].integer_reference;
8124           channel_mask=SetImageChannelMask(image,channel);
8125           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8126             (size_t) geometry_info.sigma,exception);
8127           if (image != (Image *) NULL)
8128             (void) SetImageChannelMask(image,channel_mask);
8129           break;
8130         }
8131         case 19:  /* Minify */
8132         {
8133           image=MinifyImage(image,exception);
8134           break;
8135         }
8136         case 20:  /* OilPaint */
8137         {
8138           if (attribute_flag[0] == 0)
8139             argument_list[0].real_reference=0.0;
8140           if (attribute_flag[1] == 0)
8141             argument_list[1].real_reference=1.0;
8142           image=OilPaintImage(image,argument_list[0].real_reference,
8143             argument_list[1].real_reference,exception);
8144           break;
8145         }
8146         case 21:  /* ReduceNoise */
8147         {
8148           if (attribute_flag[0] != 0)
8149             {
8150               flags=ParseGeometry(argument_list[0].string_reference,
8151                 &geometry_info);
8152               if ((flags & SigmaValue) == 0)
8153                 geometry_info.sigma=1.0;
8154             }
8155           if (attribute_flag[1] != 0)
8156             geometry_info.rho=argument_list[1].real_reference;
8157           if (attribute_flag[2] != 0)
8158             geometry_info.sigma=argument_list[2].real_reference;
8159           if (attribute_flag[3] != 0)
8160             channel=(ChannelType) argument_list[3].integer_reference;
8161           channel_mask=SetImageChannelMask(image,channel);
8162           image=StatisticImage(image,NonpeakStatistic,(size_t)
8163             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8164           if (image != (Image *) NULL)
8165             (void) SetImageChannelMask(image,channel_mask);
8166           break;
8167         }
8168         case 22:  /* Roll */
8169         {
8170           if (attribute_flag[0] != 0)
8171             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8172               &geometry,exception);
8173           if (attribute_flag[1] != 0)
8174             geometry.x=argument_list[1].integer_reference;
8175           if (attribute_flag[2] != 0)
8176             geometry.y=argument_list[2].integer_reference;
8177           image=RollImage(image,geometry.x,geometry.y,exception);
8178           break;
8179         }
8180         case 23:  /* Rotate */
8181         {
8182           if (attribute_flag[0] == 0)
8183             argument_list[0].real_reference=90.0;
8184           if (attribute_flag[1] != 0)
8185             {
8186               QueryColorCompliance(argument_list[1].string_reference,
8187                 AllCompliance,&image->background_color,exception);
8188               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8189                   (image->alpha_trait == UndefinedPixelTrait))
8190                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8191             }
8192           image=RotateImage(image,argument_list[0].real_reference,exception);
8193           break;
8194         }
8195         case 24:  /* Sample */
8196         {
8197           if (attribute_flag[0] != 0)
8198             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8199               &geometry,exception);
8200           if (attribute_flag[1] != 0)
8201             geometry.width=argument_list[1].integer_reference;
8202           if (attribute_flag[2] != 0)
8203             geometry.height=argument_list[2].integer_reference;
8204           image=SampleImage(image,geometry.width,geometry.height,exception);
8205           break;
8206         }
8207         case 25:  /* Scale */
8208         {
8209           if (attribute_flag[0] != 0)
8210             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8211               &geometry,exception);
8212           if (attribute_flag[1] != 0)
8213             geometry.width=argument_list[1].integer_reference;
8214           if (attribute_flag[2] != 0)
8215             geometry.height=argument_list[2].integer_reference;
8216           image=ScaleImage(image,geometry.width,geometry.height,exception);
8217           break;
8218         }
8219         case 26:  /* Shade */
8220         {
8221           if (attribute_flag[0] != 0)
8222             {
8223               flags=ParseGeometry(argument_list[0].string_reference,
8224                 &geometry_info);
8225               if ((flags & SigmaValue) == 0)
8226                 geometry_info.sigma=0.0;
8227             }
8228           if (attribute_flag[1] != 0)
8229             geometry_info.rho=argument_list[1].real_reference;
8230           if (attribute_flag[2] != 0)
8231             geometry_info.sigma=argument_list[2].real_reference;
8232           image=ShadeImage(image,
8233             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8234             geometry_info.rho,geometry_info.sigma,exception);
8235           break;
8236         }
8237         case 27:  /* Sharpen */
8238         {
8239           if (attribute_flag[0] != 0)
8240             {
8241               flags=ParseGeometry(argument_list[0].string_reference,
8242                 &geometry_info);
8243               if ((flags & SigmaValue) == 0)
8244                 geometry_info.sigma=1.0;
8245             }
8246           if (attribute_flag[1] != 0)
8247             geometry_info.rho=argument_list[1].real_reference;
8248           if (attribute_flag[2] != 0)
8249             geometry_info.sigma=argument_list[2].real_reference;
8250           if (attribute_flag[3] != 0)
8251             channel=(ChannelType) argument_list[3].integer_reference;
8252           channel_mask=SetImageChannelMask(image,channel);
8253           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8254             exception);
8255           if (image != (Image *) NULL)
8256             (void) SetImageChannelMask(image,channel_mask);
8257           break;
8258         }
8259         case 28:  /* Shear */
8260         {
8261           if (attribute_flag[0] != 0)
8262             {
8263               flags=ParseGeometry(argument_list[0].string_reference,
8264                 &geometry_info);
8265               if ((flags & SigmaValue) == 0)
8266                 geometry_info.sigma=geometry_info.rho;
8267             }
8268           if (attribute_flag[1] != 0)
8269             geometry_info.rho=argument_list[1].real_reference;
8270           if (attribute_flag[2] != 0)
8271             geometry_info.sigma=argument_list[2].real_reference;
8272           if (attribute_flag[3] != 0)
8273             QueryColorCompliance(argument_list[3].string_reference,
8274               AllCompliance,&image->background_color,exception);
8275           if (attribute_flag[4] != 0)
8276             QueryColorCompliance(argument_list[4].string_reference,
8277               AllCompliance,&image->background_color,exception);
8278           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8279             exception);
8280           break;
8281         }
8282         case 29:  /* Spread */
8283         {
8284           PixelInterpolateMethod
8285             method;
8286
8287           if (attribute_flag[0] == 0)
8288             argument_list[0].real_reference=1.0;
8289           method=UndefinedInterpolatePixel;
8290           if (attribute_flag[1] != 0)
8291             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8292           image=SpreadImage(image,method,argument_list[0].real_reference,
8293             exception);
8294           break;
8295         }
8296         case 30:  /* Swirl */
8297         {
8298           PixelInterpolateMethod
8299             method;
8300
8301           if (attribute_flag[0] == 0)
8302             argument_list[0].real_reference=50.0;
8303           method=UndefinedInterpolatePixel;
8304           if (attribute_flag[1] != 0)
8305             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8306           image=SwirlImage(image,argument_list[0].real_reference,
8307             method,exception);
8308           break;
8309         }
8310         case 31:  /* Resize */
8311         case 32:  /* Zoom */
8312         {
8313           if (attribute_flag[0] != 0)
8314             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8315               &geometry,exception);
8316           if (attribute_flag[1] != 0)
8317             geometry.width=argument_list[1].integer_reference;
8318           if (attribute_flag[2] != 0)
8319             geometry.height=argument_list[2].integer_reference;
8320           if (attribute_flag[3] == 0)
8321             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8322           if (attribute_flag[4] != 0)
8323             SetImageArtifact(image,"filter:support",
8324               argument_list[4].string_reference);
8325           image=ResizeImage(image,geometry.width,geometry.height,
8326             (FilterTypes) argument_list[3].integer_reference,
8327             exception);
8328           break;
8329         }
8330         case 33:  /* Annotate */
8331         {
8332           DrawInfo
8333             *draw_info;
8334
8335           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8336             (DrawInfo *) NULL);
8337           if (attribute_flag[0] != 0)
8338             {
8339               char
8340                 *text;
8341
8342               text=InterpretImageProperties(info ? info->image_info :
8343                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8344                 exception);
8345               (void) CloneString(&draw_info->text,text);
8346               text=DestroyString(text);
8347             }
8348           if (attribute_flag[1] != 0)
8349             (void) CloneString(&draw_info->font,
8350               argument_list[1].string_reference);
8351           if (attribute_flag[2] != 0)
8352             draw_info->pointsize=argument_list[2].real_reference;
8353           if (attribute_flag[3] != 0)
8354             (void) CloneString(&draw_info->density,
8355               argument_list[3].string_reference);
8356           if (attribute_flag[4] != 0)
8357             (void) QueryColorCompliance(argument_list[4].string_reference,
8358               AllCompliance,&draw_info->undercolor,exception);
8359           if (attribute_flag[5] != 0)
8360             {
8361               (void) QueryColorCompliance(argument_list[5].string_reference,
8362                 AllCompliance,&draw_info->stroke,exception);
8363               if (argument_list[5].image_reference != (Image *) NULL)
8364                 draw_info->stroke_pattern=CloneImage(
8365                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8366             }
8367           if (attribute_flag[6] != 0)
8368             {
8369               (void) QueryColorCompliance(argument_list[6].string_reference,
8370                 AllCompliance,&draw_info->fill,exception);
8371               if (argument_list[6].image_reference != (Image *) NULL)
8372                 draw_info->fill_pattern=CloneImage(
8373                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8374             }
8375           if (attribute_flag[7] != 0)
8376             {
8377               (void) CloneString(&draw_info->geometry,
8378                 argument_list[7].string_reference);
8379               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8380                 &geometry,exception);
8381               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8382                 geometry_info.sigma=geometry_info.xi;
8383             }
8384           if (attribute_flag[8] != 0)
8385             (void) QueryColorCompliance(argument_list[8].string_reference,
8386               AllCompliance,&draw_info->fill,exception);
8387           if (attribute_flag[11] != 0)
8388             draw_info->gravity=(GravityType)
8389               argument_list[11].integer_reference;
8390           if (attribute_flag[25] != 0)
8391             {
8392               AV
8393                 *av;
8394
8395               av=(AV *) argument_list[25].array_reference;
8396               if ((av_len(av) != 3) && (av_len(av) != 5))
8397                 {
8398                   ThrowPerlException(exception,OptionError,
8399                     "affine matrix must have 4 or 6 elements",PackageName);
8400                   goto PerlException;
8401                 }
8402               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8403               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8404               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8405               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8406               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8407                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8408                 {
8409                   ThrowPerlException(exception,OptionError,
8410                     "affine matrix is singular",PackageName);
8411                    goto PerlException;
8412                 }
8413               if (av_len(av) == 5)
8414                 {
8415                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8416                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8417                 }
8418             }
8419           for (j=12; j < 17; j++)
8420           {
8421             if (attribute_flag[j] == 0)
8422               continue;
8423             value=argument_list[j].string_reference;
8424             angle=argument_list[j].real_reference;
8425             current=draw_info->affine;
8426             GetAffineMatrix(&affine);
8427             switch (j)
8428             {
8429               case 12:
8430               {
8431                 /*
8432                   Translate.
8433                 */
8434                 flags=ParseGeometry(value,&geometry_info);
8435                 affine.tx=geometry_info.xi;
8436                 affine.ty=geometry_info.psi;
8437                 if ((flags & PsiValue) == 0)
8438                   affine.ty=affine.tx;
8439                 break;
8440               }
8441               case 13:
8442               {
8443                 /*
8444                   Scale.
8445                 */
8446                 flags=ParseGeometry(value,&geometry_info);
8447                 affine.sx=geometry_info.rho;
8448                 affine.sy=geometry_info.sigma;
8449                 if ((flags & SigmaValue) == 0)
8450                   affine.sy=affine.sx;
8451                 break;
8452               }
8453               case 14:
8454               {
8455                 /*
8456                   Rotate.
8457                 */
8458                 if (angle == 0.0)
8459                   break;
8460                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8461                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8462                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8463                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8464                 break;
8465               }
8466               case 15:
8467               {
8468                 /*
8469                   SkewX.
8470                 */
8471                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8472                 break;
8473               }
8474               case 16:
8475               {
8476                 /*
8477                   SkewY.
8478                 */
8479                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8480                 break;
8481               }
8482             }
8483             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8484             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8485             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8486             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8487             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8488               current.tx;
8489             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8490               current.ty;
8491           }
8492           if (attribute_flag[9] == 0)
8493             argument_list[9].real_reference=0.0;
8494           if (attribute_flag[10] == 0)
8495             argument_list[10].real_reference=0.0;
8496           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8497             {
8498               char
8499                 geometry[MagickPathExtent];
8500
8501               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8502                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8503                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8504               (void) CloneString(&draw_info->geometry,geometry);
8505             }
8506           if (attribute_flag[17] != 0)
8507             draw_info->stroke_width=argument_list[17].real_reference;
8508           if (attribute_flag[18] != 0)
8509             {
8510               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8511                 MagickTrue : MagickFalse;
8512               draw_info->stroke_antialias=draw_info->text_antialias;
8513             }
8514           if (attribute_flag[19] != 0)
8515             (void) CloneString(&draw_info->family,
8516               argument_list[19].string_reference);
8517           if (attribute_flag[20] != 0)
8518             draw_info->style=(StyleType) argument_list[20].integer_reference;
8519           if (attribute_flag[21] != 0)
8520             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8521           if (attribute_flag[22] != 0)
8522             draw_info->weight=argument_list[22].integer_reference;
8523           if (attribute_flag[23] != 0)
8524             draw_info->align=(AlignType) argument_list[23].integer_reference;
8525           if (attribute_flag[24] != 0)
8526             (void) CloneString(&draw_info->encoding,
8527               argument_list[24].string_reference);
8528           if (attribute_flag[25] != 0)
8529             draw_info->fill_pattern=CloneImage(
8530               argument_list[25].image_reference,0,0,MagickTrue,exception);
8531           if (attribute_flag[26] != 0)
8532             draw_info->fill_pattern=CloneImage(
8533               argument_list[26].image_reference,0,0,MagickTrue,exception);
8534           if (attribute_flag[27] != 0)
8535             draw_info->stroke_pattern=CloneImage(
8536               argument_list[27].image_reference,0,0,MagickTrue,exception);
8537           if (attribute_flag[29] != 0)
8538             draw_info->kerning=argument_list[29].real_reference;
8539           if (attribute_flag[30] != 0)
8540             draw_info->interline_spacing=argument_list[30].real_reference;
8541           if (attribute_flag[31] != 0)
8542             draw_info->interword_spacing=argument_list[31].real_reference;
8543           if (attribute_flag[32] != 0)
8544             draw_info->direction=(DirectionType)
8545               argument_list[32].integer_reference;
8546           (void) AnnotateImage(image,draw_info,exception);
8547           draw_info=DestroyDrawInfo(draw_info);
8548           break;
8549         }
8550         case 34:  /* ColorFloodfill */
8551         {
8552           DrawInfo
8553             *draw_info;
8554
8555           MagickBooleanType
8556             invert;
8557
8558           PixelInfo
8559             target;
8560
8561           draw_info=CloneDrawInfo(info ? info->image_info :
8562             (ImageInfo *) NULL,(DrawInfo *) NULL);
8563           if (attribute_flag[0] != 0)
8564             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8565               &geometry,exception);
8566           if (attribute_flag[1] != 0)
8567             geometry.x=argument_list[1].integer_reference;
8568           if (attribute_flag[2] != 0)
8569             geometry.y=argument_list[2].integer_reference;
8570           if (attribute_flag[3] != 0)
8571             (void) QueryColorCompliance(argument_list[3].string_reference,
8572               AllCompliance,&draw_info->fill,exception);
8573           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8574             geometry.x,geometry.y,&target,exception);
8575           invert=MagickFalse;
8576           if (attribute_flag[4] != 0)
8577             {
8578               QueryColorCompliance(argument_list[4].string_reference,
8579                 AllCompliance,&target,exception);
8580               invert=MagickTrue;
8581             }
8582           if (attribute_flag[5] != 0)
8583             image->fuzz=StringToDoubleInterval(
8584               argument_list[5].string_reference,(double) QuantumRange+1.0);
8585           if (attribute_flag[6] != 0)
8586             invert=(MagickBooleanType) argument_list[6].integer_reference;
8587           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8588             geometry.y,invert,exception);
8589           draw_info=DestroyDrawInfo(draw_info);
8590           break;
8591         }
8592         case 35:  /* Composite */
8593         {
8594           char
8595             composite_geometry[MagickPathExtent];
8596
8597           Image
8598             *composite_image,
8599             *rotate_image;
8600
8601           MagickBooleanType
8602             clip_to_self;
8603
8604           compose=OverCompositeOp;
8605           if (attribute_flag[0] != 0)
8606             composite_image=argument_list[0].image_reference;
8607           else
8608             {
8609               ThrowPerlException(exception,OptionError,
8610                 "CompositeImageRequired",PackageName);
8611               goto PerlException;
8612             }
8613           /*
8614             Parameter Handling used for BOTH normal and tiled composition.
8615           */
8616           if (attribute_flag[1] != 0) /* compose */
8617             compose=(CompositeOperator) argument_list[1].integer_reference;
8618           if (attribute_flag[6] != 0) /* opacity  */
8619             {
8620               if (compose != DissolveCompositeOp)
8621                 (void) SetImageAlpha(composite_image,(Quantum)
8622                   StringToDoubleInterval(argument_list[6].string_reference,
8623                   (double) QuantumRange+1.0),exception);
8624               else
8625                 {
8626                   CacheView
8627                     *composite_view;
8628
8629                   double
8630                     opacity;
8631
8632                   MagickBooleanType
8633                     sync;
8634
8635                   register ssize_t
8636                     x;
8637
8638                   register Quantum
8639                     *q;
8640
8641                   ssize_t
8642                     y;
8643
8644                   /*
8645                     Handle dissolve composite operator (patch by
8646                     Kevin A. McGrail).
8647                   */
8648                   (void) CloneString(&image->geometry,
8649                     argument_list[6].string_reference);
8650                   opacity=(Quantum) StringToDoubleInterval(
8651                     argument_list[6].string_reference,(double) QuantumRange+
8652                     1.0);
8653                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8654                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8655                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8656                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8657                   {
8658                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8659                       composite_image->columns,1,exception);
8660                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8661                     {
8662                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8663                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8664                           q);
8665                       q+=GetPixelChannels(composite_image);
8666                     }
8667                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8668                     if (sync == MagickFalse)
8669                       break;
8670                   }
8671                   composite_view=DestroyCacheView(composite_view);
8672                 }
8673             }
8674           if (attribute_flag[9] != 0)    /* "color=>" */
8675             QueryColorCompliance(argument_list[9].string_reference,
8676               AllCompliance,&composite_image->background_color,exception);
8677           if (attribute_flag[12] != 0) /* "interpolate=>" */
8678             image->interpolate=(PixelInterpolateMethod)
8679               argument_list[12].integer_reference;
8680           if (attribute_flag[13] != 0)   /* "args=>" */
8681             (void) SetImageArtifact(composite_image,"compose:args",
8682               argument_list[13].string_reference);
8683           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8684             (void) SetImageArtifact(composite_image,"compose:args",
8685               argument_list[14].string_reference);
8686           clip_to_self=MagickTrue;
8687           if (attribute_flag[15] != 0)
8688             clip_to_self=(MagickBooleanType)
8689               argument_list[15].integer_reference;
8690           /*
8691             Tiling Composition (with orthogonal rotate).
8692           */
8693           rotate_image=(Image *) NULL;
8694           if (attribute_flag[8] != 0)   /* "rotate=>" */
8695             {
8696                /*
8697                  Rotate image.
8698                */
8699                rotate_image=RotateImage(composite_image,
8700                  argument_list[8].real_reference,exception);
8701                if (rotate_image == (Image *) NULL)
8702                  break;
8703             }
8704           if ((attribute_flag[7] != 0) &&
8705               (argument_list[7].integer_reference != 0)) /* tile */
8706             {
8707               ssize_t
8708                 x,
8709                 y;
8710
8711               /*
8712                 Tile the composite image.
8713               */
8714              if (attribute_flag[8] != 0)   /* "tile=>" */
8715                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8716                  "false");
8717              else
8718                (void) SetImageArtifact(composite_image,
8719                  "compose:outside-overlay","false");
8720              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8721                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8722                 {
8723                   if (attribute_flag[8] != 0) /* rotate */
8724                     (void) CompositeImage(image,rotate_image,compose,
8725                       MagickTrue,x,y,exception);
8726                   else
8727                     (void) CompositeImage(image,composite_image,compose,
8728                       MagickTrue,x,y,exception);
8729                 }
8730               if (attribute_flag[8] != 0) /* rotate */
8731                 rotate_image=DestroyImage(rotate_image);
8732               break;
8733             }
8734           /*
8735             Parameter Handling used used ONLY for normal composition.
8736           */
8737           if (attribute_flag[5] != 0) /* gravity */
8738             image->gravity=(GravityType) argument_list[5].integer_reference;
8739           if (attribute_flag[2] != 0) /* geometry offset */
8740             {
8741               SetGeometry(image,&geometry);
8742               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8743                 &geometry);
8744               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8745                 &geometry);
8746             }
8747           if (attribute_flag[3] != 0) /* x offset */
8748             geometry.x=argument_list[3].integer_reference;
8749           if (attribute_flag[4] != 0) /* y offset */
8750             geometry.y=argument_list[4].integer_reference;
8751           if (attribute_flag[10] != 0) /* mask */
8752             {
8753               if ((image->compose == DisplaceCompositeOp) ||
8754                   (image->compose == DistortCompositeOp))
8755                 {
8756                   /*
8757                     Merge Y displacement into X displacement image.
8758                   */
8759                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8760                     exception);
8761                   (void) CompositeImage(composite_image,
8762                     argument_list[10].image_reference,CopyGreenCompositeOp,
8763                     MagickTrue,0,0,exception);
8764                 }
8765               else
8766                 {
8767                   Image
8768                     *mask_image;
8769
8770                   /*
8771                     Set a blending mask for the composition.
8772                   */
8773                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8774                     MagickTrue,exception);
8775                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8776                     exception);
8777                   mask_image=DestroyImage(mask_image);
8778                 }
8779             }
8780           if (attribute_flag[11] != 0) /* channel */
8781             channel=(ChannelType) argument_list[11].integer_reference;
8782           /*
8783             Composite two images (normal composition).
8784           */
8785           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8786             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8787             (double) composite_image->rows,(double) geometry.x,(double)
8788             geometry.y);
8789           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8790             exception);
8791           channel_mask=SetImageChannelMask(image,channel);
8792           if (attribute_flag[8] == 0) /* no rotate */
8793             CompositeImage(image,composite_image,compose,clip_to_self,
8794               geometry.x,geometry.y,exception);
8795           else
8796             {
8797               /*
8798                 Position adjust rotated image then composite.
8799               */
8800               geometry.x-=(ssize_t) (rotate_image->columns-
8801                 composite_image->columns)/2;
8802               geometry.y-=(ssize_t) (rotate_image->rows-
8803                 composite_image->rows)/2;
8804               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8805                 geometry.y,exception);
8806               rotate_image=DestroyImage(rotate_image);
8807             }
8808           if (attribute_flag[10] != 0) /* mask */
8809             {
8810               if ((image->compose == DisplaceCompositeOp) ||
8811                   (image->compose == DistortCompositeOp))
8812                 composite_image=DestroyImage(composite_image);
8813               else
8814                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8815                   exception);
8816             }
8817           (void) SetImageChannelMask(image,channel_mask);
8818           break;
8819         }
8820         case 36:  /* Contrast */
8821         {
8822           if (attribute_flag[0] == 0)
8823             argument_list[0].integer_reference=0;
8824           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8825             MagickTrue : MagickFalse,exception);
8826           break;
8827         }
8828         case 37:  /* CycleColormap */
8829         {
8830           if (attribute_flag[0] == 0)
8831             argument_list[0].integer_reference=6;
8832           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8833             exception);
8834           break;
8835         }
8836         case 38:  /* Draw */
8837         {
8838           DrawInfo
8839             *draw_info;
8840
8841           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8842             (DrawInfo *) NULL);
8843           (void) CloneString(&draw_info->primitive,"point");
8844           if (attribute_flag[0] != 0)
8845             {
8846               if (argument_list[0].integer_reference < 0)
8847                 (void) CloneString(&draw_info->primitive,
8848                   argument_list[0].string_reference);
8849               else
8850                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8851                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8852             }
8853           if (attribute_flag[1] != 0)
8854             {
8855               if (LocaleCompare(draw_info->primitive,"path") == 0)
8856                 {
8857                   (void) ConcatenateString(&draw_info->primitive," '");
8858                   ConcatenateString(&draw_info->primitive,
8859                     argument_list[1].string_reference);
8860                   (void) ConcatenateString(&draw_info->primitive,"'");
8861                 }
8862               else
8863                 {
8864                   (void) ConcatenateString(&draw_info->primitive," ");
8865                   ConcatenateString(&draw_info->primitive,
8866                     argument_list[1].string_reference);
8867                 }
8868             }
8869           if (attribute_flag[2] != 0)
8870             {
8871               (void) ConcatenateString(&draw_info->primitive," ");
8872               (void) ConcatenateString(&draw_info->primitive,
8873                 CommandOptionToMnemonic(MagickMethodOptions,
8874                 argument_list[2].integer_reference));
8875             }
8876           if (attribute_flag[3] != 0)
8877             {
8878               (void) QueryColorCompliance(argument_list[3].string_reference,
8879                 AllCompliance,&draw_info->stroke,exception);
8880               if (argument_list[3].image_reference != (Image *) NULL)
8881                 draw_info->stroke_pattern=CloneImage(
8882                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8883             }
8884           if (attribute_flag[4] != 0)
8885             {
8886               (void) QueryColorCompliance(argument_list[4].string_reference,
8887                 AllCompliance,&draw_info->fill,exception);
8888               if (argument_list[4].image_reference != (Image *) NULL)
8889                 draw_info->fill_pattern=CloneImage(
8890                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8891             }
8892           if (attribute_flag[5] != 0)
8893             draw_info->stroke_width=argument_list[5].real_reference;
8894           if (attribute_flag[6] != 0)
8895             (void) CloneString(&draw_info->font,
8896               argument_list[6].string_reference);
8897           if (attribute_flag[7] != 0)
8898             (void) QueryColorCompliance(argument_list[7].string_reference,
8899               AllCompliance,&draw_info->border_color,exception);
8900           if (attribute_flag[8] != 0)
8901             draw_info->affine.tx=argument_list[8].real_reference;
8902           if (attribute_flag[9] != 0)
8903             draw_info->affine.ty=argument_list[9].real_reference;
8904           if (attribute_flag[20] != 0)
8905             {
8906               AV
8907                 *av;
8908
8909               av=(AV *) argument_list[20].array_reference;
8910               if ((av_len(av) != 3) && (av_len(av) != 5))
8911                 {
8912                   ThrowPerlException(exception,OptionError,
8913                     "affine matrix must have 4 or 6 elements",PackageName);
8914                   goto PerlException;
8915                 }
8916               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8917               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8918               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8919               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8920               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8921                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8922                 {
8923                   ThrowPerlException(exception,OptionError,
8924                     "affine matrix is singular",PackageName);
8925                    goto PerlException;
8926                 }
8927               if (av_len(av) == 5)
8928                 {
8929                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8930                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8931                 }
8932             }
8933           for (j=10; j < 15; j++)
8934           {
8935             if (attribute_flag[j] == 0)
8936               continue;
8937             value=argument_list[j].string_reference;
8938             angle=argument_list[j].real_reference;
8939             current=draw_info->affine;
8940             GetAffineMatrix(&affine);
8941             switch (j)
8942             {
8943               case 10:
8944               {
8945                 /*
8946                   Translate.
8947                 */
8948                 flags=ParseGeometry(value,&geometry_info);
8949                 affine.tx=geometry_info.xi;
8950                 affine.ty=geometry_info.psi;
8951                 if ((flags & PsiValue) == 0)
8952                   affine.ty=affine.tx;
8953                 break;
8954               }
8955               case 11:
8956               {
8957                 /*
8958                   Scale.
8959                 */
8960                 flags=ParseGeometry(value,&geometry_info);
8961                 affine.sx=geometry_info.rho;
8962                 affine.sy=geometry_info.sigma;
8963                 if ((flags & SigmaValue) == 0)
8964                   affine.sy=affine.sx;
8965                 break;
8966               }
8967               case 12:
8968               {
8969                 /*
8970                   Rotate.
8971                 */
8972                 if (angle == 0.0)
8973                   break;
8974                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8975                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8976                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8977                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8978                 break;
8979               }
8980               case 13:
8981               {
8982                 /*
8983                   SkewX.
8984                 */
8985                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8986                 break;
8987               }
8988               case 14:
8989               {
8990                 /*
8991                   SkewY.
8992                 */
8993                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8994                 break;
8995               }
8996             }
8997             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8998             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8999             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9000             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9001             draw_info->affine.tx=
9002               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9003             draw_info->affine.ty=
9004               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9005           }
9006           if (attribute_flag[15] != 0)
9007             draw_info->fill_pattern=CloneImage(
9008               argument_list[15].image_reference,0,0,MagickTrue,exception);
9009           if (attribute_flag[16] != 0)
9010             draw_info->pointsize=argument_list[16].real_reference;
9011           if (attribute_flag[17] != 0)
9012             {
9013               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9014                 ? MagickTrue : MagickFalse;
9015               draw_info->text_antialias=draw_info->stroke_antialias;
9016             }
9017           if (attribute_flag[18] != 0)
9018             (void) CloneString(&draw_info->density,
9019               argument_list[18].string_reference);
9020           if (attribute_flag[19] != 0)
9021             draw_info->stroke_width=argument_list[19].real_reference;
9022           if (attribute_flag[21] != 0)
9023             draw_info->dash_offset=argument_list[21].real_reference;
9024           if (attribute_flag[22] != 0)
9025             {
9026               AV
9027                 *av;
9028
9029               av=(AV *) argument_list[22].array_reference;
9030               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9031                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9032               if (draw_info->dash_pattern != (double *) NULL)
9033                 {
9034                   for (i=0; i <= av_len(av); i++)
9035                     draw_info->dash_pattern[i]=(double)
9036                       SvNV(*(av_fetch(av,i,0)));
9037                   draw_info->dash_pattern[i]=0.0;
9038                 }
9039             }
9040           if (attribute_flag[23] != 0)
9041             image->interpolate=(PixelInterpolateMethod)
9042               argument_list[23].integer_reference;
9043           if ((attribute_flag[24] != 0) &&
9044               (draw_info->fill_pattern != (Image *) NULL))
9045             flags=ParsePageGeometry(draw_info->fill_pattern,
9046               argument_list[24].string_reference,
9047               &draw_info->fill_pattern->tile_offset,exception);
9048           if (attribute_flag[25] != 0)
9049             {
9050               (void) ConcatenateString(&draw_info->primitive," '");
9051               (void) ConcatenateString(&draw_info->primitive,
9052                 argument_list[25].string_reference);
9053               (void) ConcatenateString(&draw_info->primitive,"'");
9054             }
9055           if (attribute_flag[26] != 0)
9056             draw_info->fill_pattern=CloneImage(
9057               argument_list[26].image_reference,0,0,MagickTrue,exception);
9058           if (attribute_flag[27] != 0)
9059             draw_info->stroke_pattern=CloneImage(
9060               argument_list[27].image_reference,0,0,MagickTrue,exception);
9061           if (attribute_flag[28] != 0)
9062             (void) CloneString(&draw_info->primitive,
9063               argument_list[28].string_reference);
9064           if (attribute_flag[29] != 0)
9065             draw_info->kerning=argument_list[29].real_reference;
9066           if (attribute_flag[30] != 0)
9067             draw_info->interline_spacing=argument_list[30].real_reference;
9068           if (attribute_flag[31] != 0)
9069             draw_info->interword_spacing=argument_list[31].real_reference;
9070           if (attribute_flag[32] != 0)
9071             draw_info->direction=(DirectionType)
9072               argument_list[32].integer_reference;
9073           DrawImage(image,draw_info,exception);
9074           draw_info=DestroyDrawInfo(draw_info);
9075           break;
9076         }
9077         case 39:  /* Equalize */
9078         {
9079           if (attribute_flag[0] != 0)
9080             channel=(ChannelType) argument_list[0].integer_reference;
9081           channel_mask=SetImageChannelMask(image,channel);
9082           EqualizeImage(image,exception);
9083           (void) SetImageChannelMask(image,channel_mask);
9084           break;
9085         }
9086         case 40:  /* Gamma */
9087         {
9088           if (attribute_flag[1] != 0)
9089             channel=(ChannelType) argument_list[1].integer_reference;
9090           if (attribute_flag[2] == 0)
9091             argument_list[2].real_reference=1.0;
9092           if (attribute_flag[3] == 0)
9093             argument_list[3].real_reference=1.0;
9094           if (attribute_flag[4] == 0)
9095             argument_list[4].real_reference=1.0;
9096           if (attribute_flag[0] == 0)
9097             {
9098               (void) FormatLocaleString(message,MagickPathExtent,
9099                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9100                 (double) argument_list[3].real_reference,
9101                 (double) argument_list[4].real_reference);
9102               argument_list[0].string_reference=message;
9103             }
9104           (void) GammaImage(image,StringToDouble(
9105             argument_list[0].string_reference,(char **) NULL),exception);
9106           break;
9107         }
9108         case 41:  /* Map */
9109         {
9110           QuantizeInfo
9111             *quantize_info;
9112
9113           if (attribute_flag[0] == 0)
9114             {
9115               ThrowPerlException(exception,OptionError,"MapImageRequired",
9116                 PackageName);
9117               goto PerlException;
9118             }
9119           quantize_info=AcquireQuantizeInfo(info->image_info);
9120           if (attribute_flag[1] != 0)
9121             quantize_info->dither_method=(DitherMethod)
9122               argument_list[1].integer_reference;
9123           (void) RemapImages(quantize_info,image,
9124             argument_list[0].image_reference,exception);
9125           quantize_info=DestroyQuantizeInfo(quantize_info);
9126           break;
9127         }
9128         case 42:  /* MatteFloodfill */
9129         {
9130           DrawInfo
9131             *draw_info;
9132
9133           MagickBooleanType
9134             invert;
9135
9136           PixelInfo
9137             target;
9138
9139           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9140             (DrawInfo *) NULL);
9141           if (attribute_flag[0] != 0)
9142             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9143               &geometry,exception);
9144           if (attribute_flag[1] != 0)
9145             geometry.x=argument_list[1].integer_reference;
9146           if (attribute_flag[2] != 0)
9147             geometry.y=argument_list[2].integer_reference;
9148           if (image->alpha_trait == UndefinedPixelTrait)
9149             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9150           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9151             geometry.x,geometry.y,&target,exception);
9152           if (attribute_flag[4] != 0)
9153             QueryColorCompliance(argument_list[4].string_reference,
9154               AllCompliance,&target,exception);
9155           if (attribute_flag[3] != 0)
9156             target.alpha=StringToDoubleInterval(
9157               argument_list[3].string_reference,(double) (double) QuantumRange+
9158               1.0);
9159           if (attribute_flag[5] != 0)
9160             image->fuzz=StringToDoubleInterval(
9161               argument_list[5].string_reference,(double) QuantumRange+1.0);
9162           invert=MagickFalse;
9163           if (attribute_flag[6] != 0)
9164             invert=(MagickBooleanType) argument_list[6].integer_reference;
9165           channel_mask=SetImageChannelMask(image,AlphaChannel);
9166           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9167             geometry.y,invert,exception);
9168           (void) SetImageChannelMask(image,channel_mask);
9169           draw_info=DestroyDrawInfo(draw_info);
9170           break;
9171         }
9172         case 43:  /* Modulate */
9173         {
9174           char
9175             modulate[MagickPathExtent];
9176
9177           geometry_info.rho=100.0;
9178           geometry_info.sigma=100.0;
9179           geometry_info.xi=100.0;
9180           if (attribute_flag[0] != 0)
9181             (void)ParseGeometry(argument_list[0].string_reference,
9182               &geometry_info);
9183           if (attribute_flag[1] != 0)
9184             geometry_info.xi=argument_list[1].real_reference;
9185           if (attribute_flag[2] != 0)
9186             geometry_info.sigma=argument_list[2].real_reference;
9187           if (attribute_flag[3] != 0)
9188             {
9189               geometry_info.sigma=argument_list[3].real_reference;
9190               SetImageArtifact(image,"modulate:colorspace","HWB");
9191             }
9192           if (attribute_flag[4] != 0)
9193             {
9194               geometry_info.rho=argument_list[4].real_reference;
9195               SetImageArtifact(image,"modulate:colorspace","HSB");
9196             }
9197           if (attribute_flag[5] != 0)
9198             {
9199               geometry_info.sigma=argument_list[5].real_reference;
9200               SetImageArtifact(image,"modulate:colorspace","HSL");
9201             }
9202           if (attribute_flag[6] != 0)
9203             {
9204               geometry_info.rho=argument_list[6].real_reference;
9205               SetImageArtifact(image,"modulate:colorspace","HWB");
9206             }
9207           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9208             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9209           (void) ModulateImage(image,modulate,exception);
9210           break;
9211         }
9212         case 44:  /* Negate */
9213         {
9214           if (attribute_flag[0] == 0)
9215             argument_list[0].integer_reference=0;
9216           if (attribute_flag[1] != 0)
9217             channel=(ChannelType) argument_list[1].integer_reference;
9218           channel_mask=SetImageChannelMask(image,channel);
9219           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9220             MagickTrue : MagickFalse,exception);
9221           (void) SetImageChannelMask(image,channel_mask);
9222           break;
9223         }
9224         case 45:  /* Normalize */
9225         {
9226           if (attribute_flag[0] != 0)
9227             channel=(ChannelType) argument_list[0].integer_reference;
9228           channel_mask=SetImageChannelMask(image,channel);
9229           NormalizeImage(image,exception);
9230           (void) SetImageChannelMask(image,channel_mask);
9231           break;
9232         }
9233         case 46:  /* NumberColors */
9234           break;
9235         case 47:  /* Opaque */
9236         {
9237           MagickBooleanType
9238             invert;
9239
9240           PixelInfo
9241             fill_color,
9242             target;
9243
9244           (void) QueryColorCompliance("none",AllCompliance,&target,
9245              exception);
9246           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9247             exception);
9248           if (attribute_flag[0] != 0)
9249             (void) QueryColorCompliance(argument_list[0].string_reference,
9250               AllCompliance,&target,exception);
9251           if (attribute_flag[1] != 0)
9252             (void) QueryColorCompliance(argument_list[1].string_reference,
9253               AllCompliance,&fill_color,exception);
9254           if (attribute_flag[2] != 0)
9255             image->fuzz=StringToDoubleInterval(
9256               argument_list[2].string_reference,(double) QuantumRange+1.0);
9257           if (attribute_flag[3] != 0)
9258             channel=(ChannelType) argument_list[3].integer_reference;
9259           invert=MagickFalse;
9260           if (attribute_flag[4] != 0)
9261             invert=(MagickBooleanType) argument_list[4].integer_reference;
9262           channel_mask=SetImageChannelMask(image,channel);
9263           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9264           (void) SetImageChannelMask(image,channel_mask);
9265           break;
9266         }
9267         case 48:  /* Quantize */
9268         {
9269           QuantizeInfo
9270             *quantize_info;
9271
9272           quantize_info=AcquireQuantizeInfo(info->image_info);
9273           if (attribute_flag[0] != 0)
9274             quantize_info->number_colors=(size_t)
9275               argument_list[0].integer_reference;
9276           if (attribute_flag[1] != 0)
9277             quantize_info->tree_depth=(size_t)
9278               argument_list[1].integer_reference;
9279           if (attribute_flag[2] != 0)
9280             quantize_info->colorspace=(ColorspaceType)
9281               argument_list[2].integer_reference;
9282           if (attribute_flag[3] != 0)
9283             quantize_info->dither_method=(DitherMethod)
9284               argument_list[3].integer_reference;
9285           if (attribute_flag[4] != 0)
9286             quantize_info->measure_error=
9287               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9288           if (attribute_flag[6] != 0)
9289             (void) QueryColorCompliance(argument_list[6].string_reference,
9290               AllCompliance,&image->transparent_color,exception);
9291           if (attribute_flag[7] != 0)
9292             quantize_info->dither_method=(DitherMethod)
9293               argument_list[7].integer_reference;
9294           if (attribute_flag[5] && argument_list[5].integer_reference)
9295             (void) QuantizeImages(quantize_info,image,exception);
9296           else
9297             if ((image->storage_class == DirectClass) ||
9298                (image->colors > quantize_info->number_colors) ||
9299                (quantize_info->colorspace == GRAYColorspace))
9300              (void) QuantizeImage(quantize_info,image,exception);
9301            else
9302              CompressImageColormap(image,exception);
9303           quantize_info=DestroyQuantizeInfo(quantize_info);
9304           break;
9305         }
9306         case 49:  /* Raise */
9307         {
9308           if (attribute_flag[0] != 0)
9309             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9310               &geometry,exception);
9311           if (attribute_flag[1] != 0)
9312             geometry.width=argument_list[1].integer_reference;
9313           if (attribute_flag[2] != 0)
9314             geometry.height=argument_list[2].integer_reference;
9315           if (attribute_flag[3] == 0)
9316             argument_list[3].integer_reference=1;
9317           (void) RaiseImage(image,&geometry,
9318             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9319             exception);
9320           break;
9321         }
9322         case 50:  /* Segment */
9323         {
9324           ColorspaceType
9325             colorspace;
9326
9327           double
9328             cluster_threshold,
9329             smoothing_threshold;
9330
9331           MagickBooleanType
9332             verbose;
9333
9334           cluster_threshold=1.0;
9335           smoothing_threshold=1.5;
9336           colorspace=sRGBColorspace;
9337           verbose=MagickFalse;
9338           if (attribute_flag[0] != 0)
9339             {
9340               flags=ParseGeometry(argument_list[0].string_reference,
9341                 &geometry_info);
9342               cluster_threshold=geometry_info.rho;
9343               if (flags & SigmaValue)
9344                 smoothing_threshold=geometry_info.sigma;
9345             }
9346           if (attribute_flag[1] != 0)
9347             cluster_threshold=argument_list[1].real_reference;
9348           if (attribute_flag[2] != 0)
9349             smoothing_threshold=argument_list[2].real_reference;
9350           if (attribute_flag[3] != 0)
9351             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9352           if (attribute_flag[4] != 0)
9353             verbose=argument_list[4].integer_reference != 0 ?
9354               MagickTrue : MagickFalse;
9355           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9356             smoothing_threshold,exception);
9357           break;
9358         }
9359         case 51:  /* Signature */
9360         {
9361           (void) SignatureImage(image,exception);
9362           break;
9363         }
9364         case 52:  /* Solarize */
9365         {
9366           geometry_info.rho=QuantumRange/2.0;
9367           if (attribute_flag[0] != 0)
9368             flags=ParseGeometry(argument_list[0].string_reference,
9369               &geometry_info);
9370           if (attribute_flag[1] != 0)
9371             geometry_info.rho=StringToDoubleInterval(
9372               argument_list[1].string_reference,(double) QuantumRange+1.0);
9373           (void) SolarizeImage(image,geometry_info.rho,exception);
9374           break;
9375         }
9376         case 53:  /* Sync */
9377         {
9378           (void) SyncImage(image,exception);
9379           break;
9380         }
9381         case 54:  /* Texture */
9382         {
9383           if (attribute_flag[0] == 0)
9384             break;
9385           TextureImage(image,argument_list[0].image_reference,exception);
9386           break;
9387         }
9388         case 55:  /* Evalute */
9389         {
9390           MagickEvaluateOperator
9391             op;
9392
9393           op=SetEvaluateOperator;
9394           if (attribute_flag[0] == MagickFalse)
9395             argument_list[0].real_reference=0.0;
9396           if (attribute_flag[1] != MagickFalse)
9397             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9398           if (attribute_flag[2] != MagickFalse)
9399             channel=(ChannelType) argument_list[2].integer_reference;
9400           channel_mask=SetImageChannelMask(image,channel);
9401           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9402             exception);
9403           (void) SetImageChannelMask(image,channel_mask);
9404           break;
9405         }
9406         case 56:  /* Transparent */
9407         {
9408           double
9409             opacity;
9410
9411           MagickBooleanType
9412             invert;
9413
9414           PixelInfo
9415             target;
9416
9417           (void) QueryColorCompliance("none",AllCompliance,&target,
9418             exception);
9419           if (attribute_flag[0] != 0)
9420             (void) QueryColorCompliance(argument_list[0].string_reference,
9421               AllCompliance,&target,exception);
9422           opacity=TransparentAlpha;
9423           if (attribute_flag[1] != 0)
9424             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9425               (double) QuantumRange+1.0);
9426           if (attribute_flag[2] != 0)
9427             image->fuzz=StringToDoubleInterval(
9428               argument_list[2].string_reference,(double) QuantumRange+1.0);
9429           if (attribute_flag[3] == 0)
9430             argument_list[3].integer_reference=0;
9431           invert=MagickFalse;
9432           if (attribute_flag[3] != 0)
9433             invert=(MagickBooleanType) argument_list[3].integer_reference;
9434           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9435             invert,exception);
9436           break;
9437         }
9438         case 57:  /* Threshold */
9439         {
9440           double
9441             threshold;
9442
9443           if (attribute_flag[0] == 0)
9444             argument_list[0].string_reference="50%";
9445           if (attribute_flag[1] != 0)
9446             channel=(ChannelType) argument_list[1].integer_reference;
9447           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9448             (double) QuantumRange+1.0);
9449           channel_mask=SetImageChannelMask(image,channel);
9450           (void) BilevelImage(image,threshold,exception);
9451           (void) SetImageChannelMask(image,channel_mask);
9452           break;
9453         }
9454         case 58:  /* Charcoal */
9455         {
9456           if (attribute_flag[0] != 0)
9457             {
9458               flags=ParseGeometry(argument_list[0].string_reference,
9459                 &geometry_info);
9460               if ((flags & SigmaValue) == 0)
9461                 geometry_info.sigma=1.0;
9462             }
9463           if (attribute_flag[1] != 0)
9464             geometry_info.rho=argument_list[1].real_reference;
9465           if (attribute_flag[2] != 0)
9466             geometry_info.sigma=argument_list[2].real_reference;
9467           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9468             exception);
9469           break;
9470         }
9471         case 59:  /* Trim */
9472         {
9473           if (attribute_flag[0] != 0)
9474             image->fuzz=StringToDoubleInterval(
9475               argument_list[0].string_reference,(double) QuantumRange+1.0);
9476           image=TrimImage(image,exception);
9477           break;
9478         }
9479         case 60:  /* Wave */
9480         {
9481           PixelInterpolateMethod
9482             method;
9483
9484           if (attribute_flag[0] != 0)
9485             {
9486               flags=ParseGeometry(argument_list[0].string_reference,
9487                 &geometry_info);
9488               if ((flags & SigmaValue) == 0)
9489                 geometry_info.sigma=1.0;
9490             }
9491           if (attribute_flag[1] != 0)
9492             geometry_info.rho=argument_list[1].real_reference;
9493           if (attribute_flag[2] != 0)
9494             geometry_info.sigma=argument_list[2].real_reference;
9495           method=UndefinedInterpolatePixel;
9496           if (attribute_flag[3] != 0)
9497             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9498           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9499             method,exception);
9500           break;
9501         }
9502         case 61:  /* Separate */
9503         {
9504           if (attribute_flag[0] != 0)
9505             channel=(ChannelType) argument_list[0].integer_reference;
9506           image=SeparateImage(image,channel,exception);
9507           break;
9508         }
9509         case 63:  /* Stereo */
9510         {
9511           if (attribute_flag[0] == 0)
9512             {
9513               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9514                 PackageName);
9515               goto PerlException;
9516             }
9517           if (attribute_flag[1] != 0)
9518             geometry.x=argument_list[1].integer_reference;
9519           if (attribute_flag[2] != 0)
9520             geometry.y=argument_list[2].integer_reference;
9521           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9522             geometry.x,geometry.y,exception);
9523           break;
9524         }
9525         case 64:  /* Stegano */
9526         {
9527           if (attribute_flag[0] == 0)
9528             {
9529               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9530                 PackageName);
9531               goto PerlException;
9532             }
9533           if (attribute_flag[1] == 0)
9534             argument_list[1].integer_reference=0;
9535           image->offset=argument_list[1].integer_reference;
9536           image=SteganoImage(image,argument_list[0].image_reference,exception);
9537           break;
9538         }
9539         case 65:  /* Deconstruct */
9540         {
9541           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9542           break;
9543         }
9544         case 66:  /* GaussianBlur */
9545         {
9546           if (attribute_flag[0] != 0)
9547             {
9548               flags=ParseGeometry(argument_list[0].string_reference,
9549                 &geometry_info);
9550               if ((flags & SigmaValue) == 0)
9551                 geometry_info.sigma=1.0;
9552             }
9553           if (attribute_flag[1] != 0)
9554             geometry_info.rho=argument_list[1].real_reference;
9555           if (attribute_flag[2] != 0)
9556             geometry_info.sigma=argument_list[2].real_reference;
9557           if (attribute_flag[3] != 0)
9558             channel=(ChannelType) argument_list[3].integer_reference;
9559           channel_mask=SetImageChannelMask(image,channel);
9560           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9561             exception);
9562           if (image != (Image *) NULL)
9563             (void) SetImageChannelMask(image,channel_mask);
9564           break;
9565         }
9566         case 67:  /* Convolve */
9567         {
9568           KernelInfo
9569             *kernel;
9570
9571           kernel=(KernelInfo *) NULL;
9572           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9573             break;
9574           if (attribute_flag[0] != 0)
9575             {
9576               AV
9577                 *av;
9578
9579               size_t
9580                 order;
9581
9582               kernel=AcquireKernelInfo((const char *) NULL,exception);
9583               if (kernel == (KernelInfo *) NULL)
9584                 break;
9585               av=(AV *) argument_list[0].array_reference;
9586               order=(size_t) sqrt(av_len(av)+1);
9587               kernel->width=order;
9588               kernel->height=order;
9589               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9590                 order*sizeof(*kernel->values));
9591               if (kernel->values == (MagickRealType *) NULL)
9592                 {
9593                   kernel=DestroyKernelInfo(kernel);
9594                   ThrowPerlException(exception,ResourceLimitFatalError,
9595                     "MemoryAllocationFailed",PackageName);
9596                   goto PerlException;
9597                 }
9598               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9599                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9600               for ( ; j < (ssize_t) (order*order); j++)
9601                 kernel->values[j]=0.0;
9602             }
9603           if (attribute_flag[1] != 0)
9604             channel=(ChannelType) argument_list[1].integer_reference;
9605           if (attribute_flag[2] != 0)
9606             SetImageArtifact(image,"filter:blur",
9607               argument_list[2].string_reference);
9608           if (attribute_flag[3] != 0)
9609             {
9610               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9611                 exception);
9612               if (kernel == (KernelInfo *) NULL)
9613                 break;
9614             }
9615           channel_mask=SetImageChannelMask(image,channel);
9616           image=ConvolveImage(image,kernel,exception);
9617           if (image != (Image *) NULL)
9618             (void) SetImageChannelMask(image,channel_mask);
9619           kernel=DestroyKernelInfo(kernel);
9620           break;
9621         }
9622         case 68:  /* Profile */
9623         {
9624           const char
9625             *name;
9626
9627           Image
9628             *profile_image;
9629
9630           ImageInfo
9631             *profile_info;
9632
9633           StringInfo
9634             *profile;
9635
9636           name="*";
9637           if (attribute_flag[0] != 0)
9638             name=argument_list[0].string_reference;
9639           if (attribute_flag[2] != 0)
9640             image->rendering_intent=(RenderingIntent)
9641               argument_list[2].integer_reference;
9642           if (attribute_flag[3] != 0)
9643             image->black_point_compensation=
9644               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9645           if (attribute_flag[1] != 0)
9646             {
9647               if (argument_list[1].length == 0)
9648                 {
9649                   /*
9650                     Remove a profile from the image.
9651                   */
9652                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9653                     exception);
9654                   break;
9655                 }
9656               /*
9657                 Associate user supplied profile with the image.
9658               */
9659               profile=AcquireStringInfo(argument_list[1].length);
9660               SetStringInfoDatum(profile,(const unsigned char *)
9661                 argument_list[1].string_reference);
9662               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9663                 (size_t) GetStringInfoLength(profile),exception);
9664               profile=DestroyStringInfo(profile);
9665               break;
9666             }
9667           /*
9668             Associate a profile with the image.
9669           */
9670           profile_info=CloneImageInfo(info ? info->image_info :
9671             (ImageInfo *) NULL);
9672           profile_image=ReadImages(profile_info,name,exception);
9673           if (profile_image == (Image *) NULL)
9674             break;
9675           ResetImageProfileIterator(profile_image);
9676           name=GetNextImageProfile(profile_image);
9677           while (name != (const char *) NULL)
9678           {
9679             const StringInfo
9680               *profile;
9681
9682             profile=GetImageProfile(profile_image,name);
9683             if (profile != (const StringInfo *) NULL)
9684               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9685                 (size_t) GetStringInfoLength(profile),exception);
9686             name=GetNextImageProfile(profile_image);
9687           }
9688           profile_image=DestroyImage(profile_image);
9689           profile_info=DestroyImageInfo(profile_info);
9690           break;
9691         }
9692         case 69:  /* UnsharpMask */
9693         {
9694           if (attribute_flag[0] != 0)
9695             {
9696               flags=ParseGeometry(argument_list[0].string_reference,
9697                 &geometry_info);
9698               if ((flags & SigmaValue) == 0)
9699                 geometry_info.sigma=1.0;
9700               if ((flags & XiValue) == 0)
9701                 geometry_info.xi=1.0;
9702               if ((flags & PsiValue) == 0)
9703                 geometry_info.psi=0.5;
9704             }
9705           if (attribute_flag[1] != 0)
9706             geometry_info.rho=argument_list[1].real_reference;
9707           if (attribute_flag[2] != 0)
9708             geometry_info.sigma=argument_list[2].real_reference;
9709           if (attribute_flag[3] != 0)
9710             geometry_info.xi=argument_list[3].real_reference;
9711           if (attribute_flag[4] != 0)
9712             geometry_info.psi=argument_list[4].real_reference;
9713           if (attribute_flag[5] != 0)
9714             channel=(ChannelType) argument_list[5].integer_reference;
9715           channel_mask=SetImageChannelMask(image,channel);
9716           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9717             geometry_info.xi,geometry_info.psi,exception);
9718           if (image != (Image *) NULL)
9719             (void) SetImageChannelMask(image,channel_mask);
9720           break;
9721         }
9722         case 70:  /* MotionBlur */
9723         {
9724           if (attribute_flag[0] != 0)
9725             {
9726               flags=ParseGeometry(argument_list[0].string_reference,
9727                 &geometry_info);
9728               if ((flags & SigmaValue) == 0)
9729                 geometry_info.sigma=1.0;
9730               if ((flags & XiValue) == 0)
9731                 geometry_info.xi=1.0;
9732             }
9733           if (attribute_flag[1] != 0)
9734             geometry_info.rho=argument_list[1].real_reference;
9735           if (attribute_flag[2] != 0)
9736             geometry_info.sigma=argument_list[2].real_reference;
9737           if (attribute_flag[3] != 0)
9738             geometry_info.xi=argument_list[3].real_reference;
9739           if (attribute_flag[4] != 0)
9740             channel=(ChannelType) argument_list[4].integer_reference;
9741           channel_mask=SetImageChannelMask(image,channel);
9742           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9743             geometry_info.xi,exception);
9744           if (image != (Image *) NULL)
9745             (void) SetImageChannelMask(image,channel_mask);
9746           break;
9747         }
9748         case 71:  /* OrderedDither */
9749         {
9750           if (attribute_flag[0] == 0)
9751             argument_list[0].string_reference="o8x8";
9752           if (attribute_flag[1] != 0)
9753             channel=(ChannelType) argument_list[1].integer_reference;
9754           channel_mask=SetImageChannelMask(image,channel);
9755           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9756             exception);
9757           (void) SetImageChannelMask(image,channel_mask);
9758           break;
9759         }
9760         case 72:  /* Shave */
9761         {
9762           if (attribute_flag[0] != 0)
9763             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9764               &geometry,exception);
9765           if (attribute_flag[1] != 0)
9766             geometry.width=argument_list[1].integer_reference;
9767           if (attribute_flag[2] != 0)
9768             geometry.height=argument_list[2].integer_reference;
9769           image=ShaveImage(image,&geometry,exception);
9770           break;
9771         }
9772         case 73:  /* Level */
9773         {
9774           double
9775             black_point,
9776             gamma,
9777             white_point;
9778
9779           black_point=0.0;
9780           white_point=(double) image->columns*image->rows;
9781           gamma=1.0;
9782           if (attribute_flag[0] != 0)
9783             {
9784               flags=ParseGeometry(argument_list[0].string_reference,
9785                 &geometry_info);
9786               black_point=geometry_info.rho;
9787               if ((flags & SigmaValue) != 0)
9788                 white_point=geometry_info.sigma;
9789               if ((flags & XiValue) != 0)
9790                 gamma=geometry_info.xi;
9791               if ((flags & PercentValue) != 0)
9792                 {
9793                   black_point*=(double) (QuantumRange/100.0);
9794                   white_point*=(double) (QuantumRange/100.0);
9795                 }
9796               if ((flags & SigmaValue) == 0)
9797                 white_point=(double) QuantumRange-black_point;
9798             }
9799           if (attribute_flag[1] != 0)
9800             black_point=argument_list[1].real_reference;
9801           if (attribute_flag[2] != 0)
9802             white_point=argument_list[2].real_reference;
9803           if (attribute_flag[3] != 0)
9804             gamma=argument_list[3].real_reference;
9805           if (attribute_flag[4] != 0)
9806             channel=(ChannelType) argument_list[4].integer_reference;
9807           if (attribute_flag[5] != 0)
9808             {
9809               argument_list[0].real_reference=argument_list[5].real_reference;
9810               attribute_flag[0]=attribute_flag[5];
9811             }
9812           channel_mask=SetImageChannelMask(image,channel);
9813           (void) LevelImage(image,black_point,white_point,gamma,exception);
9814           (void) SetImageChannelMask(image,channel_mask);
9815           break;
9816         }
9817         case 74:  /* Clip */
9818         {
9819           if (attribute_flag[0] == 0)
9820             argument_list[0].string_reference="#1";
9821           if (attribute_flag[1] == 0)
9822             argument_list[1].integer_reference=MagickTrue;
9823           (void) ClipImagePath(image,argument_list[0].string_reference,
9824             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9825             exception);
9826           break;
9827         }
9828         case 75:  /* AffineTransform */
9829         {
9830           DrawInfo
9831             *draw_info;
9832
9833           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9834             (DrawInfo *) NULL);
9835           if (attribute_flag[0] != 0)
9836             {
9837               AV
9838                 *av;
9839
9840               av=(AV *) argument_list[0].array_reference;
9841               if ((av_len(av) != 3) && (av_len(av) != 5))
9842                 {
9843                   ThrowPerlException(exception,OptionError,
9844                     "affine matrix must have 4 or 6 elements",PackageName);
9845                   goto PerlException;
9846                 }
9847               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9848               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9849               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9850               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9851               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9852                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9853                 {
9854                   ThrowPerlException(exception,OptionError,
9855                     "affine matrix is singular",PackageName);
9856                    goto PerlException;
9857                 }
9858               if (av_len(av) == 5)
9859                 {
9860                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9861                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9862                 }
9863             }
9864           for (j=1; j < 6; j++)
9865           {
9866             if (attribute_flag[j] == 0)
9867               continue;
9868             value=argument_list[j].string_reference;
9869             angle=argument_list[j].real_reference;
9870             current=draw_info->affine;
9871             GetAffineMatrix(&affine);
9872             switch (j)
9873             {
9874               case 1:
9875               {
9876                 /*
9877                   Translate.
9878                 */
9879                 flags=ParseGeometry(value,&geometry_info);
9880                 affine.tx=geometry_info.xi;
9881                 affine.ty=geometry_info.psi;
9882                 if ((flags & PsiValue) == 0)
9883                   affine.ty=affine.tx;
9884                 break;
9885               }
9886               case 2:
9887               {
9888                 /*
9889                   Scale.
9890                 */
9891                 flags=ParseGeometry(value,&geometry_info);
9892                 affine.sx=geometry_info.rho;
9893                 affine.sy=geometry_info.sigma;
9894                 if ((flags & SigmaValue) == 0)
9895                   affine.sy=affine.sx;
9896                 break;
9897               }
9898               case 3:
9899               {
9900                 /*
9901                   Rotate.
9902                 */
9903                 if (angle == 0.0)
9904                   break;
9905                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9906                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9907                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9908                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9909                 break;
9910               }
9911               case 4:
9912               {
9913                 /*
9914                   SkewX.
9915                 */
9916                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9917                 break;
9918               }
9919               case 5:
9920               {
9921                 /*
9922                   SkewY.
9923                 */
9924                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9925                 break;
9926               }
9927             }
9928             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9929             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9930             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9931             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9932             draw_info->affine.tx=
9933               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9934             draw_info->affine.ty=
9935               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9936           }
9937           if (attribute_flag[6] != 0)
9938             image->interpolate=(PixelInterpolateMethod)
9939               argument_list[6].integer_reference;
9940           if (attribute_flag[7] != 0)
9941             QueryColorCompliance(argument_list[7].string_reference,
9942               AllCompliance,&image->background_color,exception);
9943           image=AffineTransformImage(image,&draw_info->affine,exception);
9944           draw_info=DestroyDrawInfo(draw_info);
9945           break;
9946         }
9947         case 76:  /* Difference */
9948         {
9949           if (attribute_flag[0] == 0)
9950             {
9951               ThrowPerlException(exception,OptionError,
9952                 "ReferenceImageRequired",PackageName);
9953               goto PerlException;
9954             }
9955           if (attribute_flag[1] != 0)
9956             image->fuzz=StringToDoubleInterval(
9957               argument_list[1].string_reference,(double) QuantumRange+1.0);
9958           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9959             exception);
9960           break;
9961         }
9962         case 77:  /* AdaptiveThreshold */
9963         {
9964           if (attribute_flag[0] != 0)
9965             {
9966               flags=ParseGeometry(argument_list[0].string_reference,
9967                 &geometry_info);
9968               if ((flags & PercentValue) != 0)
9969                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9970             }
9971           if (attribute_flag[1] != 0)
9972             geometry_info.rho=argument_list[1].integer_reference;
9973           if (attribute_flag[2] != 0)
9974             geometry_info.sigma=argument_list[2].integer_reference;
9975           if (attribute_flag[3] != 0)
9976             geometry_info.xi=argument_list[3].integer_reference;;
9977           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9978             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9979           break;
9980         }
9981         case 78:  /* Resample */
9982         {
9983           size_t
9984             height,
9985             width;
9986
9987           if (attribute_flag[0] != 0)
9988             {
9989               flags=ParseGeometry(argument_list[0].string_reference,
9990                 &geometry_info);
9991               if ((flags & SigmaValue) == 0)
9992                 geometry_info.sigma=geometry_info.rho;
9993             }
9994           if (attribute_flag[1] != 0)
9995             geometry_info.rho=argument_list[1].real_reference;
9996           if (attribute_flag[2] != 0)
9997             geometry_info.sigma=argument_list[2].real_reference;
9998           if (attribute_flag[3] == 0)
9999             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10000           if (attribute_flag[4] == 0)
10001             SetImageArtifact(image,"filter:support",
10002               argument_list[4].string_reference);
10003           width=(size_t) (geometry_info.rho*image->columns/
10004             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10005           height=(size_t) (geometry_info.sigma*image->rows/
10006             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10007           image=ResizeImage(image,width,height,(FilterTypes)
10008             argument_list[3].integer_reference,exception);
10009           if (image != (Image *) NULL)
10010             {
10011               image->resolution.x=geometry_info.rho;
10012               image->resolution.y=geometry_info.sigma;
10013             }
10014           break;
10015         }
10016         case 79:  /* Describe */
10017         {
10018           if (attribute_flag[0] == 0)
10019             argument_list[0].file_reference=(FILE *) NULL;
10020           if (attribute_flag[1] != 0)
10021             (void) SetImageArtifact(image,"identify:features",
10022               argument_list[1].string_reference);
10023           (void) IdentifyImage(image,argument_list[0].file_reference,
10024             MagickTrue,exception);
10025           break;
10026         }
10027         case 80:  /* BlackThreshold */
10028         {
10029           if (attribute_flag[0] == 0)
10030             argument_list[0].string_reference="50%";
10031           if (attribute_flag[2] != 0)
10032             channel=(ChannelType) argument_list[2].integer_reference;
10033           channel_mask=SetImageChannelMask(image,channel);
10034           BlackThresholdImage(image,argument_list[0].string_reference,
10035             exception);
10036           (void) SetImageChannelMask(image,channel_mask);
10037           break;
10038         }
10039         case 81:  /* WhiteThreshold */
10040         {
10041           if (attribute_flag[0] == 0)
10042             argument_list[0].string_reference="50%";
10043           if (attribute_flag[2] != 0)
10044             channel=(ChannelType) argument_list[2].integer_reference;
10045           channel_mask=SetImageChannelMask(image,channel);
10046           WhiteThresholdImage(image,argument_list[0].string_reference,
10047             exception);
10048           (void) SetImageChannelMask(image,channel_mask);
10049           break;
10050         }
10051         case 82:  /* RotationalBlur */
10052         {
10053           if (attribute_flag[0] != 0)
10054             {
10055               flags=ParseGeometry(argument_list[0].string_reference,
10056                 &geometry_info);
10057             }
10058           if (attribute_flag[1] != 0)
10059             geometry_info.rho=argument_list[1].real_reference;
10060           if (attribute_flag[2] != 0)
10061             channel=(ChannelType) argument_list[2].integer_reference;
10062           channel_mask=SetImageChannelMask(image,channel);
10063           image=RotationalBlurImage(image,geometry_info.rho,exception);
10064           if (image != (Image *) NULL)
10065             (void) SetImageChannelMask(image,channel_mask);
10066           break;
10067         }
10068         case 83:  /* Thumbnail */
10069         {
10070           if (attribute_flag[0] != 0)
10071             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10072               &geometry,exception);
10073           if (attribute_flag[1] != 0)
10074             geometry.width=argument_list[1].integer_reference;
10075           if (attribute_flag[2] != 0)
10076             geometry.height=argument_list[2].integer_reference;
10077           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10078           break;
10079         }
10080         case 84:  /* Strip */
10081         {
10082           (void) StripImage(image,exception);
10083           break;
10084         }
10085         case 85:  /* Tint */
10086         {
10087           PixelInfo
10088             tint;
10089
10090           GetPixelInfo(image,&tint);
10091           if (attribute_flag[0] != 0)
10092             (void) QueryColorCompliance(argument_list[0].string_reference,
10093               AllCompliance,&tint,exception);
10094           if (attribute_flag[1] == 0)
10095             argument_list[1].string_reference="100";
10096           image=TintImage(image,argument_list[1].string_reference,&tint,
10097             exception);
10098           break;
10099         }
10100         case 86:  /* Channel */
10101         {
10102           if (attribute_flag[0] != 0)
10103             channel=(ChannelType) argument_list[0].integer_reference;
10104           image=SeparateImage(image,channel,exception);
10105           break;
10106         }
10107         case 87:  /* Splice */
10108         {
10109           if (attribute_flag[7] != 0)
10110             image->gravity=(GravityType) argument_list[7].integer_reference;
10111           if (attribute_flag[0] != 0)
10112             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10113               &geometry,exception);
10114           if (attribute_flag[1] != 0)
10115             geometry.width=argument_list[1].integer_reference;
10116           if (attribute_flag[2] != 0)
10117             geometry.height=argument_list[2].integer_reference;
10118           if (attribute_flag[3] != 0)
10119             geometry.x=argument_list[3].integer_reference;
10120           if (attribute_flag[4] != 0)
10121             geometry.y=argument_list[4].integer_reference;
10122           if (attribute_flag[5] != 0)
10123             image->fuzz=StringToDoubleInterval(
10124               argument_list[5].string_reference,(double) QuantumRange+1.0);
10125           if (attribute_flag[6] != 0)
10126             (void) QueryColorCompliance(argument_list[6].string_reference,
10127               AllCompliance,&image->background_color,exception);
10128           image=SpliceImage(image,&geometry,exception);
10129           break;
10130         }
10131         case 88:  /* Posterize */
10132         {
10133           if (attribute_flag[0] == 0)
10134             argument_list[0].integer_reference=3;
10135           if (attribute_flag[1] == 0)
10136             argument_list[1].integer_reference=0;
10137           (void) PosterizeImage(image,argument_list[0].integer_reference,
10138             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10139             NoDitherMethod,exception);
10140           break;
10141         }
10142         case 89:  /* Shadow */
10143         {
10144           if (attribute_flag[0] != 0)
10145             {
10146               flags=ParseGeometry(argument_list[0].string_reference,
10147                 &geometry_info);
10148               if ((flags & SigmaValue) == 0)
10149                 geometry_info.sigma=1.0;
10150               if ((flags & XiValue) == 0)
10151                 geometry_info.xi=4.0;
10152               if ((flags & PsiValue) == 0)
10153                 geometry_info.psi=4.0;
10154             }
10155           if (attribute_flag[1] != 0)
10156             geometry_info.rho=argument_list[1].real_reference;
10157           if (attribute_flag[2] != 0)
10158             geometry_info.sigma=argument_list[2].real_reference;
10159           if (attribute_flag[3] != 0)
10160             geometry_info.xi=argument_list[3].integer_reference;
10161           if (attribute_flag[4] != 0)
10162             geometry_info.psi=argument_list[4].integer_reference;
10163           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10164             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10165             ceil(geometry_info.psi-0.5),exception);
10166           break;
10167         }
10168         case 90:  /* Identify */
10169         {
10170           if (attribute_flag[0] == 0)
10171             argument_list[0].file_reference=(FILE *) NULL;
10172           if (attribute_flag[1] != 0)
10173             (void) SetImageArtifact(image,"identify:features",
10174               argument_list[1].string_reference);
10175           if ((attribute_flag[2] != 0) &&
10176               (argument_list[2].integer_reference != 0))
10177             (void) SetImageArtifact(image,"identify:unique","true");
10178           (void) IdentifyImage(image,argument_list[0].file_reference,
10179             MagickTrue,exception);
10180           break;
10181         }
10182         case 91:  /* SepiaTone */
10183         {
10184           if (attribute_flag[0] == 0)
10185             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10186           image=SepiaToneImage(image,argument_list[0].real_reference,
10187             exception);
10188           break;
10189         }
10190         case 92:  /* SigmoidalContrast */
10191         {
10192           MagickBooleanType
10193             sharpen;
10194
10195           if (attribute_flag[0] != 0)
10196             {
10197               flags=ParseGeometry(argument_list[0].string_reference,
10198                 &geometry_info);
10199               if ((flags & SigmaValue) == 0)
10200                 geometry_info.sigma=QuantumRange/2.0;
10201               if ((flags & PercentValue) != 0)
10202                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10203             }
10204           if (attribute_flag[1] != 0)
10205             geometry_info.rho=argument_list[1].real_reference;
10206           if (attribute_flag[2] != 0)
10207             geometry_info.sigma=argument_list[2].real_reference;
10208           if (attribute_flag[3] != 0)
10209             channel=(ChannelType) argument_list[3].integer_reference;
10210           sharpen=MagickTrue;
10211           if (attribute_flag[4] != 0)
10212             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10213               MagickFalse;
10214           channel_mask=SetImageChannelMask(image,channel);
10215           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10216             geometry_info.sigma,exception);
10217           (void) SetImageChannelMask(image,channel_mask);
10218           break;
10219         }
10220         case 93:  /* Extent */
10221         {
10222           if (attribute_flag[7] != 0)
10223             image->gravity=(GravityType) argument_list[7].integer_reference;
10224           if (attribute_flag[0] != 0)
10225             {
10226               int
10227                 flags;
10228
10229               flags=ParseGravityGeometry(image,
10230                 argument_list[0].string_reference,&geometry,exception);
10231               (void) flags;
10232               if (geometry.width == 0)
10233                 geometry.width=image->columns;
10234               if (geometry.height == 0)
10235                 geometry.height=image->rows;
10236             }
10237           if (attribute_flag[1] != 0)
10238             geometry.width=argument_list[1].integer_reference;
10239           if (attribute_flag[2] != 0)
10240             geometry.height=argument_list[2].integer_reference;
10241           if (attribute_flag[3] != 0)
10242             geometry.x=argument_list[3].integer_reference;
10243           if (attribute_flag[4] != 0)
10244             geometry.y=argument_list[4].integer_reference;
10245           if (attribute_flag[5] != 0)
10246             image->fuzz=StringToDoubleInterval(
10247               argument_list[5].string_reference,(double) QuantumRange+1.0);
10248           if (attribute_flag[6] != 0)
10249             (void) QueryColorCompliance(argument_list[6].string_reference,
10250               AllCompliance,&image->background_color,exception);
10251           image=ExtentImage(image,&geometry,exception);
10252           break;
10253         }
10254         case 94:  /* Vignette */
10255         {
10256           if (attribute_flag[0] != 0)
10257             {
10258               flags=ParseGeometry(argument_list[0].string_reference,
10259                 &geometry_info);
10260               if ((flags & SigmaValue) == 0)
10261                 geometry_info.sigma=1.0;
10262               if ((flags & XiValue) == 0)
10263                 geometry_info.xi=0.1*image->columns;
10264               if ((flags & PsiValue) == 0)
10265                 geometry_info.psi=0.1*image->rows;
10266             }
10267           if (attribute_flag[1] != 0)
10268             geometry_info.rho=argument_list[1].real_reference;
10269           if (attribute_flag[2] != 0)
10270             geometry_info.sigma=argument_list[2].real_reference;
10271           if (attribute_flag[3] != 0)
10272             geometry_info.xi=argument_list[3].integer_reference;
10273           if (attribute_flag[4] != 0)
10274             geometry_info.psi=argument_list[4].integer_reference;
10275           if (attribute_flag[5] != 0)
10276             (void) QueryColorCompliance(argument_list[5].string_reference,
10277               AllCompliance,&image->background_color,exception);
10278           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10279             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10280             ceil(geometry_info.psi-0.5),exception);
10281           break;
10282         }
10283         case 95:  /* ContrastStretch */
10284         {
10285           double
10286             black_point,
10287             white_point;
10288
10289           black_point=0.0;
10290           white_point=(double) image->columns*image->rows;
10291           if (attribute_flag[0] != 0)
10292             {
10293               flags=ParseGeometry(argument_list[0].string_reference,
10294                 &geometry_info);
10295               black_point=geometry_info.rho;
10296               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10297                 black_point;
10298               if ((flags & PercentValue) != 0)
10299                 {
10300                   black_point*=(double) image->columns*image->rows/100.0;
10301                   white_point*=(double) image->columns*image->rows/100.0;
10302                 }
10303               white_point=(double) image->columns*image->rows-
10304                 white_point;
10305             }
10306           if (attribute_flag[1] != 0)
10307             black_point=argument_list[1].real_reference;
10308           if (attribute_flag[2] != 0)
10309             white_point=argument_list[2].real_reference;
10310           if (attribute_flag[4] != 0)
10311             channel=(ChannelType) argument_list[4].integer_reference;
10312           channel_mask=SetImageChannelMask(image,channel);
10313           (void) ContrastStretchImage(image,black_point,white_point,exception);
10314           (void) SetImageChannelMask(image,channel_mask);
10315           break;
10316         }
10317         case 96:  /* Sans0 */
10318         {
10319           break;
10320         }
10321         case 97:  /* Sans1 */
10322         {
10323           break;
10324         }
10325         case 98:  /* AdaptiveSharpen */
10326         {
10327           if (attribute_flag[0] != 0)
10328             {
10329               flags=ParseGeometry(argument_list[0].string_reference,
10330                 &geometry_info);
10331               if ((flags & SigmaValue) == 0)
10332                 geometry_info.sigma=1.0;
10333               if ((flags & XiValue) == 0)
10334                 geometry_info.xi=0.0;
10335             }
10336           if (attribute_flag[1] != 0)
10337             geometry_info.rho=argument_list[1].real_reference;
10338           if (attribute_flag[2] != 0)
10339             geometry_info.sigma=argument_list[2].real_reference;
10340           if (attribute_flag[3] != 0)
10341             geometry_info.xi=argument_list[3].real_reference;
10342           if (attribute_flag[4] != 0)
10343             channel=(ChannelType) argument_list[4].integer_reference;
10344           channel_mask=SetImageChannelMask(image,channel);
10345           image=AdaptiveSharpenImage(image,geometry_info.rho,
10346             geometry_info.sigma,exception);
10347           if (image != (Image *) NULL)
10348             (void) SetImageChannelMask(image,channel_mask);
10349           break;
10350         }
10351         case 99:  /* Transpose */
10352         {
10353           image=TransposeImage(image,exception);
10354           break;
10355         }
10356         case 100:  /* Tranverse */
10357         {
10358           image=TransverseImage(image,exception);
10359           break;
10360         }
10361         case 101:  /* AutoOrient */
10362         {
10363           image=AutoOrientImage(image,image->orientation,exception);
10364           break;
10365         }
10366         case 102:  /* AdaptiveBlur */
10367         {
10368           if (attribute_flag[0] != 0)
10369             {
10370               flags=ParseGeometry(argument_list[0].string_reference,
10371                 &geometry_info);
10372               if ((flags & SigmaValue) == 0)
10373                 geometry_info.sigma=1.0;
10374               if ((flags & XiValue) == 0)
10375                 geometry_info.xi=0.0;
10376             }
10377           if (attribute_flag[1] != 0)
10378             geometry_info.rho=argument_list[1].real_reference;
10379           if (attribute_flag[2] != 0)
10380             geometry_info.sigma=argument_list[2].real_reference;
10381           if (attribute_flag[3] != 0)
10382             channel=(ChannelType) argument_list[3].integer_reference;
10383           channel_mask=SetImageChannelMask(image,channel);
10384           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10385             exception);
10386           if (image != (Image *) NULL)
10387             (void) SetImageChannelMask(image,channel_mask);
10388           break;
10389         }
10390         case 103:  /* Sketch */
10391         {
10392           if (attribute_flag[0] != 0)
10393             {
10394               flags=ParseGeometry(argument_list[0].string_reference,
10395                 &geometry_info);
10396               if ((flags & SigmaValue) == 0)
10397                 geometry_info.sigma=1.0;
10398               if ((flags & XiValue) == 0)
10399                 geometry_info.xi=1.0;
10400             }
10401           if (attribute_flag[1] != 0)
10402             geometry_info.rho=argument_list[1].real_reference;
10403           if (attribute_flag[2] != 0)
10404             geometry_info.sigma=argument_list[2].real_reference;
10405           if (attribute_flag[3] != 0)
10406             geometry_info.xi=argument_list[3].real_reference;
10407           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10408             geometry_info.xi,exception);
10409           break;
10410         }
10411         case 104:  /* UniqueColors */
10412         {
10413           image=UniqueImageColors(image,exception);
10414           break;
10415         }
10416         case 105:  /* AdaptiveResize */
10417         {
10418           if (attribute_flag[0] != 0)
10419             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10420               &geometry,exception);
10421           if (attribute_flag[1] != 0)
10422             geometry.width=argument_list[1].integer_reference;
10423           if (attribute_flag[2] != 0)
10424             geometry.height=argument_list[2].integer_reference;
10425           if (attribute_flag[3] != 0)
10426             image->filter=(FilterTypes) argument_list[4].integer_reference;
10427           if (attribute_flag[4] != 0)
10428             SetImageArtifact(image,"filter:support",
10429               argument_list[4].string_reference);
10430           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10431             exception);
10432           break;
10433         }
10434         case 106:  /* ClipMask */
10435         {
10436           Image
10437             *mask_image;
10438
10439           if (attribute_flag[0] == 0)
10440             {
10441               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10442                 PackageName);
10443               goto PerlException;
10444             }
10445           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10446             exception);
10447           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10448           mask_image=DestroyImage(mask_image);
10449           break;
10450         }
10451         case 107:  /* LinearStretch */
10452         {
10453            double
10454              black_point,
10455              white_point;
10456
10457            black_point=0.0;
10458            white_point=(double) image->columns*image->rows;
10459            if (attribute_flag[0] != 0)
10460              {
10461                flags=ParseGeometry(argument_list[0].string_reference,
10462                  &geometry_info);
10463                if ((flags & SigmaValue) != 0)
10464                   white_point=geometry_info.sigma;
10465                if ((flags & PercentValue) != 0)
10466                  {
10467                    black_point*=(double) image->columns*image->rows/100.0;
10468                    white_point*=(double) image->columns*image->rows/100.0;
10469                  }
10470                if ((flags & SigmaValue) == 0)
10471                  white_point=(double) image->columns*image->rows-black_point;
10472              }
10473           if (attribute_flag[1] != 0)
10474             black_point=argument_list[1].real_reference;
10475           if (attribute_flag[2] != 0)
10476             white_point=argument_list[2].real_reference;
10477           (void) LinearStretchImage(image,black_point,white_point,exception);
10478           break;
10479         }
10480         case 108:  /* ColorMatrix */
10481         {
10482           AV
10483             *av;
10484
10485           double
10486             *color_matrix;
10487
10488           KernelInfo
10489             *kernel_info;
10490
10491           size_t
10492             order;
10493
10494           if (attribute_flag[0] == 0)
10495             break;
10496           av=(AV *) argument_list[0].array_reference;
10497           order=(size_t) sqrt(av_len(av)+1);
10498           color_matrix=(double *) AcquireQuantumMemory(order,order*
10499             sizeof(*color_matrix));
10500           if (color_matrix == (double *) NULL)
10501             {
10502               ThrowPerlException(exception,ResourceLimitFatalError,
10503                 "MemoryAllocationFailed",PackageName);
10504               goto PerlException;
10505            }
10506           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10507             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10508           for ( ; j < (ssize_t) (order*order); j++)
10509             color_matrix[j]=0.0;
10510           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10511           if (kernel_info == (KernelInfo *) NULL)
10512             break;
10513           kernel_info->width=order;
10514           kernel_info->height=order;
10515           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10516             order*sizeof(*kernel_info->values));
10517           if (kernel_info->values != (MagickRealType *) NULL)
10518             {
10519               for (i=0; i < (ssize_t) (order*order); i++)
10520                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10521               image=ColorMatrixImage(image,kernel_info,exception);
10522             }
10523           kernel_info=DestroyKernelInfo(kernel_info);
10524           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10525           break;
10526         }
10527         case 109:  /* Mask */
10528         {
10529           Image
10530             *mask_image;
10531
10532           if (attribute_flag[0] == 0)
10533             {
10534               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10535                 PackageName);
10536               goto PerlException;
10537             }
10538           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10539             MagickTrue,exception);
10540           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10541           mask_image=DestroyImage(mask_image);
10542           break;
10543         }
10544         case 110:  /* Polaroid */
10545         {
10546           char
10547             *caption;
10548
10549           DrawInfo
10550             *draw_info;
10551
10552           double
10553             angle;
10554
10555           PixelInterpolateMethod
10556             method;
10557
10558           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10559             (DrawInfo *) NULL);
10560           caption=(char *) NULL;
10561           if (attribute_flag[0] != 0)
10562             caption=InterpretImageProperties(info ? info->image_info :
10563               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10564               exception);
10565           angle=0.0;
10566           if (attribute_flag[1] != 0)
10567             angle=argument_list[1].real_reference;
10568           if (attribute_flag[2] != 0)
10569             (void) CloneString(&draw_info->font,
10570               argument_list[2].string_reference);
10571           if (attribute_flag[3] != 0)
10572             (void) QueryColorCompliance(argument_list[3].string_reference,
10573               AllCompliance,&draw_info->stroke,exception);
10574           if (attribute_flag[4] != 0)
10575             (void) QueryColorCompliance(argument_list[4].string_reference,
10576               AllCompliance,&draw_info->fill,exception);
10577           if (attribute_flag[5] != 0)
10578             draw_info->stroke_width=argument_list[5].real_reference;
10579           if (attribute_flag[6] != 0)
10580             draw_info->pointsize=argument_list[6].real_reference;
10581           if (attribute_flag[7] != 0)
10582             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10583           if (attribute_flag[8] != 0)
10584             (void) QueryColorCompliance(argument_list[8].string_reference,
10585               AllCompliance,&image->background_color,exception);
10586           method=UndefinedInterpolatePixel;
10587           if (attribute_flag[9] != 0)
10588             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10589           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10590           draw_info=DestroyDrawInfo(draw_info);
10591           if (caption != (char *) NULL)
10592             caption=DestroyString(caption);
10593           break;
10594         }
10595         case 111:  /* FloodfillPaint */
10596         {
10597           DrawInfo
10598             *draw_info;
10599
10600           MagickBooleanType
10601             invert;
10602
10603           PixelInfo
10604             target;
10605
10606           draw_info=CloneDrawInfo(info ? info->image_info :
10607             (ImageInfo *) NULL,(DrawInfo *) NULL);
10608           if (attribute_flag[0] != 0)
10609             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10610               &geometry,exception);
10611           if (attribute_flag[1] != 0)
10612             geometry.x=argument_list[1].integer_reference;
10613           if (attribute_flag[2] != 0)
10614             geometry.y=argument_list[2].integer_reference;
10615           if (attribute_flag[3] != 0)
10616             (void) QueryColorCompliance(argument_list[3].string_reference,
10617               AllCompliance,&draw_info->fill,exception);
10618           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10619             geometry.x,geometry.y,&target,exception);
10620           if (attribute_flag[4] != 0)
10621             QueryColorCompliance(argument_list[4].string_reference,
10622               AllCompliance,&target,exception);
10623           if (attribute_flag[5] != 0)
10624             image->fuzz=StringToDoubleInterval(
10625               argument_list[5].string_reference,(double) QuantumRange+1.0);
10626           if (attribute_flag[6] != 0)
10627             channel=(ChannelType) argument_list[6].integer_reference;
10628           invert=MagickFalse;
10629           if (attribute_flag[7] != 0)
10630             invert=(MagickBooleanType) argument_list[7].integer_reference;
10631           channel_mask=SetImageChannelMask(image,channel);
10632           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10633             geometry.y,invert,exception);
10634           (void) SetImageChannelMask(image,channel_mask);
10635           draw_info=DestroyDrawInfo(draw_info);
10636           break;
10637         }
10638         case 112:  /* Distort */
10639         {
10640           AV
10641             *av;
10642
10643           double
10644             *coordinates;
10645
10646           DistortImageMethod
10647             method;
10648
10649           size_t
10650             number_coordinates;
10651
10652           VirtualPixelMethod
10653             virtual_pixel;
10654
10655           if (attribute_flag[0] == 0)
10656             break;
10657           method=UndefinedDistortion;
10658           if (attribute_flag[1] != 0)
10659             method=(DistortImageMethod) argument_list[1].integer_reference;
10660           av=(AV *) argument_list[0].array_reference;
10661           number_coordinates=(size_t) av_len(av)+1;
10662           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10663             sizeof(*coordinates));
10664           if (coordinates == (double *) NULL)
10665             {
10666               ThrowPerlException(exception,ResourceLimitFatalError,
10667                 "MemoryAllocationFailed",PackageName);
10668               goto PerlException;
10669             }
10670           for (j=0; j < (ssize_t) number_coordinates; j++)
10671             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10672           virtual_pixel=UndefinedVirtualPixelMethod;
10673           if (attribute_flag[2] != 0)
10674             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10675               argument_list[2].integer_reference,exception);
10676           image=DistortImage(image,method,number_coordinates,coordinates,
10677             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10678             exception);
10679           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10680             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10681               exception);
10682           coordinates=(double *) RelinquishMagickMemory(coordinates);
10683           break;
10684         }
10685         case 113:  /* Clut */
10686         {
10687           PixelInterpolateMethod
10688             method;
10689
10690           if (attribute_flag[0] == 0)
10691             {
10692               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10693                 PackageName);
10694               goto PerlException;
10695             }
10696           method=UndefinedInterpolatePixel;
10697           if (attribute_flag[1] != 0)
10698             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10699           if (attribute_flag[2] != 0)
10700             channel=(ChannelType) argument_list[2].integer_reference;
10701           channel_mask=SetImageChannelMask(image,channel);
10702           (void) ClutImage(image,argument_list[0].image_reference,method,
10703             exception);
10704           (void) SetImageChannelMask(image,channel_mask);
10705           break;
10706         }
10707         case 114:  /* LiquidRescale */
10708         {
10709           if (attribute_flag[0] != 0)
10710             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10711               &geometry,exception);
10712           if (attribute_flag[1] != 0)
10713             geometry.width=argument_list[1].integer_reference;
10714           if (attribute_flag[2] != 0)
10715             geometry.height=argument_list[2].integer_reference;
10716           if (attribute_flag[3] == 0)
10717             argument_list[3].real_reference=1.0;
10718           if (attribute_flag[4] == 0)
10719             argument_list[4].real_reference=0.0;
10720           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10721             argument_list[3].real_reference,argument_list[4].real_reference,
10722             exception);
10723           break;
10724         }
10725         case 115:  /* EncipherImage */
10726         {
10727           (void) EncipherImage(image,argument_list[0].string_reference,
10728             exception);
10729           break;
10730         }
10731         case 116:  /* DecipherImage */
10732         {
10733           (void) DecipherImage(image,argument_list[0].string_reference,
10734             exception);
10735           break;
10736         }
10737         case 117:  /* Deskew */
10738         {
10739           geometry_info.rho=QuantumRange/2.0;
10740           if (attribute_flag[0] != 0)
10741             flags=ParseGeometry(argument_list[0].string_reference,
10742               &geometry_info);
10743           if (attribute_flag[1] != 0)
10744             geometry_info.rho=StringToDoubleInterval(
10745               argument_list[1].string_reference,(double) QuantumRange+1.0);
10746           image=DeskewImage(image,geometry_info.rho,exception);
10747           break;
10748         }
10749         case 118:  /* Remap */
10750         {
10751           QuantizeInfo
10752             *quantize_info;
10753
10754           if (attribute_flag[0] == 0)
10755             {
10756               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10757                 PackageName);
10758               goto PerlException;
10759             }
10760           quantize_info=AcquireQuantizeInfo(info->image_info);
10761           if (attribute_flag[1] != 0)
10762             quantize_info->dither_method=(DitherMethod)
10763               argument_list[1].integer_reference;
10764           (void) RemapImages(quantize_info,image,
10765             argument_list[0].image_reference,exception);
10766           quantize_info=DestroyQuantizeInfo(quantize_info);
10767           break;
10768         }
10769         case 119:  /* SparseColor */
10770         {
10771           AV
10772             *av;
10773
10774           double
10775             *coordinates;
10776
10777           SparseColorMethod
10778             method;
10779
10780           size_t
10781             number_coordinates;
10782
10783           VirtualPixelMethod
10784             virtual_pixel;
10785
10786           if (attribute_flag[0] == 0)
10787             break;
10788           method=UndefinedColorInterpolate;
10789           if (attribute_flag[1] != 0)
10790             method=(SparseColorMethod) argument_list[1].integer_reference;
10791           av=(AV *) argument_list[0].array_reference;
10792           number_coordinates=(size_t) av_len(av)+1;
10793           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10794             sizeof(*coordinates));
10795           if (coordinates == (double *) NULL)
10796             {
10797               ThrowPerlException(exception,ResourceLimitFatalError,
10798                 "MemoryAllocationFailed",PackageName);
10799               goto PerlException;
10800             }
10801           for (j=0; j < (ssize_t) number_coordinates; j++)
10802             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10803           virtual_pixel=UndefinedVirtualPixelMethod;
10804           if (attribute_flag[2] != 0)
10805             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10806               argument_list[2].integer_reference,exception);
10807           if (attribute_flag[3] != 0)
10808             channel=(ChannelType) argument_list[3].integer_reference;
10809           channel_mask=SetImageChannelMask(image,channel);
10810           image=SparseColorImage(image,method,number_coordinates,coordinates,
10811             exception);
10812           if (image != (Image *) NULL)
10813             (void) SetImageChannelMask(image,channel_mask);
10814           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10815             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10816               exception);
10817           coordinates=(double *) RelinquishMagickMemory(coordinates);
10818           break;
10819         }
10820         case 120:  /* Function */
10821         {
10822           AV
10823             *av;
10824
10825           double
10826             *parameters;
10827
10828           MagickFunction
10829             function;
10830
10831           size_t
10832             number_parameters;
10833
10834           VirtualPixelMethod
10835             virtual_pixel;
10836
10837           if (attribute_flag[0] == 0)
10838             break;
10839           function=UndefinedFunction;
10840           if (attribute_flag[1] != 0)
10841             function=(MagickFunction) argument_list[1].integer_reference;
10842           av=(AV *) argument_list[0].array_reference;
10843           number_parameters=(size_t) av_len(av)+1;
10844           parameters=(double *) AcquireQuantumMemory(number_parameters,
10845             sizeof(*parameters));
10846           if (parameters == (double *) NULL)
10847             {
10848               ThrowPerlException(exception,ResourceLimitFatalError,
10849                 "MemoryAllocationFailed",PackageName);
10850               goto PerlException;
10851             }
10852           for (j=0; j < (ssize_t) number_parameters; j++)
10853             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10854           virtual_pixel=UndefinedVirtualPixelMethod;
10855           if (attribute_flag[2] != 0)
10856             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10857               argument_list[2].integer_reference,exception);
10858           (void) FunctionImage(image,function,number_parameters,parameters,
10859             exception);
10860           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10861             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10862               exception);
10863           parameters=(double *) RelinquishMagickMemory(parameters);
10864           break;
10865         }
10866         case 121:  /* SelectiveBlur */
10867         {
10868           if (attribute_flag[0] != 0)
10869             {
10870               flags=ParseGeometry(argument_list[0].string_reference,
10871                 &geometry_info);
10872               if ((flags & SigmaValue) == 0)
10873                 geometry_info.sigma=1.0;
10874               if ((flags & PercentValue) != 0)
10875                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10876             }
10877           if (attribute_flag[1] != 0)
10878             geometry_info.rho=argument_list[1].real_reference;
10879           if (attribute_flag[2] != 0)
10880             geometry_info.sigma=argument_list[2].real_reference;
10881           if (attribute_flag[3] != 0)
10882             geometry_info.xi=argument_list[3].integer_reference;;
10883           if (attribute_flag[5] != 0)
10884             channel=(ChannelType) argument_list[5].integer_reference;
10885           channel_mask=SetImageChannelMask(image,channel);
10886           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10887             geometry_info.xi,exception);
10888           if (image != (Image *) NULL)
10889             (void) SetImageChannelMask(image,channel_mask);
10890           break;
10891         }
10892         case 122:  /* HaldClut */
10893         {
10894           if (attribute_flag[0] == 0)
10895             {
10896               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10897                 PackageName);
10898               goto PerlException;
10899             }
10900           if (attribute_flag[1] != 0)
10901             channel=(ChannelType) argument_list[1].integer_reference;
10902           channel_mask=SetImageChannelMask(image,channel);
10903           (void) HaldClutImage(image,argument_list[0].image_reference,
10904             exception);
10905           (void) SetImageChannelMask(image,channel_mask);
10906           break;
10907         }
10908         case 123:  /* BlueShift */
10909         {
10910           if (attribute_flag[0] != 0)
10911             (void) ParseGeometry(argument_list[0].string_reference,
10912               &geometry_info);
10913           image=BlueShiftImage(image,geometry_info.rho,exception);
10914           break;
10915         }
10916         case 124:  /* ForwardFourierTransformImage */
10917         {
10918           image=ForwardFourierTransformImage(image,
10919             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10920             exception);
10921           break;
10922         }
10923         case 125:  /* InverseFourierTransformImage */
10924         {
10925           image=InverseFourierTransformImage(image,image->next,
10926             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10927             exception);
10928           break;
10929         }
10930         case 126:  /* ColorDecisionList */
10931         {
10932           if (attribute_flag[0] == 0)
10933             argument_list[0].string_reference=(char *) NULL;
10934           (void) ColorDecisionListImage(image,
10935             argument_list[0].string_reference,exception);
10936           break;
10937         }
10938         case 127:  /* AutoGamma */
10939         {
10940           if (attribute_flag[0] != 0)
10941             channel=(ChannelType) argument_list[0].integer_reference;
10942           channel_mask=SetImageChannelMask(image,channel);
10943           (void) AutoGammaImage(image,exception);
10944           (void) SetImageChannelMask(image,channel_mask);
10945           break;
10946         }
10947         case 128:  /* AutoLevel */
10948         {
10949           if (attribute_flag[0] != 0)
10950             channel=(ChannelType) argument_list[0].integer_reference;
10951           channel_mask=SetImageChannelMask(image,channel);
10952           (void) AutoLevelImage(image,exception);
10953           (void) SetImageChannelMask(image,channel_mask);
10954           break;
10955         }
10956         case 129:  /* LevelColors */
10957         {
10958           PixelInfo
10959             black_point,
10960             white_point;
10961
10962           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10963             exception);
10964           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10965             exception);
10966           if (attribute_flag[1] != 0)
10967              (void) QueryColorCompliance(
10968                argument_list[1].string_reference,AllCompliance,&black_point,
10969                exception);
10970           if (attribute_flag[2] != 0)
10971              (void) QueryColorCompliance(
10972                argument_list[2].string_reference,AllCompliance,&white_point,
10973                exception);
10974           if (attribute_flag[3] != 0)
10975             channel=(ChannelType) argument_list[3].integer_reference;
10976           channel_mask=SetImageChannelMask(image,channel);
10977           (void) LevelImageColors(image,&black_point,&white_point,
10978             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10979             exception);
10980           (void) SetImageChannelMask(image,channel_mask);
10981           break;
10982         }
10983         case 130:  /* Clamp */
10984         {
10985           if (attribute_flag[0] != 0)
10986             channel=(ChannelType) argument_list[0].integer_reference;
10987           channel_mask=SetImageChannelMask(image,channel);
10988           (void) ClampImage(image,exception);
10989           (void) SetImageChannelMask(image,channel_mask);
10990           break;
10991         }
10992         case 131:  /* BrightnessContrast */
10993         {
10994           double
10995             brightness,
10996             contrast;
10997
10998           brightness=0.0;
10999           contrast=0.0;
11000           if (attribute_flag[0] != 0)
11001             {
11002               flags=ParseGeometry(argument_list[0].string_reference,
11003                 &geometry_info);
11004               brightness=geometry_info.rho;
11005               if ((flags & SigmaValue) == 0)
11006                 contrast=geometry_info.sigma;
11007             }
11008           if (attribute_flag[1] != 0)
11009             brightness=argument_list[1].real_reference;
11010           if (attribute_flag[2] != 0)
11011             contrast=argument_list[2].real_reference;
11012           if (attribute_flag[4] != 0)
11013             channel=(ChannelType) argument_list[4].integer_reference;
11014           channel_mask=SetImageChannelMask(image,channel);
11015           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11016           (void) SetImageChannelMask(image,channel_mask);
11017           break;
11018         }
11019         case 132:  /* Morphology */
11020         {
11021           KernelInfo
11022             *kernel;
11023
11024           MorphologyMethod
11025             method;
11026
11027           ssize_t
11028             iterations;
11029
11030           if (attribute_flag[0] == 0)
11031             break;
11032           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11033           if (kernel == (KernelInfo *) NULL)
11034             break;
11035           if (attribute_flag[1] != 0)
11036             channel=(ChannelType) argument_list[1].integer_reference;
11037           method=UndefinedMorphology;
11038           if (attribute_flag[2] != 0)
11039             method=argument_list[2].integer_reference;
11040           iterations=1;
11041           if (attribute_flag[3] != 0)
11042             iterations=argument_list[3].integer_reference;
11043           channel_mask=SetImageChannelMask(image,channel);
11044           image=MorphologyImage(image,method,iterations,kernel,exception);
11045           if (image != (Image *) NULL)
11046             (void) SetImageChannelMask(image,channel_mask);
11047           kernel=DestroyKernelInfo(kernel);
11048           break;
11049         }
11050         case 133:  /* Mode */
11051         {
11052           if (attribute_flag[0] != 0)
11053             {
11054               flags=ParseGeometry(argument_list[0].string_reference,
11055                 &geometry_info);
11056               if ((flags & SigmaValue) == 0)
11057                 geometry_info.sigma=1.0;
11058             }
11059           if (attribute_flag[1] != 0)
11060             geometry_info.rho=argument_list[1].real_reference;
11061           if (attribute_flag[2] != 0)
11062             geometry_info.sigma=argument_list[2].real_reference;
11063           if (attribute_flag[3] != 0)
11064             channel=(ChannelType) argument_list[3].integer_reference;
11065           channel_mask=SetImageChannelMask(image,channel);
11066           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11067             (size_t) geometry_info.sigma,exception);
11068           if (image != (Image *) NULL)
11069             (void) SetImageChannelMask(image,channel_mask);
11070           break;
11071         }
11072         case 134:  /* Statistic */
11073         {
11074           StatisticType
11075             statistic;
11076
11077           statistic=UndefinedStatistic;
11078           if (attribute_flag[0] != 0)
11079             {
11080               flags=ParseGeometry(argument_list[0].string_reference,
11081                 &geometry_info);
11082               if ((flags & SigmaValue) == 0)
11083                 geometry_info.sigma=1.0;
11084             }
11085           if (attribute_flag[1] != 0)
11086             geometry_info.rho=argument_list[1].real_reference;
11087           if (attribute_flag[2] != 0)
11088             geometry_info.sigma=argument_list[2].real_reference;
11089           if (attribute_flag[3] != 0)
11090             channel=(ChannelType) argument_list[3].integer_reference;
11091           if (attribute_flag[4] != 0)
11092             statistic=(StatisticType) argument_list[4].integer_reference;
11093           channel_mask=SetImageChannelMask(image,channel);
11094           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11095             (size_t) geometry_info.sigma,exception);
11096           if (image != (Image *) NULL)
11097             (void) SetImageChannelMask(image,channel_mask);
11098           break;
11099         }
11100         case 135:  /* Perceptible */
11101         {
11102           double
11103             epsilon;
11104
11105           epsilon=MagickEpsilon;
11106           if (attribute_flag[0] != 0)
11107             epsilon=argument_list[0].real_reference;
11108           if (attribute_flag[1] != 0)
11109             channel=(ChannelType) argument_list[1].integer_reference;
11110           channel_mask=SetImageChannelMask(image,channel);
11111           (void) PerceptibleImage(image,epsilon,exception);
11112           (void) SetImageChannelMask(image,channel_mask);
11113           break;
11114         }
11115         case 136:  /* Poly */
11116         {
11117           AV
11118             *av;
11119
11120           double
11121             *terms;
11122
11123           size_t
11124             number_terms;
11125
11126           if (attribute_flag[0] == 0)
11127             break;
11128           if (attribute_flag[1] != 0)
11129             channel=(ChannelType) argument_list[1].integer_reference;
11130           av=(AV *) argument_list[0].array_reference;
11131           number_terms=(size_t) av_len(av);
11132           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11133           if (terms == (double *) NULL)
11134             {
11135               ThrowPerlException(exception,ResourceLimitFatalError,
11136                 "MemoryAllocationFailed",PackageName);
11137               goto PerlException;
11138             }
11139           for (j=0; j < av_len(av); j++)
11140             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11141           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11142           terms=(double *) RelinquishMagickMemory(terms);
11143           break;
11144         }
11145         case 137:  /* Grayscale */
11146         {
11147           PixelIntensityMethod
11148             method;
11149
11150           method=UndefinedPixelIntensityMethod;
11151           if (attribute_flag[0] != 0)
11152             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11153           (void) GrayscaleImage(image,method,exception);
11154           break;
11155         }
11156         case 138:  /* Canny */
11157         {
11158           if (attribute_flag[0] != 0)
11159             {
11160               flags=ParseGeometry(argument_list[0].string_reference,
11161                 &geometry_info);
11162               if ((flags & SigmaValue) == 0)
11163                 geometry_info.sigma=1.0;
11164               if ((flags & XiValue) == 0)
11165                 geometry_info.xi=0.10;
11166               if ((flags & PsiValue) == 0)
11167                 geometry_info.psi=0.30;
11168               if ((flags & PercentValue) != 0)
11169                 {
11170                   geometry_info.xi/=100.0;
11171                   geometry_info.psi/=100.0;
11172                 }
11173             }
11174           if (attribute_flag[1] != 0)
11175             geometry_info.rho=argument_list[1].real_reference;
11176           if (attribute_flag[2] != 0)
11177             geometry_info.sigma=argument_list[2].real_reference;
11178           if (attribute_flag[3] != 0)
11179             geometry_info.xi=argument_list[3].real_reference;
11180           if (attribute_flag[4] != 0)
11181             geometry_info.psi=argument_list[4].real_reference;
11182           if (attribute_flag[5] != 0)
11183             channel=(ChannelType) argument_list[5].integer_reference;
11184           channel_mask=SetImageChannelMask(image,channel);
11185           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11186             geometry_info.xi,geometry_info.psi,exception);
11187           if (image != (Image *) NULL)
11188             (void) SetImageChannelMask(image,channel_mask);
11189           break;
11190         }
11191         case 139:  /* HoughLine */
11192         {
11193           if (attribute_flag[0] != 0)
11194             {
11195               flags=ParseGeometry(argument_list[0].string_reference,
11196                 &geometry_info);
11197               if ((flags & SigmaValue) == 0)
11198                 geometry_info.sigma=geometry_info.rho;
11199               if ((flags & XiValue) == 0)
11200                 geometry_info.xi=40;
11201             }
11202           if (attribute_flag[1] != 0)
11203             geometry_info.rho=(double) argument_list[1].integer_reference;
11204           if (attribute_flag[2] != 0)
11205             geometry_info.sigma=(double) argument_list[2].integer_reference;
11206           if (attribute_flag[3] != 0)
11207             geometry_info.xi=(double) argument_list[3].integer_reference;
11208           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11209             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11210           break;
11211         }
11212         case 140:  /* MeanShift */
11213         {
11214           if (attribute_flag[0] != 0)
11215             {
11216               flags=ParseGeometry(argument_list[0].string_reference,
11217                 &geometry_info);
11218               if ((flags & SigmaValue) == 0)
11219                 geometry_info.sigma=geometry_info.rho;
11220               if ((flags & XiValue) == 0)
11221                 geometry_info.xi=0.10*QuantumRange;
11222               if ((flags & PercentValue) != 0)
11223                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11224             }
11225           if (attribute_flag[1] != 0)
11226             geometry_info.rho=(double) argument_list[1].integer_reference;
11227           if (attribute_flag[2] != 0)
11228             geometry_info.sigma=(double) argument_list[2].integer_reference;
11229           if (attribute_flag[3] != 0)
11230             geometry_info.xi=(double) argument_list[3].integer_reference;
11231           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11232             geometry_info.sigma,geometry_info.xi,exception);
11233           break;
11234         }
11235         case 141:  /* Kuwahara */
11236         {
11237           if (attribute_flag[0] != 0)
11238             {
11239               flags=ParseGeometry(argument_list[0].string_reference,
11240                 &geometry_info);
11241               if ((flags & SigmaValue) == 0)
11242                 geometry_info.sigma=geometry_info.rho-0.5;
11243             }
11244           if (attribute_flag[1] != 0)
11245             geometry_info.rho=argument_list[1].real_reference;
11246           if (attribute_flag[2] != 0)
11247             geometry_info.sigma=argument_list[2].real_reference;
11248           if (attribute_flag[3] != 0)
11249             channel=(ChannelType) argument_list[3].integer_reference;
11250           channel_mask=SetImageChannelMask(image,channel);
11251           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11252             exception);
11253           if (image != (Image *) NULL)
11254             (void) SetImageChannelMask(image,channel_mask);
11255           break;
11256         }
11257         case 142:  /* ConnectedComponent */
11258         {
11259           size_t
11260             connectivity;
11261
11262           connectivity=4;
11263           if (attribute_flag[0] != 0)
11264             connectivity=argument_list[0].integer_reference;
11265           image=ConnectedComponentsImage(image,connectivity,exception);
11266           break;
11267         }
11268         case 143:  /* Copy */
11269         {
11270           Image
11271             *source_image;
11272
11273           OffsetInfo
11274             offset;
11275
11276           RectangleInfo
11277             offset_geometry;
11278
11279           source_image=image;
11280           if (attribute_flag[0] != 0)
11281             source_image=argument_list[0].image_reference;
11282           SetGeometry(source_image,&geometry);
11283           if (attribute_flag[1] != 0)
11284             flags=ParseGravityGeometry(source_image,
11285               argument_list[1].string_reference,&geometry,exception);
11286           if (attribute_flag[2] != 0)
11287             geometry.width=argument_list[2].integer_reference;
11288           if (attribute_flag[3] != 0)
11289             geometry.height=argument_list[3].integer_reference;
11290           if (attribute_flag[4] != 0)
11291             geometry.x=argument_list[4].integer_reference;
11292           if (attribute_flag[5] != 0)
11293             geometry.y=argument_list[5].integer_reference;
11294           if (attribute_flag[6] != 0)
11295             image->gravity=(GravityType) argument_list[6].integer_reference;
11296           SetGeometry(image,&offset_geometry);
11297           if (attribute_flag[7] != 0)
11298             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11299               &offset_geometry,exception);
11300           offset.x=offset_geometry.x;
11301           offset.y=offset_geometry.y;
11302           if (attribute_flag[8] != 0)
11303             offset.x=argument_list[8].integer_reference;
11304           if (attribute_flag[9] != 0)
11305             offset.y=argument_list[9].integer_reference;
11306           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11307             exception);
11308           break;
11309         }
11310       }
11311       if (next != (Image *) NULL)
11312         (void) CatchImageException(next);
11313       if (region_image != (Image *) NULL)
11314         {
11315           /*
11316             Composite region.
11317           */
11318           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11319             region_info.x,region_info.y,exception);
11320           (void) status;
11321           (void) CatchImageException(region_image);
11322           image=DestroyImage(image);
11323           image=region_image;
11324         }
11325       if (image != (Image *) NULL)
11326         {
11327           number_images++;
11328           if (next && (next != image))
11329             {
11330               image->next=next->next;
11331               if (image->next != (Image *) NULL)
11332                 image->next->previous=image;
11333               DeleteImageFromRegistry(*pv,next);
11334             }
11335           sv_setiv(*pv,PTR2IV(image));
11336           next=image;
11337         }
11338       if (*pv)
11339         pv++;
11340     }
11341
11342   PerlException:
11343     if (reference_vector)
11344       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11345     InheritPerlException(exception,perl_exception);
11346     exception=DestroyExceptionInfo(exception);
11347     sv_setiv(perl_exception,(IV) number_images);
11348     SvPOK_on(perl_exception);
11349     ST(0)=sv_2mortal(perl_exception);
11350     XSRETURN(1);
11351   }
11352 \f
11353 #
11354 ###############################################################################
11355 #                                                                             #
11356 #                                                                             #
11357 #                                                                             #
11358 #   M o n t a g e                                                             #
11359 #                                                                             #
11360 #                                                                             #
11361 #                                                                             #
11362 ###############################################################################
11363 #
11364 #
11365 void
11366 Montage(ref,...)
11367   Image::Magick ref=NO_INIT
11368   ALIAS:
11369     MontageImage  = 1
11370     montage       = 2
11371     montageimage  = 3
11372   PPCODE:
11373   {
11374     AV
11375       *av;
11376
11377     char
11378       *attribute;
11379
11380     ExceptionInfo
11381       *exception;
11382
11383     HV
11384       *hv;
11385
11386     Image
11387       *image,
11388       *next;
11389
11390     PixelInfo
11391       transparent_color;
11392
11393     MontageInfo
11394       *montage_info;
11395
11396     register ssize_t
11397       i;
11398
11399     ssize_t
11400       sp;
11401
11402     struct PackageInfo
11403       *info;
11404
11405     SV
11406       *av_reference,
11407       *perl_exception,
11408       *reference,
11409       *rv,
11410       *sv;
11411
11412     PERL_UNUSED_VAR(ref);
11413     PERL_UNUSED_VAR(ix);
11414     exception=AcquireExceptionInfo();
11415     perl_exception=newSVpv("",0);
11416     sv=NULL;
11417     attribute=NULL;
11418     if (sv_isobject(ST(0)) == 0)
11419       {
11420         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11421           PackageName);
11422         goto PerlException;
11423       }
11424     reference=SvRV(ST(0));
11425     hv=SvSTASH(reference);
11426     av=newAV();
11427     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11428     SvREFCNT_dec(av);
11429     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11430     if (image == (Image *) NULL)
11431       {
11432         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11433           PackageName);
11434         goto PerlException;
11435       }
11436     /*
11437       Get options.
11438     */
11439     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11440     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11441     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11442       exception);
11443     for (i=2; i < items; i+=2)
11444     {
11445       attribute=(char *) SvPV(ST(i-1),na);
11446       switch (*attribute)
11447       {
11448         case 'B':
11449         case 'b':
11450         {
11451           if (LocaleCompare(attribute,"background") == 0)
11452             {
11453               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11454                 &montage_info->background_color,exception);
11455               for (next=image; next; next=next->next)
11456                 next->background_color=montage_info->background_color;
11457               break;
11458             }
11459           if (LocaleCompare(attribute,"border") == 0)
11460             {
11461               montage_info->border_width=SvIV(ST(i));
11462               break;
11463             }
11464           if (LocaleCompare(attribute,"bordercolor") == 0)
11465             {
11466               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11467                 &montage_info->border_color,exception);
11468               for (next=image; next; next=next->next)
11469                 next->border_color=montage_info->border_color;
11470               break;
11471             }
11472           if (LocaleCompare(attribute,"borderwidth") == 0)
11473             {
11474               montage_info->border_width=SvIV(ST(i));
11475               break;
11476             }
11477           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11478             attribute);
11479           break;
11480         }
11481         case 'C':
11482         case 'c':
11483         {
11484           if (LocaleCompare(attribute,"compose") == 0)
11485             {
11486               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11487                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11488               if (sp < 0)
11489                 {
11490                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11491                     SvPV(ST(i),na));
11492                   break;
11493                 }
11494               for (next=image; next; next=next->next)
11495                 next->compose=(CompositeOperator) sp;
11496               break;
11497             }
11498           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11499             attribute);
11500           break;
11501         }
11502         case 'F':
11503         case 'f':
11504         {
11505           if (LocaleCompare(attribute,"fill") == 0)
11506             {
11507               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11508                 &montage_info->fill,exception);
11509               break;
11510             }
11511           if (LocaleCompare(attribute,"font") == 0)
11512             {
11513               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11514               break;
11515             }
11516           if (LocaleCompare(attribute,"frame") == 0)
11517             {
11518               char
11519                 *p;
11520
11521               p=SvPV(ST(i),na);
11522               if (IsGeometry(p) == MagickFalse)
11523                 {
11524                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11525                     p);
11526                   break;
11527                 }
11528               (void) CloneString(&montage_info->frame,p);
11529               if (*p == '\0')
11530                 montage_info->frame=(char *) NULL;
11531               break;
11532             }
11533           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11534             attribute);
11535           break;
11536         }
11537         case 'G':
11538         case 'g':
11539         {
11540           if (LocaleCompare(attribute,"geometry") == 0)
11541             {
11542               char
11543                 *p;
11544
11545               p=SvPV(ST(i),na);
11546               if (IsGeometry(p) == MagickFalse)
11547                 {
11548                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11549                     p);
11550                   break;
11551                 }
11552              (void) CloneString(&montage_info->geometry,p);
11553              if (*p == '\0')
11554                montage_info->geometry=(char *) NULL;
11555              break;
11556            }
11557          if (LocaleCompare(attribute,"gravity") == 0)
11558            {
11559              ssize_t
11560                in;
11561
11562              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11563                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11564              if (in < 0)
11565                {
11566                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11567                    SvPV(ST(i),na));
11568                  return;
11569                }
11570              montage_info->gravity=(GravityType) in;
11571              for (next=image; next; next=next->next)
11572                next->gravity=(GravityType) in;
11573              break;
11574            }
11575           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11576             attribute);
11577           break;
11578         }
11579         case 'L':
11580         case 'l':
11581         {
11582           if (LocaleCompare(attribute,"label") == 0)
11583             {
11584               for (next=image; next; next=next->next)
11585                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11586                   info ? info->image_info : (ImageInfo *) NULL,next,
11587                   SvPV(ST(i),na),exception),exception);
11588               break;
11589             }
11590           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11591             attribute);
11592           break;
11593         }
11594         case 'M':
11595         case 'm':
11596         {
11597           if (LocaleCompare(attribute,"mattecolor") == 0)
11598             {
11599               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11600                 &montage_info->matte_color,exception);
11601               for (next=image; next; next=next->next)
11602                 next->matte_color=montage_info->matte_color;
11603               break;
11604             }
11605           if (LocaleCompare(attribute,"mode") == 0)
11606             {
11607               ssize_t
11608                 in;
11609
11610               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11611                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11612               switch (in)
11613               {
11614                 default:
11615                 {
11616                   ThrowPerlException(exception,OptionError,
11617                     "UnrecognizedModeType",SvPV(ST(i),na));
11618                   break;
11619                 }
11620                 case FrameMode:
11621                 {
11622                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11623                   montage_info->shadow=MagickTrue;
11624                   break;
11625                 }
11626                 case UnframeMode:
11627                 {
11628                   montage_info->frame=(char *) NULL;
11629                   montage_info->shadow=MagickFalse;
11630                   montage_info->border_width=0;
11631                   break;
11632                 }
11633                 case ConcatenateMode:
11634                 {
11635                   montage_info->frame=(char *) NULL;
11636                   montage_info->shadow=MagickFalse;
11637                   (void) CloneString(&montage_info->geometry,"+0+0");
11638                   montage_info->border_width=0;
11639                 }
11640               }
11641               break;
11642             }
11643           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11644             attribute);
11645           break;
11646         }
11647         case 'P':
11648         case 'p':
11649         {
11650           if (LocaleCompare(attribute,"pointsize") == 0)
11651             {
11652               montage_info->pointsize=SvIV(ST(i));
11653               break;
11654             }
11655           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11656             attribute);
11657           break;
11658         }
11659         case 'S':
11660         case 's':
11661         {
11662           if (LocaleCompare(attribute,"shadow") == 0)
11663             {
11664               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11665                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11666               if (sp < 0)
11667                 {
11668                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11669                     SvPV(ST(i),na));
11670                   break;
11671                 }
11672              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11673              break;
11674             }
11675           if (LocaleCompare(attribute,"stroke") == 0)
11676             {
11677               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11678                 &montage_info->stroke,exception);
11679               break;
11680             }
11681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11682             attribute);
11683           break;
11684         }
11685         case 'T':
11686         case 't':
11687         {
11688           if (LocaleCompare(attribute,"texture") == 0)
11689             {
11690               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11691               break;
11692             }
11693           if (LocaleCompare(attribute,"tile") == 0)
11694             {
11695               char *p=SvPV(ST(i),na);
11696               if (IsGeometry(p) == MagickFalse)
11697                 {
11698                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11699                     p);
11700                   break;
11701                 }
11702               (void) CloneString(&montage_info->tile,p);
11703               if (*p == '\0')
11704                 montage_info->tile=(char *) NULL;
11705               break;
11706             }
11707           if (LocaleCompare(attribute,"title") == 0)
11708             {
11709               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11710               break;
11711             }
11712           if (LocaleCompare(attribute,"transparent") == 0)
11713             {
11714               PixelInfo
11715                 transparent_color;
11716
11717               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11718                 &transparent_color,exception);
11719               for (next=image; next; next=next->next)
11720                 (void) TransparentPaintImage(next,&transparent_color,
11721                   TransparentAlpha,MagickFalse,exception);
11722               break;
11723             }
11724           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11725             attribute);
11726           break;
11727         }
11728         default:
11729         {
11730           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11731             attribute);
11732           break;
11733         }
11734       }
11735     }
11736     image=MontageImageList(info->image_info,montage_info,image,exception);
11737     montage_info=DestroyMontageInfo(montage_info);
11738     if (image == (Image *) NULL)
11739       goto PerlException;
11740     if (transparent_color.alpha != TransparentAlpha)
11741       for (next=image; next; next=next->next)
11742         (void) TransparentPaintImage(next,&transparent_color,
11743           TransparentAlpha,MagickFalse,exception);
11744     for (  ; image; image=image->next)
11745     {
11746       AddImageToRegistry(sv,image);
11747       rv=newRV(sv);
11748       av_push(av,sv_bless(rv,hv));
11749       SvREFCNT_dec(sv);
11750     }
11751     exception=DestroyExceptionInfo(exception);
11752     ST(0)=av_reference;
11753     SvREFCNT_dec(perl_exception);
11754     XSRETURN(1);
11755
11756   PerlException:
11757     InheritPerlException(exception,perl_exception);
11758     exception=DestroyExceptionInfo(exception);
11759     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11760     SvPOK_on(perl_exception);
11761     ST(0)=sv_2mortal(perl_exception);
11762     XSRETURN(1);
11763   }
11764 \f
11765 #
11766 ###############################################################################
11767 #                                                                             #
11768 #                                                                             #
11769 #                                                                             #
11770 #   M o r p h                                                                 #
11771 #                                                                             #
11772 #                                                                             #
11773 #                                                                             #
11774 ###############################################################################
11775 #
11776 #
11777 void
11778 Morph(ref,...)
11779   Image::Magick ref=NO_INIT
11780   ALIAS:
11781     MorphImage  = 1
11782     morph       = 2
11783     morphimage  = 3
11784   PPCODE:
11785   {
11786     AV
11787       *av;
11788
11789     char
11790       *attribute;
11791
11792     ExceptionInfo
11793       *exception;
11794
11795     HV
11796       *hv;
11797
11798     Image
11799       *image;
11800
11801     register ssize_t
11802       i;
11803
11804     ssize_t
11805       number_frames;
11806
11807     struct PackageInfo
11808       *info;
11809
11810     SV
11811       *av_reference,
11812       *perl_exception,
11813       *reference,
11814       *rv,
11815       *sv;
11816
11817     PERL_UNUSED_VAR(ref);
11818     PERL_UNUSED_VAR(ix);
11819     exception=AcquireExceptionInfo();
11820     perl_exception=newSVpv("",0);
11821     sv=NULL;
11822     av=NULL;
11823     attribute=NULL;
11824     if (sv_isobject(ST(0)) == 0)
11825       {
11826         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11827           PackageName);
11828         goto PerlException;
11829       }
11830     reference=SvRV(ST(0));
11831     hv=SvSTASH(reference);
11832     av=newAV();
11833     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11834     SvREFCNT_dec(av);
11835     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11836     if (image == (Image *) NULL)
11837       {
11838         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11839           PackageName);
11840         goto PerlException;
11841       }
11842     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11843     /*
11844       Get attribute.
11845     */
11846     number_frames=30;
11847     for (i=2; i < items; i+=2)
11848     {
11849       attribute=(char *) SvPV(ST(i-1),na);
11850       switch (*attribute)
11851       {
11852         case 'F':
11853         case 'f':
11854         {
11855           if (LocaleCompare(attribute,"frames") == 0)
11856             {
11857               number_frames=SvIV(ST(i));
11858               break;
11859             }
11860           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11861             attribute);
11862           break;
11863         }
11864         default:
11865         {
11866           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11867             attribute);
11868           break;
11869         }
11870       }
11871     }
11872     image=MorphImages(image,number_frames,exception);
11873     if (image == (Image *) NULL)
11874       goto PerlException;
11875     for ( ; image; image=image->next)
11876     {
11877       AddImageToRegistry(sv,image);
11878       rv=newRV(sv);
11879       av_push(av,sv_bless(rv,hv));
11880       SvREFCNT_dec(sv);
11881     }
11882     exception=DestroyExceptionInfo(exception);
11883     ST(0)=av_reference;
11884     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11885     XSRETURN(1);
11886
11887   PerlException:
11888     InheritPerlException(exception,perl_exception);
11889     exception=DestroyExceptionInfo(exception);
11890     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11891     SvPOK_on(perl_exception);
11892     ST(0)=sv_2mortal(perl_exception);
11893     XSRETURN(1);
11894   }
11895 \f
11896 #
11897 ###############################################################################
11898 #                                                                             #
11899 #                                                                             #
11900 #                                                                             #
11901 #   M o s a i c                                                               #
11902 #                                                                             #
11903 #                                                                             #
11904 #                                                                             #
11905 ###############################################################################
11906 #
11907 #
11908 void
11909 Mosaic(ref)
11910   Image::Magick ref=NO_INIT
11911   ALIAS:
11912     MosaicImage   = 1
11913     mosaic        = 2
11914     mosaicimage   = 3
11915   PPCODE:
11916   {
11917     AV
11918       *av;
11919
11920     ExceptionInfo
11921       *exception;
11922
11923     HV
11924       *hv;
11925
11926     Image
11927       *image;
11928
11929     struct PackageInfo
11930       *info;
11931
11932     SV
11933       *perl_exception,
11934       *reference,
11935       *rv,
11936       *sv;
11937
11938     PERL_UNUSED_VAR(ref);
11939     PERL_UNUSED_VAR(ix);
11940     exception=AcquireExceptionInfo();
11941     perl_exception=newSVpv("",0);
11942     sv=NULL;
11943     if (sv_isobject(ST(0)) == 0)
11944       {
11945         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11946           PackageName);
11947         goto PerlException;
11948       }
11949     reference=SvRV(ST(0));
11950     hv=SvSTASH(reference);
11951     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11952     if (image == (Image *) NULL)
11953       {
11954         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11955           PackageName);
11956         goto PerlException;
11957       }
11958     image=MergeImageLayers(image,MosaicLayer,exception);
11959     /*
11960       Create blessed Perl array for the returned image.
11961     */
11962     av=newAV();
11963     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11964     SvREFCNT_dec(av);
11965     AddImageToRegistry(sv,image);
11966     rv=newRV(sv);
11967     av_push(av,sv_bless(rv,hv));
11968     SvREFCNT_dec(sv);
11969     (void) CopyMagickString(info->image_info->filename,image->filename,
11970       MagickPathExtent);
11971     SetImageInfo(info->image_info,0,exception);
11972     exception=DestroyExceptionInfo(exception);
11973     SvREFCNT_dec(perl_exception);
11974     XSRETURN(1);
11975
11976   PerlException:
11977     InheritPerlException(exception,perl_exception);
11978     exception=DestroyExceptionInfo(exception);
11979     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11980     SvPOK_on(perl_exception);  /* return messages in string context */
11981     ST(0)=sv_2mortal(perl_exception);
11982     XSRETURN(1);
11983   }
11984 \f
11985 #
11986 ###############################################################################
11987 #                                                                             #
11988 #                                                                             #
11989 #                                                                             #
11990 #   P i n g                                                                   #
11991 #                                                                             #
11992 #                                                                             #
11993 #                                                                             #
11994 ###############################################################################
11995 #
11996 #
11997 void
11998 Ping(ref,...)
11999   Image::Magick ref=NO_INIT
12000   ALIAS:
12001     PingImage  = 1
12002     ping       = 2
12003     pingimage  = 3
12004   PPCODE:
12005   {
12006     AV
12007       *av;
12008
12009     char
12010       **keep,
12011       **list;
12012
12013     ExceptionInfo
12014       *exception;
12015
12016     Image
12017       *image,
12018       *next;
12019
12020     int
12021       n;
12022
12023     MagickBooleanType
12024       status;
12025
12026     register char
12027       **p;
12028
12029     register ssize_t
12030       i;
12031
12032     ssize_t
12033       ac;
12034
12035     STRLEN
12036       *length;
12037
12038     struct PackageInfo
12039       *info,
12040       *package_info;
12041
12042     SV
12043       *perl_exception,
12044       *reference;
12045
12046     size_t
12047       count;
12048
12049     PERL_UNUSED_VAR(ref);
12050     PERL_UNUSED_VAR(ix);
12051     exception=AcquireExceptionInfo();
12052     perl_exception=newSVpv("",0);
12053     package_info=(struct PackageInfo *) NULL;
12054     ac=(items < 2) ? 1 : items-1;
12055     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12056     keep=list;
12057     length=(STRLEN *) NULL;
12058     if (list == (char **) NULL)
12059       {
12060         ThrowPerlException(exception,ResourceLimitError,
12061           "MemoryAllocationFailed",PackageName);
12062         goto PerlException;
12063       }
12064     keep=list;
12065     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12066     if (length == (STRLEN *) NULL)
12067       {
12068         ThrowPerlException(exception,ResourceLimitError,
12069           "MemoryAllocationFailed",PackageName);
12070         goto PerlException;
12071       }
12072     if (sv_isobject(ST(0)) == 0)
12073       {
12074         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12075           PackageName);
12076         goto PerlException;
12077       }
12078     reference=SvRV(ST(0));
12079     if (SvTYPE(reference) != SVt_PVAV)
12080       {
12081         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12082           PackageName);
12083         goto PerlException;
12084       }
12085     av=(AV *) reference;
12086     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12087       exception);
12088     package_info=ClonePackageInfo(info,exception);
12089     n=1;
12090     if (items <= 1)
12091       *list=(char *) (*package_info->image_info->filename ?
12092         package_info->image_info->filename : "XC:black");
12093     else
12094       for (n=0, i=0; i < ac; i++)
12095       {
12096         list[n]=(char *) SvPV(ST(i+1),length[n]);
12097         if ((items >= 3) && strEQcase(list[n],"blob"))
12098           {
12099             void
12100               *blob;
12101
12102             i++;
12103             blob=(void *) (SvPV(ST(i+1),length[n]));
12104             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12105           }
12106         if ((items >= 3) && strEQcase(list[n],"filename"))
12107           continue;
12108         if ((items >= 3) && strEQcase(list[n],"file"))
12109           {
12110             FILE
12111               *file;
12112
12113             PerlIO
12114               *io_info;
12115
12116             i++;
12117             io_info=IoIFP(sv_2io(ST(i+1)));
12118             if (io_info == (PerlIO *) NULL)
12119               {
12120                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12121                   PackageName);
12122                 continue;
12123               }
12124             file=PerlIO_findFILE(io_info);
12125             if (file == (FILE *) NULL)
12126               {
12127                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12128                   PackageName);
12129                 continue;
12130               }
12131             SetImageInfoFile(package_info->image_info,file);
12132           }
12133         if ((items >= 3) && strEQcase(list[n],"magick"))
12134           continue;
12135         n++;
12136       }
12137     list[n]=(char *) NULL;
12138     keep=list;
12139     status=ExpandFilenames(&n,&list);
12140     if (status == MagickFalse)
12141       {
12142         ThrowPerlException(exception,ResourceLimitError,
12143           "MemoryAllocationFailed",PackageName);
12144         goto PerlException;
12145       }
12146     count=0;
12147     for (i=0; i < n; i++)
12148     {
12149       (void) CopyMagickString(package_info->image_info->filename,list[i],
12150         MagickPathExtent);
12151       image=PingImage(package_info->image_info,exception);
12152       if (image == (Image *) NULL)
12153         break;
12154       if ((package_info->image_info->file != (FILE *) NULL) ||
12155           (package_info->image_info->blob != (void *) NULL))
12156         DisassociateImageStream(image);
12157       count+=GetImageListLength(image);
12158       EXTEND(sp,4*count);
12159       for (next=image; next; next=next->next)
12160       {
12161         PUSHs(sv_2mortal(newSViv(next->columns)));
12162         PUSHs(sv_2mortal(newSViv(next->rows)));
12163         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12164         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12165       }
12166       image=DestroyImageList(image);
12167     }
12168     /*
12169       Free resources.
12170     */
12171     for (i=0; i < n; i++)
12172       if (list[i] != (char *) NULL)
12173         for (p=keep; list[i] != *p++; )
12174           if (*p == NULL)
12175             {
12176               list[i]=(char *) RelinquishMagickMemory(list[i]);
12177               break;
12178             }
12179
12180   PerlException:
12181     if (package_info != (struct PackageInfo *) NULL)
12182       DestroyPackageInfo(package_info);
12183     if (list && (list != keep))
12184       list=(char **) RelinquishMagickMemory(list);
12185     if (keep)
12186       keep=(char **) RelinquishMagickMemory(keep);
12187     if (length)
12188       length=(STRLEN *) RelinquishMagickMemory(length);
12189     InheritPerlException(exception,perl_exception);
12190     exception=DestroyExceptionInfo(exception);
12191     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12192   }
12193 \f
12194 #
12195 ###############################################################################
12196 #                                                                             #
12197 #                                                                             #
12198 #                                                                             #
12199 #   P r e v i e w                                                             #
12200 #                                                                             #
12201 #                                                                             #
12202 #                                                                             #
12203 ###############################################################################
12204 #
12205 #
12206 void
12207 Preview(ref,...)
12208   Image::Magick ref=NO_INIT
12209   ALIAS:
12210     PreviewImage = 1
12211     preview      = 2
12212     previewimage = 3
12213   PPCODE:
12214   {
12215     AV
12216       *av;
12217
12218     ExceptionInfo
12219       *exception;
12220
12221     HV
12222       *hv;
12223
12224     Image
12225       *image,
12226       *preview_image;
12227
12228     PreviewType
12229       preview_type;
12230
12231     struct PackageInfo
12232       *info;
12233
12234     SV
12235       *av_reference,
12236       *perl_exception,
12237       *reference,
12238       *rv,
12239       *sv;
12240
12241     PERL_UNUSED_VAR(ref);
12242     PERL_UNUSED_VAR(ix);
12243     exception=AcquireExceptionInfo();
12244     perl_exception=newSVpv("",0);
12245     sv=NULL;
12246     av=NULL;
12247     if (sv_isobject(ST(0)) == 0)
12248       {
12249         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12250           PackageName);
12251         goto PerlException;
12252       }
12253     reference=SvRV(ST(0));
12254     hv=SvSTASH(reference);
12255     av=newAV();
12256     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12257     SvREFCNT_dec(av);
12258     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12259     if (image == (Image *) NULL)
12260       {
12261         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12262           PackageName);
12263         goto PerlException;
12264       }
12265     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12266     preview_type=GammaPreview;
12267     if (items > 1)
12268       preview_type=(PreviewType)
12269         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12270     for ( ; image; image=image->next)
12271     {
12272       preview_image=PreviewImage(image,preview_type,exception);
12273       if (preview_image == (Image *) NULL)
12274         goto PerlException;
12275       AddImageToRegistry(sv,preview_image);
12276       rv=newRV(sv);
12277       av_push(av,sv_bless(rv,hv));
12278       SvREFCNT_dec(sv);
12279     }
12280     exception=DestroyExceptionInfo(exception);
12281     ST(0)=av_reference;
12282     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12283     XSRETURN(1);
12284
12285   PerlException:
12286     InheritPerlException(exception,perl_exception);
12287     exception=DestroyExceptionInfo(exception);
12288     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12289     SvPOK_on(perl_exception);
12290     ST(0)=sv_2mortal(perl_exception);
12291     XSRETURN(1);
12292   }
12293 \f
12294 #
12295 ###############################################################################
12296 #                                                                             #
12297 #                                                                             #
12298 #                                                                             #
12299 #   Q u e r y C o l o r                                                       #
12300 #                                                                             #
12301 #                                                                             #
12302 #                                                                             #
12303 ###############################################################################
12304 #
12305 #
12306 void
12307 QueryColor(ref,...)
12308   Image::Magick ref=NO_INIT
12309   ALIAS:
12310     querycolor = 1
12311   PPCODE:
12312   {
12313     char
12314       *name;
12315
12316     ExceptionInfo
12317       *exception;
12318
12319     PixelInfo
12320       color;
12321
12322     register ssize_t
12323       i;
12324
12325     SV
12326       *perl_exception;
12327
12328     PERL_UNUSED_VAR(ref);
12329     PERL_UNUSED_VAR(ix);
12330     exception=AcquireExceptionInfo();
12331     perl_exception=newSVpv("",0);
12332     if (items == 1)
12333       {
12334         const ColorInfo
12335           **colorlist;
12336
12337         size_t
12338           colors;
12339
12340         colorlist=GetColorInfoList("*",&colors,exception);
12341         EXTEND(sp,colors);
12342         for (i=0; i < (ssize_t) colors; i++)
12343         {
12344           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12345         }
12346         colorlist=(const ColorInfo **)
12347           RelinquishMagickMemory((ColorInfo **) colorlist);
12348         goto PerlException;
12349       }
12350     EXTEND(sp,5*items);
12351     for (i=1; i < items; i++)
12352     {
12353       name=(char *) SvPV(ST(i),na);
12354       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12355         {
12356           PUSHs(&sv_undef);
12357           continue;
12358         }
12359       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12360       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12361       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12362       if (color.colorspace == CMYKColorspace)
12363         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12364       if (color.alpha_trait != UndefinedPixelTrait)
12365         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12366     }
12367
12368   PerlException:
12369     InheritPerlException(exception,perl_exception);
12370     exception=DestroyExceptionInfo(exception);
12371     SvREFCNT_dec(perl_exception);
12372   }
12373 \f
12374 #
12375 ###############################################################################
12376 #                                                                             #
12377 #                                                                             #
12378 #                                                                             #
12379 #   Q u e r y C o l o r N a m e                                               #
12380 #                                                                             #
12381 #                                                                             #
12382 #                                                                             #
12383 ###############################################################################
12384 #
12385 #
12386 void
12387 QueryColorname(ref,...)
12388   Image::Magick ref=NO_INIT
12389   ALIAS:
12390     querycolorname = 1
12391   PPCODE:
12392   {
12393     AV
12394       *av;
12395
12396     char
12397       message[MagickPathExtent];
12398
12399     ExceptionInfo
12400       *exception;
12401
12402     Image
12403       *image;
12404
12405     PixelInfo
12406       target_color;
12407
12408     register ssize_t
12409       i;
12410
12411     struct PackageInfo
12412       *info;
12413
12414     SV
12415       *perl_exception,
12416       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12417
12418     PERL_UNUSED_VAR(ref);
12419     PERL_UNUSED_VAR(ix);
12420     exception=AcquireExceptionInfo();
12421     perl_exception=newSVpv("",0);
12422     reference=SvRV(ST(0));
12423     av=(AV *) reference;
12424     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12425       exception);
12426     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12427     if (image == (Image *) NULL)
12428       {
12429         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12430           PackageName);
12431         goto PerlException;
12432       }
12433     EXTEND(sp,items);
12434     for (i=1; i < items; i++)
12435     {
12436       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12437         exception);
12438       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12439         exception);
12440       PUSHs(sv_2mortal(newSVpv(message,0)));
12441     }
12442
12443   PerlException:
12444     InheritPerlException(exception,perl_exception);
12445     exception=DestroyExceptionInfo(exception);
12446     SvREFCNT_dec(perl_exception);
12447   }
12448 \f
12449 #
12450 ###############################################################################
12451 #                                                                             #
12452 #                                                                             #
12453 #                                                                             #
12454 #   Q u e r y F o n t                                                         #
12455 #                                                                             #
12456 #                                                                             #
12457 #                                                                             #
12458 ###############################################################################
12459 #
12460 #
12461 void
12462 QueryFont(ref,...)
12463   Image::Magick ref=NO_INIT
12464   ALIAS:
12465     queryfont = 1
12466   PPCODE:
12467   {
12468     char
12469       *name,
12470       message[MagickPathExtent];
12471
12472     ExceptionInfo
12473       *exception;
12474
12475     register ssize_t
12476       i;
12477
12478     SV
12479       *perl_exception;
12480
12481     volatile const TypeInfo
12482       *type_info;
12483
12484     PERL_UNUSED_VAR(ref);
12485     PERL_UNUSED_VAR(ix);
12486     exception=AcquireExceptionInfo();
12487     perl_exception=newSVpv("",0);
12488     if (items == 1)
12489       {
12490         const TypeInfo
12491           **typelist;
12492
12493         size_t
12494           types;
12495
12496         typelist=GetTypeInfoList("*",&types,exception);
12497         EXTEND(sp,types);
12498         for (i=0; i < (ssize_t) types; i++)
12499         {
12500           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12501         }
12502         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12503           typelist);
12504         goto PerlException;
12505       }
12506     EXTEND(sp,10*items);
12507     for (i=1; i < items; i++)
12508     {
12509       name=(char *) SvPV(ST(i),na);
12510       type_info=GetTypeInfo(name,exception);
12511       if (type_info == (TypeInfo *) NULL)
12512         {
12513           PUSHs(&sv_undef);
12514           continue;
12515         }
12516       if (type_info->name == (char *) NULL)
12517         PUSHs(&sv_undef);
12518       else
12519         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12520       if (type_info->description == (char *) NULL)
12521         PUSHs(&sv_undef);
12522       else
12523         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12524       if (type_info->family == (char *) NULL)
12525         PUSHs(&sv_undef);
12526       else
12527         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12528       if (type_info->style == UndefinedStyle)
12529         PUSHs(&sv_undef);
12530       else
12531         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12532           type_info->style),0)));
12533       if (type_info->stretch == UndefinedStretch)
12534         PUSHs(&sv_undef);
12535       else
12536         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12537           type_info->stretch),0)));
12538       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12539         type_info->weight);
12540       PUSHs(sv_2mortal(newSVpv(message,0)));
12541       if (type_info->encoding == (char *) NULL)
12542         PUSHs(&sv_undef);
12543       else
12544         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12545       if (type_info->foundry == (char *) NULL)
12546         PUSHs(&sv_undef);
12547       else
12548         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12549       if (type_info->format == (char *) NULL)
12550         PUSHs(&sv_undef);
12551       else
12552         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12553       if (type_info->metrics == (char *) NULL)
12554         PUSHs(&sv_undef);
12555       else
12556         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12557       if (type_info->glyphs == (char *) NULL)
12558         PUSHs(&sv_undef);
12559       else
12560         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12561     }
12562
12563   PerlException:
12564     InheritPerlException(exception,perl_exception);
12565     exception=DestroyExceptionInfo(exception);
12566     SvREFCNT_dec(perl_exception);
12567   }
12568 \f
12569 #
12570 ###############################################################################
12571 #                                                                             #
12572 #                                                                             #
12573 #                                                                             #
12574 #   Q u e r y F o n t M e t r i c s                                           #
12575 #                                                                             #
12576 #                                                                             #
12577 #                                                                             #
12578 ###############################################################################
12579 #
12580 #
12581 void
12582 QueryFontMetrics(ref,...)
12583   Image::Magick ref=NO_INIT
12584   ALIAS:
12585     queryfontmetrics = 1
12586   PPCODE:
12587   {
12588     AffineMatrix
12589       affine,
12590       current;
12591
12592     AV
12593       *av;
12594
12595     char
12596       *attribute;
12597
12598     double
12599       x,
12600       y;
12601
12602     DrawInfo
12603       *draw_info;
12604
12605     ExceptionInfo
12606       *exception;
12607
12608     GeometryInfo
12609       geometry_info;
12610
12611     Image
12612       *image;
12613
12614     MagickBooleanType
12615       status;
12616
12617     MagickStatusType
12618       flags;
12619
12620     register ssize_t
12621       i;
12622
12623     ssize_t
12624       type;
12625
12626     struct PackageInfo
12627       *info,
12628       *package_info;
12629
12630     SV
12631       *perl_exception,
12632       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12633
12634     TypeMetric
12635       metrics;
12636
12637     PERL_UNUSED_VAR(ref);
12638     PERL_UNUSED_VAR(ix);
12639     exception=AcquireExceptionInfo();
12640     package_info=(struct PackageInfo *) NULL;
12641     perl_exception=newSVpv("",0);
12642     reference=SvRV(ST(0));
12643     av=(AV *) reference;
12644     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12645       exception);
12646     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12647     if (image == (Image *) NULL)
12648       {
12649         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12650           PackageName);
12651         goto PerlException;
12652       }
12653     package_info=ClonePackageInfo(info,exception);
12654     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12655     CloneString(&draw_info->text,"");
12656     current=draw_info->affine;
12657     GetAffineMatrix(&affine);
12658     x=0.0;
12659     y=0.0;
12660     EXTEND(sp,7*items);
12661     for (i=2; i < items; i+=2)
12662     {
12663       attribute=(char *) SvPV(ST(i-1),na);
12664       switch (*attribute)
12665       {
12666         case 'A':
12667         case 'a':
12668         {
12669           if (LocaleCompare(attribute,"antialias") == 0)
12670             {
12671               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12672                 SvPV(ST(i),na));
12673               if (type < 0)
12674                 {
12675                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12676                     SvPV(ST(i),na));
12677                   break;
12678                 }
12679               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12680               break;
12681             }
12682           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12683             attribute);
12684           break;
12685         }
12686         case 'd':
12687         case 'D':
12688         {
12689           if (LocaleCompare(attribute,"density") == 0)
12690             {
12691               CloneString(&draw_info->density,SvPV(ST(i),na));
12692               break;
12693             }
12694           if (LocaleCompare(attribute,"direction") == 0)
12695             {
12696               draw_info->direction=(DirectionType) ParseCommandOption(
12697                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12698               break;
12699             }
12700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12701             attribute);
12702           break;
12703         }
12704         case 'e':
12705         case 'E':
12706         {
12707           if (LocaleCompare(attribute,"encoding") == 0)
12708             {
12709               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12710               break;
12711             }
12712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12713             attribute);
12714           break;
12715         }
12716         case 'f':
12717         case 'F':
12718         {
12719           if (LocaleCompare(attribute,"family") == 0)
12720             {
12721               CloneString(&draw_info->family,SvPV(ST(i),na));
12722               break;
12723             }
12724           if (LocaleCompare(attribute,"fill") == 0)
12725             {
12726               if (info)
12727                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12728                   &draw_info->fill,exception);
12729               break;
12730             }
12731           if (LocaleCompare(attribute,"font") == 0)
12732             {
12733               CloneString(&draw_info->font,SvPV(ST(i),na));
12734               break;
12735             }
12736           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12737             attribute);
12738           break;
12739         }
12740         case 'g':
12741         case 'G':
12742         {
12743           if (LocaleCompare(attribute,"geometry") == 0)
12744             {
12745               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12746               break;
12747             }
12748           if (LocaleCompare(attribute,"gravity") == 0)
12749             {
12750               draw_info->gravity=(GravityType) ParseCommandOption(
12751                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12752               break;
12753             }
12754           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12755             attribute);
12756           break;
12757         }
12758         case 'i':
12759         case 'I':
12760         {
12761           if (LocaleCompare(attribute,"interline-spacing") == 0)
12762             {
12763               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12764               draw_info->interline_spacing=geometry_info.rho;
12765               break;
12766             }
12767           if (LocaleCompare(attribute,"interword-spacing") == 0)
12768             {
12769               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12770               draw_info->interword_spacing=geometry_info.rho;
12771               break;
12772             }
12773           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12774             attribute);
12775           break;
12776         }
12777         case 'k':
12778         case 'K':
12779         {
12780           if (LocaleCompare(attribute,"kerning") == 0)
12781             {
12782               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12783               draw_info->kerning=geometry_info.rho;
12784               break;
12785             }
12786           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12787             attribute);
12788           break;
12789         }
12790         case 'p':
12791         case 'P':
12792         {
12793           if (LocaleCompare(attribute,"pointsize") == 0)
12794             {
12795               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12796               draw_info->pointsize=geometry_info.rho;
12797               break;
12798             }
12799           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12800             attribute);
12801           break;
12802         }
12803         case 'r':
12804         case 'R':
12805         {
12806           if (LocaleCompare(attribute,"rotate") == 0)
12807             {
12808               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12809               affine.rx=geometry_info.rho;
12810               affine.ry=geometry_info.sigma;
12811               if ((flags & SigmaValue) == 0)
12812                 affine.ry=affine.rx;
12813               break;
12814             }
12815           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12816             attribute);
12817           break;
12818         }
12819         case 's':
12820         case 'S':
12821         {
12822           if (LocaleCompare(attribute,"scale") == 0)
12823             {
12824               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12825               affine.sx=geometry_info.rho;
12826               affine.sy=geometry_info.sigma;
12827               if ((flags & SigmaValue) == 0)
12828                 affine.sy=affine.sx;
12829               break;
12830             }
12831           if (LocaleCompare(attribute,"skew") == 0)
12832             {
12833               double
12834                 x_angle,
12835                 y_angle;
12836
12837               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12838               x_angle=geometry_info.rho;
12839               y_angle=geometry_info.sigma;
12840               if ((flags & SigmaValue) == 0)
12841                 y_angle=x_angle;
12842               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12843               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12844               break;
12845             }
12846           if (LocaleCompare(attribute,"stroke") == 0)
12847             {
12848               if (info)
12849                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12850                   &draw_info->stroke,exception);
12851               break;
12852             }
12853           if (LocaleCompare(attribute,"style") == 0)
12854             {
12855               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12856                 SvPV(ST(i),na));
12857               if (type < 0)
12858                 {
12859                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12860                     SvPV(ST(i),na));
12861                   break;
12862                 }
12863               draw_info->style=(StyleType) type;
12864               break;
12865             }
12866           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12867             attribute);
12868           break;
12869         }
12870         case 't':
12871         case 'T':
12872         {
12873           if (LocaleCompare(attribute,"text") == 0)
12874             {
12875               CloneString(&draw_info->text,SvPV(ST(i),na));
12876               break;
12877             }
12878           if (LocaleCompare(attribute,"translate") == 0)
12879             {
12880               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12881               affine.tx=geometry_info.rho;
12882               affine.ty=geometry_info.sigma;
12883               if ((flags & SigmaValue) == 0)
12884                 affine.ty=affine.tx;
12885               break;
12886             }
12887           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12888             attribute);
12889           break;
12890         }
12891         case 'w':
12892         case 'W':
12893         {
12894           if (LocaleCompare(attribute,"weight") == 0)
12895             {
12896               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12897               draw_info->weight=(size_t) geometry_info.rho;
12898               break;
12899             }
12900           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12901             attribute);
12902           break;
12903         }
12904         case 'x':
12905         case 'X':
12906         {
12907           if (LocaleCompare(attribute,"x") == 0)
12908             {
12909               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12910               x=geometry_info.rho;
12911               break;
12912             }
12913           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12914             attribute);
12915           break;
12916         }
12917         case 'y':
12918         case 'Y':
12919         {
12920           if (LocaleCompare(attribute,"y") == 0)
12921             {
12922               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12923               y=geometry_info.rho;
12924               break;
12925             }
12926           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12927             attribute);
12928           break;
12929         }
12930         default:
12931         {
12932           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12933             attribute);
12934           break;
12935         }
12936       }
12937     }
12938     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12939     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12940     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12941     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12942     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12943     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12944     if (draw_info->geometry == (char *) NULL)
12945       {
12946         draw_info->geometry=AcquireString((char *) NULL);
12947         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12948           "%.15g,%.15g",x,y);
12949       }
12950     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12951     (void) CatchImageException(image);
12952     if (status == MagickFalse)
12953       PUSHs(&sv_undef);
12954     else
12955       {
12956         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12957         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12958         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12959         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12960         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12961         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12962         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12963         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12964         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12965         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12966         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12967         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12968         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12969       }
12970     draw_info=DestroyDrawInfo(draw_info);
12971
12972   PerlException:
12973     if (package_info != (struct PackageInfo *) NULL)
12974       DestroyPackageInfo(package_info);
12975     InheritPerlException(exception,perl_exception);
12976     exception=DestroyExceptionInfo(exception);
12977     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12978   }
12979 \f
12980 #
12981 ###############################################################################
12982 #                                                                             #
12983 #                                                                             #
12984 #                                                                             #
12985 #   Q u e r y M u l t i l i n e F o n t M e t r i c s                         #
12986 #                                                                             #
12987 #                                                                             #
12988 #                                                                             #
12989 ###############################################################################
12990 #
12991 #
12992 void
12993 QueryMultilineFontMetrics(ref,...)
12994   Image::Magick ref=NO_INIT
12995   ALIAS:
12996     querymultilinefontmetrics = 1
12997   PPCODE:
12998   {
12999     AffineMatrix
13000       affine,
13001       current;
13002
13003     AV
13004       *av;
13005
13006     char
13007       *attribute;
13008
13009     double
13010       x,
13011       y;
13012
13013     DrawInfo
13014       *draw_info;
13015
13016     ExceptionInfo
13017       *exception;
13018
13019     GeometryInfo
13020       geometry_info;
13021
13022     Image
13023       *image;
13024
13025     MagickBooleanType
13026       status;
13027
13028     MagickStatusType
13029       flags;
13030
13031     register ssize_t
13032       i;
13033
13034     ssize_t
13035       type;
13036
13037     struct PackageInfo
13038       *info,
13039       *package_info;
13040
13041     SV
13042       *perl_exception,
13043       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13044
13045     TypeMetric
13046       metrics;
13047
13048     PERL_UNUSED_VAR(ref);
13049     PERL_UNUSED_VAR(ix);
13050     exception=AcquireExceptionInfo();
13051     package_info=(struct PackageInfo *) NULL;
13052     perl_exception=newSVpv("",0);
13053     reference=SvRV(ST(0));
13054     av=(AV *) reference;
13055     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13056       exception);
13057     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13058     if (image == (Image *) NULL)
13059       {
13060         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13061           PackageName);
13062         goto PerlException;
13063       }
13064     package_info=ClonePackageInfo(info,exception);
13065     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13066     CloneString(&draw_info->text,"");
13067     current=draw_info->affine;
13068     GetAffineMatrix(&affine);
13069     x=0.0;
13070     y=0.0;
13071     EXTEND(sp,7*items);
13072     for (i=2; i < items; i+=2)
13073     {
13074       attribute=(char *) SvPV(ST(i-1),na);
13075       switch (*attribute)
13076       {
13077         case 'A':
13078         case 'a':
13079         {
13080           if (LocaleCompare(attribute,"antialias") == 0)
13081             {
13082               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13083                 SvPV(ST(i),na));
13084               if (type < 0)
13085                 {
13086                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13087                     SvPV(ST(i),na));
13088                   break;
13089                 }
13090               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13091               break;
13092             }
13093           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13094             attribute);
13095           break;
13096         }
13097         case 'd':
13098         case 'D':
13099         {
13100           if (LocaleCompare(attribute,"density") == 0)
13101             {
13102               CloneString(&draw_info->density,SvPV(ST(i),na));
13103               break;
13104             }
13105           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13106             attribute);
13107           break;
13108         }
13109         case 'e':
13110         case 'E':
13111         {
13112           if (LocaleCompare(attribute,"encoding") == 0)
13113             {
13114               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13115               break;
13116             }
13117           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13118             attribute);
13119           break;
13120         }
13121         case 'f':
13122         case 'F':
13123         {
13124           if (LocaleCompare(attribute,"family") == 0)
13125             {
13126               CloneString(&draw_info->family,SvPV(ST(i),na));
13127               break;
13128             }
13129           if (LocaleCompare(attribute,"fill") == 0)
13130             {
13131               if (info)
13132                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13133                   &draw_info->fill,exception);
13134               break;
13135             }
13136           if (LocaleCompare(attribute,"font") == 0)
13137             {
13138               CloneString(&draw_info->font,SvPV(ST(i),na));
13139               break;
13140             }
13141           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13142             attribute);
13143           break;
13144         }
13145         case 'g':
13146         case 'G':
13147         {
13148           if (LocaleCompare(attribute,"geometry") == 0)
13149             {
13150               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13151               break;
13152             }
13153           if (LocaleCompare(attribute,"gravity") == 0)
13154             {
13155               draw_info->gravity=(GravityType) ParseCommandOption(
13156                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13157               break;
13158             }
13159           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13160             attribute);
13161           break;
13162         }
13163         case 'p':
13164         case 'P':
13165         {
13166           if (LocaleCompare(attribute,"pointsize") == 0)
13167             {
13168               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13169               draw_info->pointsize=geometry_info.rho;
13170               break;
13171             }
13172           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13173             attribute);
13174           break;
13175         }
13176         case 'r':
13177         case 'R':
13178         {
13179           if (LocaleCompare(attribute,"rotate") == 0)
13180             {
13181               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13182               affine.rx=geometry_info.rho;
13183               affine.ry=geometry_info.sigma;
13184               if ((flags & SigmaValue) == 0)
13185                 affine.ry=affine.rx;
13186               break;
13187             }
13188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13189             attribute);
13190           break;
13191         }
13192         case 's':
13193         case 'S':
13194         {
13195           if (LocaleCompare(attribute,"scale") == 0)
13196             {
13197               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13198               affine.sx=geometry_info.rho;
13199               affine.sy=geometry_info.sigma;
13200               if ((flags & SigmaValue) == 0)
13201                 affine.sy=affine.sx;
13202               break;
13203             }
13204           if (LocaleCompare(attribute,"skew") == 0)
13205             {
13206               double
13207                 x_angle,
13208                 y_angle;
13209
13210               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13211               x_angle=geometry_info.rho;
13212               y_angle=geometry_info.sigma;
13213               if ((flags & SigmaValue) == 0)
13214                 y_angle=x_angle;
13215               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13216               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13217               break;
13218             }
13219           if (LocaleCompare(attribute,"stroke") == 0)
13220             {
13221               if (info)
13222                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13223                   &draw_info->stroke,exception);
13224               break;
13225             }
13226           if (LocaleCompare(attribute,"style") == 0)
13227             {
13228               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13229                 SvPV(ST(i),na));
13230               if (type < 0)
13231                 {
13232                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13233                     SvPV(ST(i),na));
13234                   break;
13235                 }
13236               draw_info->style=(StyleType) type;
13237               break;
13238             }
13239           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13240             attribute);
13241           break;
13242         }
13243         case 't':
13244         case 'T':
13245         {
13246           if (LocaleCompare(attribute,"text") == 0)
13247             {
13248               CloneString(&draw_info->text,SvPV(ST(i),na));
13249               break;
13250             }
13251           if (LocaleCompare(attribute,"translate") == 0)
13252             {
13253               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13254               affine.tx=geometry_info.rho;
13255               affine.ty=geometry_info.sigma;
13256               if ((flags & SigmaValue) == 0)
13257                 affine.ty=affine.tx;
13258               break;
13259             }
13260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13261             attribute);
13262           break;
13263         }
13264         case 'w':
13265         case 'W':
13266         {
13267           if (LocaleCompare(attribute,"weight") == 0)
13268             {
13269               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13270               draw_info->weight=(size_t) geometry_info.rho;
13271               break;
13272             }
13273           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13274             attribute);
13275           break;
13276         }
13277         case 'x':
13278         case 'X':
13279         {
13280           if (LocaleCompare(attribute,"x") == 0)
13281             {
13282               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13283               x=geometry_info.rho;
13284               break;
13285             }
13286           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13287             attribute);
13288           break;
13289         }
13290         case 'y':
13291         case 'Y':
13292         {
13293           if (LocaleCompare(attribute,"y") == 0)
13294             {
13295               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13296               y=geometry_info.rho;
13297               break;
13298             }
13299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13300             attribute);
13301           break;
13302         }
13303         default:
13304         {
13305           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13306             attribute);
13307           break;
13308         }
13309       }
13310     }
13311     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13312     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13313     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13314     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13315     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13316     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13317     if (draw_info->geometry == (char *) NULL)
13318       {
13319         draw_info->geometry=AcquireString((char *) NULL);
13320         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13321           "%.15g,%.15g",x,y);
13322       }
13323     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13324     (void) CatchException(exception);
13325     if (status == MagickFalse)
13326       PUSHs(&sv_undef);
13327     else
13328       {
13329         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13330         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13331         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13332         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13333         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13334         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13335         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13336         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13337         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13338         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13339         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13340         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13341         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13342       }
13343     draw_info=DestroyDrawInfo(draw_info);
13344
13345   PerlException:
13346     if (package_info != (struct PackageInfo *) NULL)
13347       DestroyPackageInfo(package_info);
13348     InheritPerlException(exception,perl_exception);
13349     exception=DestroyExceptionInfo(exception);
13350     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13351   }
13352 \f
13353 #
13354 ###############################################################################
13355 #                                                                             #
13356 #                                                                             #
13357 #                                                                             #
13358 #   Q u e r y F o r m a t                                                     #
13359 #                                                                             #
13360 #                                                                             #
13361 #                                                                             #
13362 ###############################################################################
13363 #
13364 #
13365 void
13366 QueryFormat(ref,...)
13367   Image::Magick ref=NO_INIT
13368   ALIAS:
13369     queryformat = 1
13370   PPCODE:
13371   {
13372     char
13373       *name;
13374
13375     ExceptionInfo
13376       *exception;
13377
13378     register ssize_t
13379       i;
13380
13381     SV
13382       *perl_exception;
13383
13384     volatile const MagickInfo
13385       *magick_info;
13386
13387     PERL_UNUSED_VAR(ref);
13388     PERL_UNUSED_VAR(ix);
13389     exception=AcquireExceptionInfo();
13390     perl_exception=newSVpv("",0);
13391     if (items == 1)
13392       {
13393         char
13394           format[MagickPathExtent];
13395
13396         const MagickInfo
13397           **format_list;
13398
13399         size_t
13400           types;
13401
13402         format_list=GetMagickInfoList("*",&types,exception);
13403         EXTEND(sp,types);
13404         for (i=0; i < (ssize_t) types; i++)
13405         {
13406           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13407           LocaleLower(format);
13408           PUSHs(sv_2mortal(newSVpv(format,0)));
13409         }
13410         format_list=(const MagickInfo **)
13411           RelinquishMagickMemory((MagickInfo *) format_list);
13412         goto PerlException;
13413       }
13414     EXTEND(sp,8*items);
13415     for (i=1; i < items; i++)
13416     {
13417       name=(char *) SvPV(ST(i),na);
13418       magick_info=GetMagickInfo(name,exception);
13419       if (magick_info == (const MagickInfo *) NULL)
13420         {
13421           PUSHs(&sv_undef);
13422           continue;
13423         }
13424       if (magick_info->description == (char *) NULL)
13425         PUSHs(&sv_undef);
13426       else
13427         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13428       if (magick_info->module == (char *) NULL)
13429         PUSHs(&sv_undef);
13430       else
13431         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13432     }
13433
13434   PerlException:
13435     InheritPerlException(exception,perl_exception);
13436     exception=DestroyExceptionInfo(exception);
13437     SvREFCNT_dec(perl_exception);
13438   }
13439 \f
13440 #
13441 ###############################################################################
13442 #                                                                             #
13443 #                                                                             #
13444 #                                                                             #
13445 #   Q u e r y O p t i o n                                                     #
13446 #                                                                             #
13447 #                                                                             #
13448 #                                                                             #
13449 ###############################################################################
13450 #
13451 #
13452 void
13453 QueryOption(ref,...)
13454   Image::Magick ref=NO_INIT
13455   ALIAS:
13456     queryoption = 1
13457   PPCODE:
13458   {
13459     char
13460       **options;
13461
13462     ExceptionInfo
13463       *exception;
13464
13465     register ssize_t
13466       i;
13467
13468     ssize_t
13469       j,
13470       option;
13471
13472     SV
13473       *perl_exception;
13474
13475     PERL_UNUSED_VAR(ref);
13476     PERL_UNUSED_VAR(ix);
13477     exception=AcquireExceptionInfo();
13478     perl_exception=newSVpv("",0);
13479     EXTEND(sp,8*items);
13480     for (i=1; i < items; i++)
13481     {
13482       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13483         SvPV(ST(i),na));
13484       options=GetCommandOptions((CommandOption) option);
13485       if (options == (char **) NULL)
13486         PUSHs(&sv_undef);
13487       else
13488         {
13489           for (j=0; options[j] != (char *) NULL; j++)
13490             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13491           options=DestroyStringList(options);
13492         }
13493     }
13494
13495     InheritPerlException(exception,perl_exception);
13496     exception=DestroyExceptionInfo(exception);
13497     SvREFCNT_dec(perl_exception);
13498   }
13499 \f
13500 #
13501 ###############################################################################
13502 #                                                                             #
13503 #                                                                             #
13504 #                                                                             #
13505 #   R e a d                                                                   #
13506 #                                                                             #
13507 #                                                                             #
13508 #                                                                             #
13509 ###############################################################################
13510 #
13511 #
13512 void
13513 Read(ref,...)
13514   Image::Magick ref=NO_INIT
13515   ALIAS:
13516     ReadImage  = 1
13517     read       = 2
13518     readimage  = 3
13519   PPCODE:
13520   {
13521     AV
13522       *av;
13523
13524     char
13525       **keep,
13526       **list;
13527
13528     ExceptionInfo
13529       *exception;
13530
13531     HV
13532       *hv;
13533
13534     Image
13535       *image;
13536
13537     int
13538       n;
13539
13540     MagickBooleanType
13541       status;
13542
13543     register char
13544       **p;
13545
13546     register ssize_t
13547       i;
13548
13549     ssize_t
13550       ac,
13551       number_images;
13552
13553     STRLEN
13554       *length;
13555
13556     struct PackageInfo
13557       *info,
13558       *package_info;
13559
13560     SV
13561       *perl_exception,  /* Perl variable for storing messages */
13562       *reference,
13563       *rv,
13564       *sv;
13565
13566     PERL_UNUSED_VAR(ref);
13567     PERL_UNUSED_VAR(ix);
13568     exception=AcquireExceptionInfo();
13569     perl_exception=newSVpv("",0);
13570     sv=NULL;
13571     package_info=(struct PackageInfo *) NULL;
13572     number_images=0;
13573     ac=(items < 2) ? 1 : items-1;
13574     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13575     keep=list;
13576     length=(STRLEN *) NULL;
13577     if (list == (char **) NULL)
13578       {
13579         ThrowPerlException(exception,ResourceLimitError,
13580           "MemoryAllocationFailed",PackageName);
13581         goto PerlException;
13582       }
13583     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13584     if (length == (STRLEN *) NULL)
13585       {
13586         ThrowPerlException(exception,ResourceLimitError,
13587           "MemoryAllocationFailed",PackageName);
13588         goto PerlException;
13589       }
13590     if (sv_isobject(ST(0)) == 0)
13591       {
13592         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13593           PackageName);
13594         goto PerlException;
13595       }
13596     reference=SvRV(ST(0));
13597     hv=SvSTASH(reference);
13598     if (SvTYPE(reference) != SVt_PVAV)
13599       {
13600         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13601           PackageName);
13602         goto PerlException;
13603       }
13604     av=(AV *) reference;
13605     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13606       exception);
13607     package_info=ClonePackageInfo(info,exception);
13608     n=1;
13609     if (items <= 1)
13610       *list=(char *) (*package_info->image_info->filename ?
13611         package_info->image_info->filename : "XC:black");
13612     else
13613       for (n=0, i=0; i < ac; i++)
13614       {
13615         list[n]=(char *) SvPV(ST(i+1),length[n]);
13616         if ((items >= 3) && strEQcase(list[n],"blob"))
13617           {
13618             void
13619               *blob;
13620
13621             i++;
13622             blob=(void *) (SvPV(ST(i+1),length[n]));
13623             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13624           }
13625         if ((items >= 3) && strEQcase(list[n],"filename"))
13626           continue;
13627         if ((items >= 3) && strEQcase(list[n],"file"))
13628           {
13629             FILE
13630               *file;
13631
13632             PerlIO
13633               *io_info;
13634
13635             i++;
13636             io_info=IoIFP(sv_2io(ST(i+1)));
13637             if (io_info == (PerlIO *) NULL)
13638               {
13639                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13640                   PackageName);
13641                 continue;
13642               }
13643             file=PerlIO_findFILE(io_info);
13644             if (file == (FILE *) NULL)
13645               {
13646                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13647                   PackageName);
13648                 continue;
13649               }
13650             SetImageInfoFile(package_info->image_info,file);
13651           }
13652         if ((items >= 3) && strEQcase(list[n],"magick"))
13653           continue;
13654         n++;
13655       }
13656     list[n]=(char *) NULL;
13657     keep=list;
13658     status=ExpandFilenames(&n,&list);
13659     if (status == MagickFalse)
13660       {
13661         ThrowPerlException(exception,ResourceLimitError,
13662           "MemoryAllocationFailed",PackageName);
13663         goto PerlException;
13664       }
13665     number_images=0;
13666     for (i=0; i < n; i++)
13667     {
13668       if ((package_info->image_info->file == (FILE *) NULL) &&
13669           (package_info->image_info->blob == (void *) NULL))
13670         image=ReadImages(package_info->image_info,list[i],exception);
13671       else
13672         {
13673           image=ReadImages(package_info->image_info,
13674             package_info->image_info->filename,exception);
13675           if (image != (Image *) NULL)
13676             DisassociateImageStream(image);
13677         }
13678       if (image == (Image *) NULL)
13679         break;
13680       for ( ; image; image=image->next)
13681       {
13682         AddImageToRegistry(sv,image);
13683         rv=newRV(sv);
13684         av_push(av,sv_bless(rv,hv));
13685         SvREFCNT_dec(sv);
13686         number_images++;
13687       }
13688     }
13689     /*
13690       Free resources.
13691     */
13692     for (i=0; i < n; i++)
13693       if (list[i] != (char *) NULL)
13694         for (p=keep; list[i] != *p++; )
13695           if (*p == (char *) NULL)
13696             {
13697               list[i]=(char *) RelinquishMagickMemory(list[i]);
13698               break;
13699             }
13700
13701   PerlException:
13702     if (package_info != (struct PackageInfo *) NULL)
13703       DestroyPackageInfo(package_info);
13704     if (list && (list != keep))
13705       list=(char **) RelinquishMagickMemory(list);
13706     if (keep)
13707       keep=(char **) RelinquishMagickMemory(keep);
13708     if (length)
13709       length=(STRLEN *) RelinquishMagickMemory(length);
13710     InheritPerlException(exception,perl_exception);
13711     exception=DestroyExceptionInfo(exception);
13712     sv_setiv(perl_exception,(IV) number_images);
13713     SvPOK_on(perl_exception);
13714     ST(0)=sv_2mortal(perl_exception);
13715     XSRETURN(1);
13716   }
13717 \f
13718 #
13719 ###############################################################################
13720 #                                                                             #
13721 #                                                                             #
13722 #                                                                             #
13723 #   R e m o t e                                                               #
13724 #                                                                             #
13725 #                                                                             #
13726 #                                                                             #
13727 ###############################################################################
13728 #
13729 #
13730 void
13731 Remote(ref,...)
13732   Image::Magick ref=NO_INIT
13733   ALIAS:
13734     RemoteCommand  = 1
13735     remote         = 2
13736     remoteCommand  = 3
13737   PPCODE:
13738   {
13739     AV
13740       *av;
13741
13742     ExceptionInfo
13743       *exception;
13744
13745     register ssize_t
13746       i;
13747
13748     SV
13749       *perl_exception,
13750       *reference;
13751
13752     struct PackageInfo
13753       *info;
13754
13755     PERL_UNUSED_VAR(ref);
13756     PERL_UNUSED_VAR(ix);
13757     exception=AcquireExceptionInfo();
13758     perl_exception=newSVpv("",0);
13759     reference=SvRV(ST(0));
13760     av=(AV *) reference;
13761     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13762       exception);
13763     for (i=1; i < items; i++)
13764       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13765         SvPV(ST(i),na),exception);
13766     InheritPerlException(exception,perl_exception);
13767     exception=DestroyExceptionInfo(exception);
13768     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13769   }
13770 \f
13771 #
13772 ###############################################################################
13773 #                                                                             #
13774 #                                                                             #
13775 #                                                                             #
13776 #   S e t                                                                     #
13777 #                                                                             #
13778 #                                                                             #
13779 #                                                                             #
13780 ###############################################################################
13781 #
13782 #
13783 void
13784 Set(ref,...)
13785   Image::Magick ref=NO_INIT
13786   ALIAS:
13787     SetAttributes  = 1
13788     SetAttribute   = 2
13789     set            = 3
13790     setattributes  = 4
13791     setattribute   = 5
13792   PPCODE:
13793   {
13794     ExceptionInfo
13795       *exception;
13796
13797     Image
13798       *image;
13799
13800     register ssize_t
13801       i;
13802
13803     struct PackageInfo
13804       *info;
13805
13806     SV
13807       *perl_exception,
13808       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13809
13810     PERL_UNUSED_VAR(ref);
13811     PERL_UNUSED_VAR(ix);
13812     exception=AcquireExceptionInfo();
13813     perl_exception=newSVpv("",0);
13814     if (sv_isobject(ST(0)) == 0)
13815       {
13816         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13817           PackageName);
13818         goto PerlException;
13819       }
13820     reference=SvRV(ST(0));
13821     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13822     if (items == 2)
13823       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13824     else
13825       for (i=2; i < items; i+=2)
13826         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13827
13828   PerlException:
13829     InheritPerlException(exception,perl_exception);
13830     exception=DestroyExceptionInfo(exception);
13831     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13832     SvPOK_on(perl_exception);
13833     ST(0)=sv_2mortal(perl_exception);
13834     XSRETURN(1);
13835   }
13836 \f
13837 #
13838 ###############################################################################
13839 #                                                                             #
13840 #                                                                             #
13841 #                                                                             #
13842 #   S e t P i x e l                                                           #
13843 #                                                                             #
13844 #                                                                             #
13845 #                                                                             #
13846 ###############################################################################
13847 #
13848 #
13849 void
13850 SetPixel(ref,...)
13851   Image::Magick ref=NO_INIT
13852   ALIAS:
13853     setpixel = 1
13854     setPixel = 2
13855   PPCODE:
13856   {
13857     AV
13858       *av;
13859
13860     char
13861       *attribute;
13862
13863     ChannelType
13864       channel,
13865       channel_mask;
13866
13867     ExceptionInfo
13868       *exception;
13869
13870     Image
13871       *image;
13872
13873     MagickBooleanType
13874       normalize;
13875
13876     RectangleInfo
13877       region;
13878
13879     register ssize_t
13880       i;
13881
13882     register Quantum
13883       *q;
13884
13885     ssize_t
13886       option;
13887
13888     struct PackageInfo
13889       *info;
13890
13891     SV
13892       *perl_exception,
13893       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13894
13895     PERL_UNUSED_VAR(ref);
13896     PERL_UNUSED_VAR(ix);
13897     exception=AcquireExceptionInfo();
13898     perl_exception=newSVpv("",0);
13899     reference=SvRV(ST(0));
13900     av=(AV *) reference;
13901     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13902       exception);
13903     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13904     if (image == (Image *) NULL)
13905       {
13906         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13907           PackageName);
13908         goto PerlException;
13909       }
13910     av=(AV *) NULL;
13911     normalize=MagickTrue;
13912     region.x=0;
13913     region.y=0;
13914     region.width=image->columns;
13915     region.height=1;
13916     if (items == 1)
13917       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13918     channel=DefaultChannels;
13919     for (i=2; i < items; i+=2)
13920     {
13921       attribute=(char *) SvPV(ST(i-1),na);
13922       switch (*attribute)
13923       {
13924         case 'C':
13925         case 'c':
13926         {
13927           if (LocaleCompare(attribute,"channel") == 0)
13928             {
13929               ssize_t
13930                 option;
13931
13932               option=ParseChannelOption(SvPV(ST(i),na));
13933               if (option < 0)
13934                 {
13935                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13936                     SvPV(ST(i),na));
13937                   return;
13938                 }
13939               channel=(ChannelType) option;
13940               break;
13941             }
13942           if (LocaleCompare(attribute,"color") == 0)
13943             {
13944               if (SvTYPE(ST(i)) != SVt_RV)
13945                 {
13946                   char
13947                     message[MagickPathExtent];
13948
13949                   (void) FormatLocaleString(message,MagickPathExtent,
13950                     "invalid %.60s value",attribute);
13951                   ThrowPerlException(exception,OptionError,message,
13952                     SvPV(ST(i),na));
13953                 }
13954               av=(AV *) SvRV(ST(i));
13955               break;
13956             }
13957           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13958             attribute);
13959           break;
13960         }
13961         case 'g':
13962         case 'G':
13963         {
13964           if (LocaleCompare(attribute,"geometry") == 0)
13965             {
13966               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13967               break;
13968             }
13969           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13970             attribute);
13971           break;
13972         }
13973         case 'N':
13974         case 'n':
13975         {
13976           if (LocaleCompare(attribute,"normalize") == 0)
13977             {
13978               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13979                 SvPV(ST(i),na));
13980               if (option < 0)
13981                 {
13982                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13983                     SvPV(ST(i),na));
13984                   break;
13985                 }
13986              normalize=option != 0 ? MagickTrue : MagickFalse;
13987              break;
13988             }
13989           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13990             attribute);
13991           break;
13992         }
13993         case 'x':
13994         case 'X':
13995         {
13996           if (LocaleCompare(attribute,"x") == 0)
13997             {
13998               region.x=SvIV(ST(i));
13999               break;
14000             }
14001           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14002             attribute);
14003           break;
14004         }
14005         case 'y':
14006         case 'Y':
14007         {
14008           if (LocaleCompare(attribute,"y") == 0)
14009             {
14010               region.y=SvIV(ST(i));
14011               break;
14012             }
14013           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14014             attribute);
14015           break;
14016         }
14017         default:
14018         {
14019           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14020             attribute);
14021           break;
14022         }
14023       }
14024     }
14025     (void) SetImageStorageClass(image,DirectClass,exception);
14026     channel_mask=SetImageChannelMask(image,channel);
14027     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14028     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14029         (SvTYPE(av) != SVt_PVAV))
14030       PUSHs(&sv_undef);
14031     else
14032       {
14033         double
14034           scale;
14035
14036         register ssize_t
14037           i;
14038
14039         i=0;
14040         scale=1.0;
14041         if (normalize != MagickFalse)
14042           scale=QuantumRange;
14043         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14044             (i <= av_len(av)))
14045           {
14046             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14047               av_fetch(av,i,0)))),q);
14048             i++;
14049           }
14050         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14051             (i <= av_len(av)))
14052           {
14053             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14054               av_fetch(av,i,0)))),q);
14055             i++;
14056           }
14057         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14058             (i <= av_len(av)))
14059           {
14060             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14061               av_fetch(av,i,0)))),q);
14062             i++;
14063           }
14064         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14065             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14066           {
14067             SetPixelBlack(image,ClampToQuantum(scale*
14068               SvNV(*(av_fetch(av,i,0)))),q);
14069             i++;
14070           }
14071         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14072             (i <= av_len(av)))
14073           {
14074             SetPixelAlpha(image,ClampToQuantum(scale*
14075               SvNV(*(av_fetch(av,i,0)))),q);
14076             i++;
14077           }
14078         (void) SyncAuthenticPixels(image,exception);
14079       }
14080     (void) SetImageChannelMask(image,channel_mask);
14081
14082   PerlException:
14083     InheritPerlException(exception,perl_exception);
14084     exception=DestroyExceptionInfo(exception);
14085     SvREFCNT_dec(perl_exception);
14086   }
14087 \f
14088 #
14089 ###############################################################################
14090 #                                                                             #
14091 #                                                                             #
14092 #                                                                             #
14093 #   S m u s h                                                                 #
14094 #                                                                             #
14095 #                                                                             #
14096 #                                                                             #
14097 ###############################################################################
14098 #
14099 #
14100 void
14101 Smush(ref,...)
14102   Image::Magick ref=NO_INIT
14103   ALIAS:
14104     SmushImage  = 1
14105     smush       = 2
14106     smushimage  = 3
14107   PPCODE:
14108   {
14109     AV
14110       *av;
14111
14112     char
14113       *attribute;
14114
14115     ExceptionInfo
14116       *exception;
14117
14118     HV
14119       *hv;
14120
14121     Image
14122       *image;
14123
14124     register ssize_t
14125       i;
14126
14127     ssize_t
14128       offset,
14129       stack;
14130
14131     struct PackageInfo
14132       *info;
14133
14134     SV
14135       *av_reference,
14136       *perl_exception,
14137       *reference,
14138       *rv,
14139       *sv;
14140
14141     PERL_UNUSED_VAR(ref);
14142     PERL_UNUSED_VAR(ix);
14143     exception=AcquireExceptionInfo();
14144     perl_exception=newSVpv("",0);
14145     sv=NULL;
14146     attribute=NULL;
14147     av=NULL;
14148     if (sv_isobject(ST(0)) == 0)
14149       {
14150         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14151           PackageName);
14152         goto PerlException;
14153       }
14154     reference=SvRV(ST(0));
14155     hv=SvSTASH(reference);
14156     av=newAV();
14157     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14158     SvREFCNT_dec(av);
14159     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14160     if (image == (Image *) NULL)
14161       {
14162         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14163           PackageName);
14164         goto PerlException;
14165       }
14166     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14167     /*
14168       Get options.
14169     */
14170     offset=0;
14171     stack=MagickTrue;
14172     for (i=2; i < items; i+=2)
14173     {
14174       attribute=(char *) SvPV(ST(i-1),na);
14175       switch (*attribute)
14176       {
14177         case 'O':
14178         case 'o':
14179         {
14180           if (LocaleCompare(attribute,"offset") == 0)
14181             {
14182               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14183               break;
14184             }
14185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14186             attribute);
14187           break;
14188         }
14189         case 'S':
14190         case 's':
14191         {
14192           if (LocaleCompare(attribute,"stack") == 0)
14193             {
14194               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14195                 SvPV(ST(i),na));
14196               if (stack < 0)
14197                 {
14198                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14199                     SvPV(ST(i),na));
14200                   return;
14201                 }
14202               break;
14203             }
14204           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14205             attribute);
14206           break;
14207         }
14208         default:
14209         {
14210           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14211             attribute);
14212           break;
14213         }
14214       }
14215     }
14216     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14217       exception);
14218     if (image == (Image *) NULL)
14219       goto PerlException;
14220     for ( ; image; image=image->next)
14221     {
14222       AddImageToRegistry(sv,image);
14223       rv=newRV(sv);
14224       av_push(av,sv_bless(rv,hv));
14225       SvREFCNT_dec(sv);
14226     }
14227     exception=DestroyExceptionInfo(exception);
14228     ST(0)=av_reference;
14229     SvREFCNT_dec(perl_exception);
14230     XSRETURN(1);
14231
14232   PerlException:
14233     InheritPerlException(exception,perl_exception);
14234     exception=DestroyExceptionInfo(exception);
14235     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14236     SvPOK_on(perl_exception);
14237     ST(0)=sv_2mortal(perl_exception);
14238     XSRETURN(1);
14239   }
14240 \f
14241 #
14242 ###############################################################################
14243 #                                                                             #
14244 #                                                                             #
14245 #                                                                             #
14246 #   S t a t i s t i c s                                                       #
14247 #                                                                             #
14248 #                                                                             #
14249 #                                                                             #
14250 ###############################################################################
14251 #
14252 #
14253 void
14254 Statistics(ref,...)
14255   Image::Magick ref=NO_INIT
14256   ALIAS:
14257     StatisticsImage = 1
14258     statistics      = 2
14259     statisticsimage = 3
14260   PPCODE:
14261   {
14262 #define ChannelStatistics(channel) \
14263 { \
14264   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14265     (double) channel_statistics[channel].depth); \
14266   PUSHs(sv_2mortal(newSVpv(message,0))); \
14267   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14268     channel_statistics[channel].minima/scale); \
14269   PUSHs(sv_2mortal(newSVpv(message,0))); \
14270   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14271     channel_statistics[channel].maxima/scale); \
14272   PUSHs(sv_2mortal(newSVpv(message,0))); \
14273   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14274     channel_statistics[channel].mean/scale); \
14275   PUSHs(sv_2mortal(newSVpv(message,0))); \
14276   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14277     channel_statistics[channel].standard_deviation/scale); \
14278   PUSHs(sv_2mortal(newSVpv(message,0))); \
14279   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14280     channel_statistics[channel].kurtosis); \
14281   PUSHs(sv_2mortal(newSVpv(message,0))); \
14282   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14283     channel_statistics[channel].skewness); \
14284   PUSHs(sv_2mortal(newSVpv(message,0))); \
14285   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14286     channel_statistics[channel].entropy); \
14287   PUSHs(sv_2mortal(newSVpv(message,0))); \
14288 }
14289
14290     AV
14291       *av;
14292
14293     char
14294       message[MagickPathExtent];
14295
14296     ChannelStatistics
14297       *channel_statistics;
14298
14299     double
14300       scale;
14301
14302     ExceptionInfo
14303       *exception;
14304
14305     Image
14306       *image;
14307
14308     ssize_t
14309       count;
14310
14311     struct PackageInfo
14312       *info;
14313
14314     SV
14315       *perl_exception,
14316       *reference;
14317
14318     PERL_UNUSED_VAR(ref);
14319     PERL_UNUSED_VAR(ix);
14320     exception=AcquireExceptionInfo();
14321     perl_exception=newSVpv("",0);
14322     av=NULL;
14323     if (sv_isobject(ST(0)) == 0)
14324       {
14325         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14326           PackageName);
14327         goto PerlException;
14328       }
14329     reference=SvRV(ST(0));
14330     av=newAV();
14331     SvREFCNT_dec(av);
14332     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14333     if (image == (Image *) NULL)
14334       {
14335         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14336           PackageName);
14337         goto PerlException;
14338       }
14339     count=0;
14340     for ( ; image; image=image->next)
14341     {
14342       channel_statistics=GetImageStatistics(image,exception);
14343       if (channel_statistics == (ChannelStatistics *) NULL)
14344         continue;
14345       count++;
14346       EXTEND(sp,35*count);
14347       scale=(double) QuantumRange;
14348       ChannelStatistics(RedChannel);
14349       ChannelStatistics(GreenChannel);
14350       ChannelStatistics(BlueChannel);
14351       if (image->colorspace == CMYKColorspace)
14352         ChannelStatistics(BlackChannel);
14353       if (image->alpha_trait != UndefinedPixelTrait)
14354         ChannelStatistics(AlphaChannel);
14355       channel_statistics=(ChannelStatistics *)
14356         RelinquishMagickMemory(channel_statistics);
14357     }
14358
14359   PerlException:
14360     InheritPerlException(exception,perl_exception);
14361     exception=DestroyExceptionInfo(exception);
14362     SvREFCNT_dec(perl_exception);
14363   }
14364 \f
14365 #
14366 ###############################################################################
14367 #                                                                             #
14368 #                                                                             #
14369 #                                                                             #
14370 #   S y n c A u t h e n t i c P i x e l s                                     #
14371 #                                                                             #
14372 #                                                                             #
14373 #                                                                             #
14374 ###############################################################################
14375 #
14376 #
14377 void
14378 SyncAuthenticPixels(ref,...)
14379   Image::Magick ref = NO_INIT
14380   ALIAS:
14381     Syncauthenticpixels = 1
14382     SyncImagePixels = 2
14383     syncimagepixels = 3
14384   CODE:
14385   {
14386     ExceptionInfo
14387       *exception;
14388
14389     Image
14390       *image;
14391
14392     MagickBooleanType
14393       status;
14394
14395     struct PackageInfo
14396       *info;
14397
14398     SV
14399       *perl_exception,
14400       *reference;
14401
14402     PERL_UNUSED_VAR(ref);
14403     PERL_UNUSED_VAR(ix);
14404     exception=AcquireExceptionInfo();
14405     perl_exception=newSVpv("",0);
14406     if (sv_isobject(ST(0)) == 0)
14407       {
14408         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14409           PackageName);
14410         goto PerlException;
14411       }
14412
14413     reference=SvRV(ST(0));
14414     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14415     if (image == (Image *) NULL)
14416       {
14417         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14418           PackageName);
14419         goto PerlException;
14420       }
14421
14422     status=SyncAuthenticPixels(image,exception);
14423     if (status != MagickFalse)
14424       return;
14425
14426   PerlException:
14427     InheritPerlException(exception,perl_exception);
14428     exception=DestroyExceptionInfo(exception);
14429     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14430   }
14431 \f
14432 #
14433 ###############################################################################
14434 #                                                                             #
14435 #                                                                             #
14436 #                                                                             #
14437 #   T r a n s f o r m                                                         #
14438 #                                                                             #
14439 #                                                                             #
14440 #                                                                             #
14441 ###############################################################################
14442 #
14443 #
14444 void
14445 Transform(ref,...)
14446   Image::Magick ref=NO_INIT
14447   ALIAS:
14448     TransformImage = 1
14449     transform      = 2
14450     transformimage = 3
14451   PPCODE:
14452   {
14453     AV
14454       *av;
14455
14456     char
14457       *attribute,
14458       *crop_geometry,
14459       *geometry;
14460
14461     ExceptionInfo
14462       *exception;
14463
14464     HV
14465       *hv;
14466
14467     Image
14468       *clone,
14469       *image;
14470
14471     register ssize_t
14472       i;
14473
14474     struct PackageInfo
14475       *info;
14476
14477     SV
14478       *av_reference,
14479       *perl_exception,
14480       *reference,
14481       *rv,
14482       *sv;
14483
14484     PERL_UNUSED_VAR(ref);
14485     PERL_UNUSED_VAR(ix);
14486     exception=AcquireExceptionInfo();
14487     perl_exception=newSVpv("",0);
14488     sv=NULL;
14489     av=NULL;
14490     attribute=NULL;
14491     if (sv_isobject(ST(0)) == 0)
14492       {
14493         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14494           PackageName);
14495         goto PerlException;
14496       }
14497     reference=SvRV(ST(0));
14498     hv=SvSTASH(reference);
14499     av=newAV();
14500     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14501     SvREFCNT_dec(av);
14502     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14503     if (image == (Image *) NULL)
14504       {
14505         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14506           PackageName);
14507         goto PerlException;
14508       }
14509     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14510     /*
14511       Get attribute.
14512     */
14513     crop_geometry=(char *) NULL;
14514     geometry=(char *) NULL;
14515     for (i=2; i < items; i+=2)
14516     {
14517       attribute=(char *) SvPV(ST(i-1),na);
14518       switch (*attribute)
14519       {
14520         case 'c':
14521         case 'C':
14522         {
14523           if (LocaleCompare(attribute,"crop") == 0)
14524             {
14525               crop_geometry=SvPV(ST(i),na);
14526               break;
14527             }
14528           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14529             attribute);
14530           break;
14531         }
14532         case 'g':
14533         case 'G':
14534         {
14535           if (LocaleCompare(attribute,"geometry") == 0)
14536             {
14537               geometry=SvPV(ST(i),na);
14538               break;
14539             }
14540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14541             attribute);
14542           break;
14543         }
14544         default:
14545         {
14546           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14547             attribute);
14548           break;
14549         }
14550       }
14551     }
14552     for ( ; image; image=image->next)
14553     {
14554       clone=CloneImage(image,0,0,MagickTrue,exception);
14555       if (clone == (Image *) NULL)
14556         goto PerlException;
14557       TransformImage(&clone,crop_geometry,geometry,exception);
14558       for ( ; clone; clone=clone->next)
14559       {
14560         AddImageToRegistry(sv,clone);
14561         rv=newRV(sv);
14562         av_push(av,sv_bless(rv,hv));
14563         SvREFCNT_dec(sv);
14564       }
14565     }
14566     exception=DestroyExceptionInfo(exception);
14567     ST(0)=av_reference;
14568     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14569     XSRETURN(1);
14570
14571   PerlException:
14572     InheritPerlException(exception,perl_exception);
14573     exception=DestroyExceptionInfo(exception);
14574     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14575     SvPOK_on(perl_exception);
14576     ST(0)=sv_2mortal(perl_exception);
14577     XSRETURN(1);
14578   }
14579 \f
14580 #
14581 ###############################################################################
14582 #                                                                             #
14583 #                                                                             #
14584 #                                                                             #
14585 #   W r i t e                                                                 #
14586 #                                                                             #
14587 #                                                                             #
14588 #                                                                             #
14589 ###############################################################################
14590 #
14591 #
14592 void
14593 Write(ref,...)
14594   Image::Magick ref=NO_INIT
14595   ALIAS:
14596     WriteImage    = 1
14597     write         = 2
14598     writeimage    = 3
14599   PPCODE:
14600   {
14601     char
14602       filename[MagickPathExtent];
14603
14604     ExceptionInfo
14605       *exception;
14606
14607     Image
14608       *image,
14609       *next;
14610
14611     register ssize_t
14612       i;
14613
14614     ssize_t
14615       number_images,
14616       scene;
14617
14618     struct PackageInfo
14619       *info,
14620       *package_info;
14621
14622     SV
14623       *perl_exception,
14624       *reference;
14625
14626     PERL_UNUSED_VAR(ref);
14627     PERL_UNUSED_VAR(ix);
14628     exception=AcquireExceptionInfo();
14629     perl_exception=newSVpv("",0);
14630     number_images=0;
14631     package_info=(struct PackageInfo *) NULL;
14632     if (sv_isobject(ST(0)) == 0)
14633       {
14634         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14635           PackageName);
14636         goto PerlException;
14637       }
14638     reference=SvRV(ST(0));
14639     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14640     if (image == (Image *) NULL)
14641       {
14642         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14643           PackageName);
14644         goto PerlException;
14645       }
14646     package_info=ClonePackageInfo(info,exception);
14647     if (items == 2)
14648       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14649     else
14650       if (items > 2)
14651         for (i=2; i < items; i+=2)
14652           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14653             exception);
14654     (void) CopyMagickString(filename,package_info->image_info->filename,
14655       MagickPathExtent);
14656     scene=0;
14657     for (next=image; next; next=next->next)
14658     {
14659       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14660       next->scene=scene++;
14661     }
14662     *package_info->image_info->magick='\0';
14663     SetImageInfo(package_info->image_info,(unsigned int)
14664       GetImageListLength(image),exception);
14665     for (next=image; next; next=next->next)
14666     {
14667       (void) WriteImage(package_info->image_info,next,exception);
14668       number_images++;
14669       if (package_info->image_info->adjoin)
14670         break;
14671     }
14672
14673   PerlException:
14674     if (package_info != (struct PackageInfo *) NULL)
14675       DestroyPackageInfo(package_info);
14676     InheritPerlException(exception,perl_exception);
14677     exception=DestroyExceptionInfo(exception);
14678     sv_setiv(perl_exception,(IV) number_images);
14679     SvPOK_on(perl_exception);
14680     ST(0)=sv_2mortal(perl_exception);
14681     XSRETURN(1);
14682   }