]> granicus.if.org Git - imagemagick/blob - PerlMagick/quantum/quantum.xs.in
(no commit message)
[imagemagick] / PerlMagick / quantum / quantum.xs.in
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 "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.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::@MAGICK_ABI_SUFFIX@"
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__@MAGICK_ABI_SUFFIX@;  /* data type for the Image::Magick::@MAGICK_ABI_NAME@ 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       {"double", RealReference} } },
556     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
557       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
558     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
559   };
560
561 static SplayTreeInfo
562   *magick_registry = (SplayTreeInfo *) NULL;
563 \f
564 /*
565   Forward declarations.
566 */
567 static Image
568   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
569
570 static ssize_t
571   strEQcase(const char *,const char *);
572 \f
573 /*
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 %                                                                             %
576 %                                                                             %
577 %                                                                             %
578 %   C l o n e P a c k a g e I n f o                                           %
579 %                                                                             %
580 %                                                                             %
581 %                                                                             %
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 %
584 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
585 %  a new one.
586 %
587 %  The format of the ClonePackageInfo routine is:
588 %
589 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
590 %        exception)
591 %
592 %  A description of each parameter follows:
593 %
594 %    o info: a structure of type info.
595 %
596 %    o exception: Return any errors or warnings in this structure.
597 %
598 */
599 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
600   ExceptionInfo *exception)
601 {
602   struct PackageInfo
603     *clone_info;
604
605   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
606   if (clone_info == (struct PackageInfo *) NULL)
607     {
608       ThrowPerlException(exception,ResourceLimitError,
609         "UnableToClonePackageInfo",PackageName);
610       return((struct PackageInfo *) NULL);
611     }
612   if (info == (struct PackageInfo *) NULL)
613     {
614       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
615       return(clone_info);
616     }
617   *clone_info=(*info);
618   clone_info->image_info=CloneImageInfo(info->image_info);
619   return(clone_info);
620 }
621 \f
622 /*
623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624 %                                                                             %
625 %                                                                             %
626 %                                                                             %
627 %   c o n s t a n t                                                           %
628 %                                                                             %
629 %                                                                             %
630 %                                                                             %
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 %
633 %  constant() returns a double value for the specified name.
634 %
635 %  The format of the constant routine is:
636 %
637 %      double constant(char *name,ssize_t sans)
638 %
639 %  A description of each parameter follows:
640 %
641 %    o value: Method constant returns a double value for the specified name.
642 %
643 %    o name: The name of the constant.
644 %
645 %    o sans: This integer value is not used.
646 %
647 */
648 static double constant(char *name,ssize_t sans)
649 {
650   (void) sans;
651   errno=0;
652   switch (*name)
653   {
654     case 'B':
655     {
656       if (strEQ(name,"BlobError"))
657         return(BlobError);
658       if (strEQ(name,"BlobWarning"))
659         return(BlobWarning);
660       break;
661     }
662     case 'C':
663     {
664       if (strEQ(name,"CacheError"))
665         return(CacheError);
666       if (strEQ(name,"CacheWarning"))
667         return(CacheWarning);
668       if (strEQ(name,"CoderError"))
669         return(CoderError);
670       if (strEQ(name,"CoderWarning"))
671         return(CoderWarning);
672       if (strEQ(name,"ConfigureError"))
673         return(ConfigureError);
674       if (strEQ(name,"ConfigureWarning"))
675         return(ConfigureWarning);
676       if (strEQ(name,"CorruptImageError"))
677         return(CorruptImageError);
678       if (strEQ(name,"CorruptImageWarning"))
679         return(CorruptImageWarning);
680       break;
681     }
682     case 'D':
683     {
684       if (strEQ(name,"DelegateError"))
685         return(DelegateError);
686       if (strEQ(name,"DelegateWarning"))
687         return(DelegateWarning);
688       if (strEQ(name,"DrawError"))
689         return(DrawError);
690       if (strEQ(name,"DrawWarning"))
691         return(DrawWarning);
692       break;
693     }
694     case 'E':
695     {
696       if (strEQ(name,"ErrorException"))
697         return(ErrorException);
698       if (strEQ(name,"ExceptionError"))
699         return(CoderError);
700       if (strEQ(name,"ExceptionWarning"))
701         return(CoderWarning);
702       break;
703     }
704     case 'F':
705     {
706       if (strEQ(name,"FatalErrorException"))
707         return(FatalErrorException);
708       if (strEQ(name,"FileOpenError"))
709         return(FileOpenError);
710       if (strEQ(name,"FileOpenWarning"))
711         return(FileOpenWarning);
712       break;
713     }
714     case 'I':
715     {
716       if (strEQ(name,"ImageError"))
717         return(ImageError);
718       if (strEQ(name,"ImageWarning"))
719         return(ImageWarning);
720       break;
721     }
722     case 'M':
723     {
724       if (strEQ(name,"MaxRGB"))
725         return(QuantumRange);
726       if (strEQ(name,"MissingDelegateError"))
727         return(MissingDelegateError);
728       if (strEQ(name,"MissingDelegateWarning"))
729         return(MissingDelegateWarning);
730       if (strEQ(name,"ModuleError"))
731         return(ModuleError);
732       if (strEQ(name,"ModuleWarning"))
733         return(ModuleWarning);
734       break;
735     }
736     case 'O':
737     {
738       if (strEQ(name,"Opaque"))
739         return(OpaqueAlpha);
740       if (strEQ(name,"OptionError"))
741         return(OptionError);
742       if (strEQ(name,"OptionWarning"))
743         return(OptionWarning);
744       break;
745     }
746     case 'Q':
747     {
748       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
749         return(MAGICKCORE_QUANTUM_DEPTH);
750       if (strEQ(name,"QuantumDepth"))
751         return(MAGICKCORE_QUANTUM_DEPTH);
752       if (strEQ(name,"QuantumRange"))
753         return(QuantumRange);
754       break;
755     }
756     case 'R':
757     {
758       if (strEQ(name,"ResourceLimitError"))
759         return(ResourceLimitError);
760       if (strEQ(name,"ResourceLimitWarning"))
761         return(ResourceLimitWarning);
762       if (strEQ(name,"RegistryError"))
763         return(RegistryError);
764       if (strEQ(name,"RegistryWarning"))
765         return(RegistryWarning);
766       break;
767     }
768     case 'S':
769     {
770       if (strEQ(name,"StreamError"))
771         return(StreamError);
772       if (strEQ(name,"StreamWarning"))
773         return(StreamWarning);
774       if (strEQ(name,"Success"))
775         return(0);
776       break;
777     }
778     case 'T':
779     {
780       if (strEQ(name,"Transparent"))
781         return(TransparentAlpha);
782       if (strEQ(name,"TypeError"))
783         return(TypeError);
784       if (strEQ(name,"TypeWarning"))
785         return(TypeWarning);
786       break;
787     }
788     case 'W':
789     {
790       if (strEQ(name,"WarningException"))
791         return(WarningException);
792       break;
793     }
794     case 'X':
795     {
796       if (strEQ(name,"XServerError"))
797         return(XServerError);
798       if (strEQ(name,"XServerWarning"))
799         return(XServerWarning);
800       break;
801     }
802   }
803   errno=EINVAL;
804   return(0);
805 }
806 \f
807 /*
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
809 %                                                                             %
810 %                                                                             %
811 %                                                                             %
812 %   D e s t r o y P a c k a g e I n f o                                       %
813 %                                                                             %
814 %                                                                             %
815 %                                                                             %
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %
818 %  Method DestroyPackageInfo frees a previously created info structure.
819 %
820 %  The format of the DestroyPackageInfo routine is:
821 %
822 %      DestroyPackageInfo(struct PackageInfo *info)
823 %
824 %  A description of each parameter follows:
825 %
826 %    o info: a structure of type info.
827 %
828 */
829 static void DestroyPackageInfo(struct PackageInfo *info)
830 {
831   info->image_info=DestroyImageInfo(info->image_info);
832   info=(struct PackageInfo *) RelinquishMagickMemory(info);
833 }
834 \f
835 /*
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 %                                                                             %
838 %                                                                             %
839 %                                                                             %
840 %   G e t L i s t                                                             %
841 %                                                                             %
842 %                                                                             %
843 %                                                                             %
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845 %
846 %  Method GetList is recursively called by SetupList to traverse the
847 %  Image__Magick reference.  If building an reference_vector (see SetupList),
848 %  *current is the current position in *reference_vector and *last is the final
849 %  entry in *reference_vector.
850 %
851 %  The format of the GetList routine is:
852 %
853 %      GetList(info)
854 %
855 %  A description of each parameter follows:
856 %
857 %    o info: a structure of type info.
858 %
859 */
860 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
861   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
862 {
863   Image
864     *image;
865
866   if (reference == (SV *) NULL)
867     return(NULL);
868   switch (SvTYPE(reference))
869   {
870     case SVt_PVAV:
871     {
872       AV
873         *av;
874
875       Image
876         *head,
877         *previous;
878
879       register ssize_t
880         i;
881
882       ssize_t
883         n;
884
885       /*
886         Array of images.
887       */
888       previous=(Image *) NULL;
889       head=(Image *) NULL;
890       av=(AV *) reference;
891       n=av_len(av);
892       for (i=0; i <= n; i++)
893       {
894         SV
895           **rv;
896
897         rv=av_fetch(av,i,0);
898         if (rv && *rv && sv_isobject(*rv))
899           {
900             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
901               exception);
902             if (image == (Image *) NULL)
903               continue;
904             if (image == previous)
905               {
906                 image=CloneImage(image,0,0,MagickTrue,exception);
907                 if (image == (Image *) NULL)
908                   return(NULL);
909               }
910             image->previous=previous;
911             *(previous ? &previous->next : &head)=image;
912             for (previous=image; previous->next; previous=previous->next) ;
913           }
914       }
915       return(head);
916     }
917     case SVt_PVMG:
918     {
919       /*
920         Blessed scalar, one image.
921       */
922       image=INT2PTR(Image *,SvIV(reference));
923       if (image == (Image *) NULL)
924         return(NULL);
925       image->previous=(Image *) NULL;
926       image->next=(Image *) NULL;
927       if (reference_vector)
928         {
929           if (*current == *last)
930             {
931               *last+=256;
932               if (*reference_vector == (SV **) NULL)
933                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
934                   sizeof(*reference_vector));
935               else
936                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
937                   *last,sizeof(*reference_vector));
938             }
939           if (*reference_vector == (SV **) NULL)
940             {
941               ThrowPerlException(exception,ResourceLimitError,
942                 "MemoryAllocationFailed",PackageName);
943               return((Image *) NULL);
944             }
945           (*reference_vector)[*current]=reference;
946           (*reference_vector)[++(*current)]=NULL;
947         }
948       return(image);
949     }
950     default:
951       break;
952   }
953   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
954     (double) SvTYPE(reference));
955   return((Image *) NULL);
956 }
957 \f
958 /*
959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
960 %                                                                             %
961 %                                                                             %
962 %                                                                             %
963 %   G e t P a c k a g e I n f o                                               %
964 %                                                                             %
965 %                                                                             %
966 %                                                                             %
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 %
969 %  Method GetPackageInfo looks up or creates an info structure for the given
970 %  Image__Magick reference.  If it does create a new one, the information in
971 %  package_info is used to initialize it.
972 %
973 %  The format of the GetPackageInfo routine is:
974 %
975 %      struct PackageInfo *GetPackageInfo(void *reference,
976 %        struct PackageInfo *package_info,ExceptionInfo *exception)
977 %
978 %  A description of each parameter follows:
979 %
980 %    o info: a structure of type info.
981 %
982 %    o exception: Return any errors or warnings in this structure.
983 %
984 */
985 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
986   struct PackageInfo *package_info,ExceptionInfo *exception)
987 {
988   char
989     message[MagickPathExtent];
990
991   struct PackageInfo
992     *clone_info;
993
994   SV
995     *sv;
996
997   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
998     PackageName,XS_VERSION,reference);
999   sv=perl_get_sv(message,(TRUE | 0x02));
1000   if (sv == (SV *) NULL)
1001     {
1002       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1003         message);
1004       return(package_info);
1005     }
1006   if (SvREFCNT(sv) == 0)
1007     (void) SvREFCNT_inc(sv);
1008   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1009     return(clone_info);
1010   clone_info=ClonePackageInfo(package_info,exception);
1011   sv_setiv(sv,PTR2IV(clone_info));
1012   return(clone_info);
1013 }
1014 \f
1015 /*
1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1017 %                                                                             %
1018 %                                                                             %
1019 %                                                                             %
1020 %   S e t A t t r i b u t e                                                   %
1021 %                                                                             %
1022 %                                                                             %
1023 %                                                                             %
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 %
1026 %  SetAttribute() sets the attribute to the value in sval.  This can change
1027 %  either or both of image or info.
1028 %
1029 %  The format of the SetAttribute routine is:
1030 %
1031 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1032 %        SV *sval,ExceptionInfo *exception)
1033 %
1034 %  A description of each parameter follows:
1035 %
1036 %    o list: a list of strings.
1037 %
1038 %    o string: a character string.
1039 %
1040 */
1041
1042 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1043 {
1044   char
1045     *q;
1046
1047   double
1048     value;
1049
1050   value=InterpretSiPrefixValue(string,&q);
1051   if (*q == '%')
1052     value*=interval/100.0;
1053   return(value);
1054 }
1055
1056 static inline double StringToDouble(const char *string,char **sentinal)
1057 {
1058   return(InterpretLocaleValue(string,sentinal));
1059 }
1060
1061 static double StringToDoubleInterval(const char *string,const double interval)
1062 {
1063   char
1064     *q;
1065
1066   double
1067     value;
1068
1069   value=InterpretLocaleValue(string,&q);
1070   if (*q == '%')
1071     value*=interval/100.0;
1072   return(value);
1073 }
1074
1075 static inline ssize_t StringToLong(const char *value)
1076 {
1077   return(strtol(value,(char **) NULL,10));
1078 }
1079
1080 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1081   const char *attribute,SV *sval,ExceptionInfo *exception)
1082 {
1083   GeometryInfo
1084     geometry_info;
1085
1086   long
1087     x,
1088     y;
1089
1090   PixelInfo
1091     pixel;
1092
1093   MagickStatusType
1094     flags;
1095
1096   PixelInfo
1097     *color,
1098     target_color;
1099
1100   ssize_t
1101     sp;
1102
1103   switch (*attribute)
1104   {
1105     case 'A':
1106     case 'a':
1107     {
1108       if (LocaleCompare(attribute,"adjoin") == 0)
1109         {
1110           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1111             SvPV(sval,na)) : SvIV(sval);
1112           if (sp < 0)
1113             {
1114               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1115                 SvPV(sval,na));
1116               break;
1117             }
1118           if (info)
1119             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1120           break;
1121         }
1122       if (LocaleCompare(attribute,"alpha") == 0)
1123         {
1124           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1125             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1126           if (sp < 0)
1127             {
1128               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1129                 SvPV(sval,na));
1130               break;
1131             }
1132           for ( ; image; image=image->next)
1133             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1134               exception);
1135           break;
1136         }
1137       if (LocaleCompare(attribute,"antialias") == 0)
1138         {
1139           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1140             SvPV(sval,na)) : SvIV(sval);
1141           if (sp < 0)
1142             {
1143               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1144                 SvPV(sval,na));
1145               break;
1146             }
1147           if (info)
1148             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1149           break;
1150         }
1151       if (LocaleCompare(attribute,"area-limit") == 0)
1152         {
1153           MagickSizeType
1154             limit;
1155
1156           limit=MagickResourceInfinity;
1157           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1158             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1159               100.0);
1160           (void) SetMagickResourceLimit(AreaResource,limit);
1161           break;
1162         }
1163       if (LocaleCompare(attribute,"attenuate") == 0)
1164         {
1165           if (info)
1166             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1167           break;
1168         }
1169       if (LocaleCompare(attribute,"authenticate") == 0)
1170         {
1171           if (info)
1172             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1173           break;
1174         }
1175       if (info)
1176         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1177       for ( ; image; image=image->next)
1178         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1179       break;
1180     }
1181     case 'B':
1182     case 'b':
1183     {
1184       if (LocaleCompare(attribute,"background") == 0)
1185         {
1186           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1187             exception);
1188           if (info)
1189             info->image_info->background_color=target_color;
1190           for ( ; image; image=image->next)
1191             image->background_color=target_color;
1192           break;
1193         }
1194       if (LocaleCompare(attribute,"blue-primary") == 0)
1195         {
1196           for ( ; image; image=image->next)
1197           {
1198             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1199             image->chromaticity.blue_primary.x=geometry_info.rho;
1200             image->chromaticity.blue_primary.y=geometry_info.sigma;
1201             if ((flags & SigmaValue) == 0)
1202               image->chromaticity.blue_primary.y=
1203                 image->chromaticity.blue_primary.x;
1204           }
1205           break;
1206         }
1207       if (LocaleCompare(attribute,"bordercolor") == 0)
1208         {
1209           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1210             exception);
1211           if (info)
1212             info->image_info->border_color=target_color;
1213           for ( ; image; image=image->next)
1214             image->border_color=target_color;
1215           break;
1216         }
1217       if (info)
1218         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1219       for ( ; image; image=image->next)
1220         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1221       break;
1222     }
1223     case 'C':
1224     case 'c':
1225     {
1226       if (LocaleCompare(attribute,"cache-threshold") == 0)
1227         {
1228           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1229             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1230           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1231             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1232           break;
1233         }
1234       if (LocaleCompare(attribute,"clip-mask") == 0)
1235         {
1236           Image
1237             *clip_mask;
1238
1239           clip_mask=(Image *) NULL;
1240           if (SvPOK(sval))
1241             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1242           for ( ; image; image=image->next)
1243             SetImageMask(image,clip_mask,exception);
1244           break;
1245         }
1246       if (LocaleNCompare(attribute,"colormap",8) == 0)
1247         {
1248           for ( ; image; image=image->next)
1249           {
1250             int
1251               items;
1252
1253             long
1254               i;
1255
1256             if (image->storage_class == DirectClass)
1257               continue;
1258             i=0;
1259             items=sscanf(attribute,"%*[^[][%ld",&i);
1260             (void) items;
1261             if (i > (ssize_t) image->colors)
1262               i%=image->colors;
1263             if ((strchr(SvPV(sval,na),',') == 0) ||
1264                 (strchr(SvPV(sval,na),')') != 0))
1265               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1266                 image->colormap+i,exception);
1267             else
1268               {
1269                 color=image->colormap+i;
1270                 pixel.red=color->red;
1271                 pixel.green=color->green;
1272                 pixel.blue=color->blue;
1273                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1274                 pixel.red=geometry_info.rho;
1275                 pixel.green=geometry_info.sigma;
1276                 pixel.blue=geometry_info.xi;
1277                 color->red=ClampToQuantum(pixel.red);
1278                 color->green=ClampToQuantum(pixel.green);
1279                 color->blue=ClampToQuantum(pixel.blue);
1280               }
1281           }
1282           break;
1283         }
1284       if (LocaleCompare(attribute,"colorspace") == 0)
1285         {
1286           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1287             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1288           if (sp < 0)
1289             {
1290               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1291                 SvPV(sval,na));
1292               break;
1293             }
1294           for ( ; image; image=image->next)
1295             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1296               exception);
1297           break;
1298         }
1299       if (LocaleCompare(attribute,"comment") == 0)
1300         {
1301           for ( ; image; image=image->next)
1302             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1303               info ? info->image_info : (ImageInfo *) NULL,image,
1304               SvPV(sval,na),exception),exception);
1305           break;
1306         }
1307       if (LocaleCompare(attribute,"compression") == 0)
1308         {
1309           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1310             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1311           if (sp < 0)
1312             {
1313               ThrowPerlException(exception,OptionError,
1314                 "UnrecognizedImageCompression",SvPV(sval,na));
1315               break;
1316             }
1317           if (info)
1318             info->image_info->compression=(CompressionType) sp;
1319           for ( ; image; image=image->next)
1320             image->compression=(CompressionType) sp;
1321           break;
1322         }
1323       if (info)
1324         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1325       for ( ; image; image=image->next)
1326         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1327       break;
1328     }
1329     case 'D':
1330     case 'd':
1331     {
1332       if (LocaleCompare(attribute,"debug") == 0)
1333         {
1334           SetLogEventMask(SvPV(sval,na));
1335           break;
1336         }
1337       if (LocaleCompare(attribute,"delay") == 0)
1338         {
1339           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1340           for ( ; image; image=image->next)
1341           {
1342             image->delay=(size_t) floor(geometry_info.rho+0.5);
1343             if ((flags & SigmaValue) != 0)
1344               image->ticks_per_second=(ssize_t)
1345                 floor(geometry_info.sigma+0.5);
1346           }
1347           break;
1348         }
1349       if (LocaleCompare(attribute,"disk-limit") == 0)
1350         {
1351           MagickSizeType
1352             limit;
1353
1354           limit=MagickResourceInfinity;
1355           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1356             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1357               100.0);
1358           (void) SetMagickResourceLimit(DiskResource,limit);
1359           break;
1360         }
1361       if (LocaleCompare(attribute,"density") == 0)
1362         {
1363           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1364             {
1365               ThrowPerlException(exception,OptionError,"MissingGeometry",
1366                 SvPV(sval,na));
1367               break;
1368             }
1369           if (info)
1370             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1371           for ( ; image; image=image->next)
1372           {
1373             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1374             image->resolution.x=geometry_info.rho;
1375             image->resolution.y=geometry_info.sigma;
1376             if ((flags & SigmaValue) == 0)
1377               image->resolution.y=image->resolution.x;
1378           }
1379           break;
1380         }
1381       if (LocaleCompare(attribute,"depth") == 0)
1382         {
1383           if (info)
1384             info->image_info->depth=SvIV(sval);
1385           for ( ; image; image=image->next)
1386             (void) SetImageDepth(image,SvIV(sval),exception);
1387           break;
1388         }
1389       if (LocaleCompare(attribute,"dispose") == 0)
1390         {
1391           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1392             SvPV(sval,na)) : SvIV(sval);
1393           if (sp < 0)
1394             {
1395               ThrowPerlException(exception,OptionError,
1396                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1397               break;
1398             }
1399           for ( ; image; image=image->next)
1400             image->dispose=(DisposeType) sp;
1401           break;
1402         }
1403       if (LocaleCompare(attribute,"dither") == 0)
1404         {
1405           if (info)
1406             {
1407               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1408                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1409               if (sp < 0)
1410                 {
1411                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1412                     SvPV(sval,na));
1413                   break;
1414                 }
1415               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1416             }
1417           break;
1418         }
1419       if (LocaleCompare(attribute,"display") == 0)
1420         {
1421           display:
1422           if (info)
1423             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1424           break;
1425         }
1426       if (info)
1427         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1428       for ( ; image; image=image->next)
1429         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1430       break;
1431     }
1432     case 'E':
1433     case 'e':
1434     {
1435       if (LocaleCompare(attribute,"endian") == 0)
1436         {
1437           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1438             SvPV(sval,na)) : SvIV(sval);
1439           if (sp < 0)
1440             {
1441               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1442                 SvPV(sval,na));
1443               break;
1444             }
1445           if (info)
1446             info->image_info->endian=(EndianType) sp;
1447           for ( ; image; image=image->next)
1448             image->endian=(EndianType) sp;
1449           break;
1450         }
1451       if (LocaleCompare(attribute,"extract") == 0)
1452         {
1453           /*
1454             Set image extract geometry.
1455           */
1456           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1457           break;
1458         }
1459       if (info)
1460         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1461       for ( ; image; image=image->next)
1462         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1463       break;
1464     }
1465     case 'F':
1466     case 'f':
1467     {
1468       if (LocaleCompare(attribute,"filename") == 0)
1469         {
1470           if (info)
1471             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1472               MagickPathExtent);
1473           for ( ; image; image=image->next)
1474             (void) CopyMagickString(image->filename,SvPV(sval,na),
1475               MagickPathExtent);
1476           break;
1477         }
1478       if (LocaleCompare(attribute,"file") == 0)
1479         {
1480           FILE
1481             *file;
1482
1483           PerlIO
1484             *io_info;
1485
1486           if (info == (struct PackageInfo *) NULL)
1487             break;
1488           io_info=IoIFP(sv_2io(sval));
1489           if (io_info == (PerlIO *) NULL)
1490             {
1491               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1492                 PackageName);
1493               break;
1494             }
1495           file=PerlIO_findFILE(io_info);
1496           if (file == (FILE *) NULL)
1497             {
1498               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1499                 PackageName);
1500               break;
1501             }
1502           SetImageInfoFile(info->image_info,file);
1503           break;
1504         }
1505       if (LocaleCompare(attribute,"fill") == 0)
1506         {
1507           if (info)
1508             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1509           break;
1510         }
1511       if (LocaleCompare(attribute,"font") == 0)
1512         {
1513           if (info)
1514             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1515           break;
1516         }
1517       if (LocaleCompare(attribute,"foreground") == 0)
1518         break;
1519       if (LocaleCompare(attribute,"fuzz") == 0)
1520         {
1521           if (info)
1522             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1523               QuantumRange+1.0);
1524           for ( ; image; image=image->next)
1525             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1526               QuantumRange+1.0);
1527           break;
1528         }
1529       if (info)
1530         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1531       for ( ; image; image=image->next)
1532         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1533       break;
1534     }
1535     case 'G':
1536     case 'g':
1537     {
1538       if (LocaleCompare(attribute,"gamma") == 0)
1539         {
1540           for ( ; image; image=image->next)
1541             image->gamma=SvNV(sval);
1542           break;
1543         }
1544       if (LocaleCompare(attribute,"gravity") == 0)
1545         {
1546           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1547             SvPV(sval,na)) : SvIV(sval);
1548           if (sp < 0)
1549             {
1550               ThrowPerlException(exception,OptionError,
1551                 "UnrecognizedGravityType",SvPV(sval,na));
1552               break;
1553             }
1554           if (info)
1555             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1556           for ( ; image; image=image->next)
1557             image->gravity=(GravityType) sp;
1558           break;
1559         }
1560       if (LocaleCompare(attribute,"green-primary") == 0)
1561         {
1562           for ( ; image; image=image->next)
1563           {
1564             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1565             image->chromaticity.green_primary.x=geometry_info.rho;
1566             image->chromaticity.green_primary.y=geometry_info.sigma;
1567             if ((flags & SigmaValue) == 0)
1568               image->chromaticity.green_primary.y=
1569                 image->chromaticity.green_primary.x;
1570           }
1571           break;
1572         }
1573       if (info)
1574         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1575       for ( ; image; image=image->next)
1576         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1577       break;
1578     }
1579     case 'I':
1580     case 'i':
1581     {
1582       if (LocaleNCompare(attribute,"index",5) == 0)
1583         {
1584           int
1585             items;
1586
1587           long
1588             index;
1589
1590           register Quantum
1591             *q;
1592
1593           CacheView
1594             *image_view;
1595
1596           for ( ; image; image=image->next)
1597           {
1598             if (image->storage_class != PseudoClass)
1599               continue;
1600             x=0;
1601             y=0;
1602             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1603             (void) items;
1604             image_view=AcquireAuthenticCacheView(image,exception);
1605             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1606             if (q != (Quantum *) NULL)
1607               {
1608                 items=sscanf(SvPV(sval,na),"%ld",&index);
1609                 if ((index >= 0) && (index < (ssize_t) image->colors))
1610                   SetPixelIndex(image,index,q);
1611                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1612               }
1613             image_view=DestroyCacheView(image_view);
1614           }
1615           break;
1616         }
1617       if (LocaleCompare(attribute,"iterations") == 0)
1618         {
1619   iterations:
1620           for ( ; image; image=image->next)
1621             image->iterations=SvIV(sval);
1622           break;
1623         }
1624       if (LocaleCompare(attribute,"interlace") == 0)
1625         {
1626           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1627             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1628           if (sp < 0)
1629             {
1630               ThrowPerlException(exception,OptionError,
1631                 "UnrecognizedInterlaceType",SvPV(sval,na));
1632               break;
1633             }
1634           if (info)
1635             info->image_info->interlace=(InterlaceType) sp;
1636           for ( ; image; image=image->next)
1637             image->interlace=(InterlaceType) sp;
1638           break;
1639         }
1640       if (info)
1641         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1642       for ( ; image; image=image->next)
1643         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1644       break;
1645     }
1646     case 'L':
1647     case 'l':
1648     {
1649       if (LocaleCompare(attribute,"label") == 0)
1650         {
1651           for ( ; image; image=image->next)
1652             (void) SetImageProperty(image,"label",InterpretImageProperties(
1653               info ? info->image_info : (ImageInfo *) NULL,image,
1654               SvPV(sval,na),exception),exception);
1655           break;
1656         }
1657       if (LocaleCompare(attribute,"loop") == 0)
1658         goto iterations;
1659       if (info)
1660         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1661       for ( ; image; image=image->next)
1662         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1663       break;
1664     }
1665     case 'M':
1666     case 'm':
1667     {
1668       if (LocaleCompare(attribute,"magick") == 0)
1669         {
1670           if (info)
1671             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1672               "%s:",SvPV(sval,na));
1673           for ( ; image; image=image->next)
1674             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1675           break;
1676         }
1677       if (LocaleCompare(attribute,"map-limit") == 0)
1678         {
1679           MagickSizeType
1680             limit;
1681
1682           limit=MagickResourceInfinity;
1683           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1684             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1685               100.0);
1686           (void) SetMagickResourceLimit(MapResource,limit);
1687           break;
1688         }
1689       if (LocaleCompare(attribute,"mask") == 0)
1690         {
1691           Image
1692             *mask;
1693
1694           mask=(Image *) NULL;
1695           if (SvPOK(sval))
1696             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1697           for ( ; image; image=image->next)
1698             SetImageMask(image,mask,exception);
1699           break;
1700         }
1701       if (LocaleCompare(attribute,"mattecolor") == 0)
1702         {
1703           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1704             exception);
1705           if (info)
1706             info->image_info->matte_color=target_color;
1707           for ( ; image; image=image->next)
1708             image->matte_color=target_color;
1709           break;
1710         }
1711       if (LocaleCompare(attribute,"matte") == 0)
1712         {
1713           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1714             SvPV(sval,na)) : SvIV(sval);
1715           if (sp < 0)
1716             {
1717               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1718                 SvPV(sval,na));
1719               break;
1720             }
1721           for ( ; image; image=image->next)
1722             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1723           break;
1724         }
1725       if (LocaleCompare(attribute,"memory-limit") == 0)
1726         {
1727           MagickSizeType
1728             limit;
1729
1730           limit=MagickResourceInfinity;
1731           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1732             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1733               100.0);
1734           (void) SetMagickResourceLimit(MemoryResource,limit);
1735           break;
1736         }
1737       if (LocaleCompare(attribute,"monochrome") == 0)
1738         {
1739           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1740             SvPV(sval,na)) : SvIV(sval);
1741           if (sp < 0)
1742             {
1743               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1744                 SvPV(sval,na));
1745               break;
1746             }
1747           if (info)
1748             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1749           for ( ; image; image=image->next)
1750             (void) SetImageType(image,BilevelType,exception);
1751           break;
1752         }
1753       if (info)
1754         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1755       for ( ; image; image=image->next)
1756         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1757       break;
1758     }
1759     case 'O':
1760     case 'o':
1761     {
1762       if (LocaleCompare(attribute,"option") == 0)
1763         {
1764           if (info)
1765             DefineImageOption(info->image_info,SvPV(sval,na));
1766           break;
1767         }
1768       if (LocaleCompare(attribute,"orientation") == 0)
1769         {
1770           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1771             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1772           if (sp < 0)
1773             {
1774               ThrowPerlException(exception,OptionError,
1775                 "UnrecognizedOrientationType",SvPV(sval,na));
1776               break;
1777             }
1778           if (info)
1779             info->image_info->orientation=(OrientationType) sp;
1780           for ( ; image; image=image->next)
1781             image->orientation=(OrientationType) sp;
1782           break;
1783         }
1784       if (info)
1785         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1786       for ( ; image; image=image->next)
1787         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1788       break;
1789     }
1790     case 'P':
1791     case 'p':
1792     {
1793       if (LocaleCompare(attribute,"page") == 0)
1794         {
1795           char
1796             *geometry;
1797
1798           geometry=GetPageGeometry(SvPV(sval,na));
1799           if (info)
1800             (void) CloneString(&info->image_info->page,geometry);
1801           for ( ; image; image=image->next)
1802             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1803           geometry=(char *) RelinquishMagickMemory(geometry);
1804           break;
1805         }
1806       if (LocaleNCompare(attribute,"pixel",5) == 0)
1807         {
1808           int
1809             items;
1810
1811           PixelInfo
1812             pixel;
1813
1814           register Quantum
1815             *q;
1816
1817           CacheView
1818             *image_view;
1819
1820           for ( ; image; image=image->next)
1821           {
1822             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1823               break;
1824             x=0;
1825             y=0;
1826             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1827             (void) items;
1828             image_view=AcquireVirtualCacheView(image,exception);
1829             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1830             if (q != (Quantum *) NULL)
1831               {
1832                 if ((strchr(SvPV(sval,na),',') == 0) ||
1833                     (strchr(SvPV(sval,na),')') != 0))
1834                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1835                     &pixel,exception);
1836                 else
1837                   {
1838                     GetPixelInfo(image,&pixel);
1839                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1840                     pixel.red=geometry_info.rho;
1841                     if ((flags & SigmaValue) != 0)
1842                       pixel.green=geometry_info.sigma;
1843                     if ((flags & XiValue) != 0)
1844                       pixel.blue=geometry_info.xi;
1845                     if ((flags & PsiValue) != 0)
1846                       pixel.alpha=geometry_info.psi;
1847                     if ((flags & ChiValue) != 0)
1848                       pixel.black=geometry_info.chi;
1849                   }
1850                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1851                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1852                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1853                 if (image->colorspace == CMYKColorspace)
1854                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1855                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1856                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1857               }
1858             image_view=DestroyCacheView(image_view);
1859           }
1860           break;
1861         }
1862       if (LocaleCompare(attribute,"pointsize") == 0)
1863         {
1864           if (info)
1865             {
1866               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1867               info->image_info->pointsize=geometry_info.rho;
1868             }
1869           break;
1870         }
1871       if (LocaleCompare(attribute,"preview") == 0)
1872         {
1873           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1874             SvPV(sval,na)) : SvIV(sval);
1875           if (sp < 0)
1876             {
1877               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1878                 SvPV(sval,na));
1879               break;
1880             }
1881           if (info)
1882             info->image_info->preview_type=(PreviewType) sp;
1883           break;
1884         }
1885       if (info)
1886         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1887       for ( ; image; image=image->next)
1888         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1889       break;
1890     }
1891     case 'Q':
1892     case 'q':
1893     {
1894       if (LocaleCompare(attribute,"quality") == 0)
1895         {
1896           if (info)
1897             info->image_info->quality=SvIV(sval);
1898           for ( ; image; image=image->next)
1899             image->quality=SvIV(sval);
1900           break;
1901         }
1902       if (info)
1903         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1904       for ( ; image; image=image->next)
1905         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1906       break;
1907     }
1908     case 'R':
1909     case 'r':
1910     {
1911       if (LocaleCompare(attribute,"red-primary") == 0)
1912         {
1913           for ( ; image; image=image->next)
1914           {
1915             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1916             image->chromaticity.red_primary.x=geometry_info.rho;
1917             image->chromaticity.red_primary.y=geometry_info.sigma;
1918             if ((flags & SigmaValue) == 0)
1919               image->chromaticity.red_primary.y=
1920                 image->chromaticity.red_primary.x;
1921           }
1922           break;
1923         }
1924       if (LocaleCompare(attribute,"render") == 0)
1925         {
1926           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1927             SvPV(sval,na)) : SvIV(sval);
1928           if (sp < 0)
1929             {
1930               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1931                 SvPV(sval,na));
1932               break;
1933             }
1934          for ( ; image; image=image->next)
1935            image->rendering_intent=(RenderingIntent) sp;
1936          break;
1937        }
1938       if (LocaleCompare(attribute,"repage") == 0)
1939         {
1940           RectangleInfo
1941             geometry;
1942
1943           for ( ; image; image=image->next)
1944           {
1945             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1946             if ((flags & WidthValue) != 0)
1947               {
1948                 if ((flags & HeightValue) == 0)
1949                   geometry.height=geometry.width;
1950                 image->page.width=geometry.width;
1951                 image->page.height=geometry.height;
1952               }
1953             if ((flags & AspectValue) != 0)
1954               {
1955                 if ((flags & XValue) != 0)
1956                   image->page.x+=geometry.x;
1957                 if ((flags & YValue) != 0)
1958                   image->page.y+=geometry.y;
1959               }
1960             else
1961               {
1962                 if ((flags & XValue) != 0)
1963                   {
1964                     image->page.x=geometry.x;
1965                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1966                       image->page.width=image->columns+geometry.x;
1967                   }
1968                 if ((flags & YValue) != 0)
1969                   {
1970                     image->page.y=geometry.y;
1971                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1972                       image->page.height=image->rows+geometry.y;
1973                   }
1974               }
1975           }
1976           break;
1977         }
1978       if (info)
1979         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1980       for ( ; image; image=image->next)
1981         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1982       break;
1983     }
1984     case 'S':
1985     case 's':
1986     {
1987       if (LocaleCompare(attribute,"sampling-factor") == 0)
1988         {
1989           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1990             {
1991               ThrowPerlException(exception,OptionError,"MissingGeometry",
1992                 SvPV(sval,na));
1993               break;
1994             }
1995           if (info)
1996             (void) CloneString(&info->image_info->sampling_factor,
1997               SvPV(sval,na));
1998           break;
1999         }
2000       if (LocaleCompare(attribute,"scene") == 0)
2001         {
2002           for ( ; image; image=image->next)
2003             image->scene=SvIV(sval);
2004           break;
2005         }
2006       if (LocaleCompare(attribute,"server") == 0)
2007         goto display;
2008       if (LocaleCompare(attribute,"size") == 0)
2009         {
2010           if (info)
2011             {
2012               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2013                 {
2014                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2015                     SvPV(sval,na));
2016                   break;
2017                 }
2018               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2019             }
2020           break;
2021         }
2022       if (LocaleCompare(attribute,"stroke") == 0)
2023         {
2024           if (info)
2025             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2026           break;
2027         }
2028       if (info)
2029         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2030       for ( ; image; image=image->next)
2031         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2032       break;
2033     }
2034     case 'T':
2035     case 't':
2036     {
2037       if (LocaleCompare(attribute,"texture") == 0)
2038         {
2039           if (info)
2040             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2041           break;
2042         }
2043       if (LocaleCompare(attribute,"thread-limit") == 0)
2044         {
2045           MagickSizeType
2046             limit;
2047
2048           limit=MagickResourceInfinity;
2049           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2050             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2051               100.0);
2052           (void) SetMagickResourceLimit(ThreadResource,limit);
2053           break;
2054         }
2055       if (LocaleCompare(attribute,"tile-offset") == 0)
2056         {
2057           char
2058             *geometry;
2059
2060           geometry=GetPageGeometry(SvPV(sval,na));
2061           if (info)
2062             (void) CloneString(&info->image_info->page,geometry);
2063           for ( ; image; image=image->next)
2064             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2065               exception);
2066           geometry=(char *) RelinquishMagickMemory(geometry);
2067           break;
2068         }
2069       if (LocaleCompare(attribute,"time-limit") == 0)
2070         {
2071           MagickSizeType
2072             limit;
2073
2074           limit=MagickResourceInfinity;
2075           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2076             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2077               100.0);
2078           (void) SetMagickResourceLimit(TimeResource,limit);
2079           break;
2080         }
2081       if (LocaleCompare(attribute,"transparent-color") == 0)
2082         {
2083           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2084             exception);
2085           if (info)
2086             info->image_info->transparent_color=target_color;
2087           for ( ; image; image=image->next)
2088             image->transparent_color=target_color;
2089           break;
2090         }
2091       if (LocaleCompare(attribute,"type") == 0)
2092         {
2093           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2094             SvPV(sval,na)) : SvIV(sval);
2095           if (sp < 0)
2096             {
2097               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2098                 SvPV(sval,na));
2099               break;
2100             }
2101           if (info)
2102             info->image_info->type=(ImageType) sp;
2103           for ( ; image; image=image->next)
2104             SetImageType(image,(ImageType) sp,exception);
2105           break;
2106         }
2107       if (info)
2108         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2109       for ( ; image; image=image->next)
2110         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2111       break;
2112     }
2113     case 'U':
2114     case 'u':
2115     {
2116       if (LocaleCompare(attribute,"units") == 0)
2117         {
2118           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2119             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2120           if (sp < 0)
2121             {
2122               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2123                 SvPV(sval,na));
2124               break;
2125             }
2126           if (info)
2127             info->image_info->units=(ResolutionType) sp;
2128           for ( ; image; image=image->next)
2129           {
2130             ResolutionType
2131               units;
2132
2133             units=(ResolutionType) sp;
2134             if (image->units != units)
2135               switch (image->units)
2136               {
2137                 case UndefinedResolution:
2138                 case PixelsPerInchResolution:
2139                 {
2140                   if (units == PixelsPerCentimeterResolution)
2141                     {
2142                       image->resolution.x*=2.54;
2143                       image->resolution.y*=2.54;
2144                     }
2145                   break;
2146                 }
2147                 case PixelsPerCentimeterResolution:
2148                 {
2149                   if (units == PixelsPerInchResolution)
2150                     {
2151                       image->resolution.x/=2.54;
2152                       image->resolution.y/=2.54;
2153                     }
2154                   break;
2155                 }
2156               }
2157             image->units=units;
2158           }
2159           break;
2160         }
2161       if (info)
2162         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2163       for ( ; image; image=image->next)
2164         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2165       break;
2166     }
2167     case 'V':
2168     case 'v':
2169     {
2170       if (LocaleCompare(attribute,"verbose") == 0)
2171         {
2172           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2173             SvPV(sval,na)) : SvIV(sval);
2174           if (sp < 0)
2175             {
2176               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2177                 SvPV(sval,na));
2178               break;
2179             }
2180           if (info)
2181             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2182           break;
2183         }
2184       if (LocaleCompare(attribute,"view") == 0)
2185         {
2186           if (info)
2187             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2188           break;
2189         }
2190       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2191         {
2192           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2193             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2194           if (sp < 0)
2195             {
2196               ThrowPerlException(exception,OptionError,
2197                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2198               break;
2199             }
2200           for ( ; image; image=image->next)
2201             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2202           break;
2203         }
2204       if (info)
2205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2206       for ( ; image; image=image->next)
2207         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2208       break;
2209     }
2210     case 'W':
2211     case 'w':
2212     {
2213       if (LocaleCompare(attribute,"white-point") == 0)
2214         {
2215           for ( ; image; image=image->next)
2216           {
2217             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2218             image->chromaticity.white_point.x=geometry_info.rho;
2219             image->chromaticity.white_point.y=geometry_info.sigma;
2220             if ((flags & SigmaValue) == 0)
2221               image->chromaticity.white_point.y=
2222                 image->chromaticity.white_point.x;
2223           }
2224           break;
2225         }
2226       if (info)
2227         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2228       for ( ; image; image=image->next)
2229         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2230       break;
2231     }
2232     default:
2233     {
2234       if (info)
2235         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2236       for ( ; image; image=image->next)
2237         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2238       break;
2239     }
2240   }
2241 }
2242 \f
2243 /*
2244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2245 %                                                                             %
2246 %                                                                             %
2247 %                                                                             %
2248 %   S e t u p L i s t                                                         %
2249 %                                                                             %
2250 %                                                                             %
2251 %                                                                             %
2252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2253 %
2254 %  Method SetupList returns the list of all the images linked by their
2255 %  image->next and image->previous link lists for use with ImageMagick.  If
2256 %  info is non-NULL, an info structure is returned in *info.  If
2257 %  reference_vector is non-NULL,an array of SV* are returned in
2258 %  *reference_vector.  Reference_vector is used when the images are going to be
2259 %  replaced with new Image*'s.
2260 %
2261 %  The format of the SetupList routine is:
2262 %
2263 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2264 %        SV ***reference_vector,ExceptionInfo *exception)
2265 %
2266 %  A description of each parameter follows:
2267 %
2268 %    o list: a list of strings.
2269 %
2270 %    o string: a character string.
2271 %
2272 %    o exception: Return any errors or warnings in this structure.
2273 %
2274 */
2275 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2276   SV ***reference_vector,ExceptionInfo *exception)
2277 {
2278   Image
2279     *image;
2280
2281   ssize_t
2282     current,
2283     last;
2284
2285   if (reference_vector)
2286     *reference_vector=NULL;
2287   if (info)
2288     *info=NULL;
2289   current=0;
2290   last=0;
2291   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2292   if (info && (SvTYPE(reference) == SVt_PVAV))
2293     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2294       exception);
2295   return(image);
2296 }
2297 \f
2298 /*
2299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2300 %                                                                             %
2301 %                                                                             %
2302 %                                                                             %
2303 %   s t r E Q c a s e                                                         %
2304 %                                                                             %
2305 %                                                                             %
2306 %                                                                             %
2307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2308 %
2309 %  strEQcase() compares two strings and returns 0 if they are the
2310 %  same or if the second string runs out first.  The comparison is case
2311 %  insensitive.
2312 %
2313 %  The format of the strEQcase routine is:
2314 %
2315 %      ssize_t strEQcase(const char *p,const char *q)
2316 %
2317 %  A description of each parameter follows:
2318 %
2319 %    o p: a character string.
2320 %
2321 %    o q: a character string.
2322 %
2323 %
2324 */
2325 static ssize_t strEQcase(const char *p,const char *q)
2326 {
2327   char
2328     c;
2329
2330   register ssize_t
2331     i;
2332
2333   for (i=0 ; (c=(*q)) != 0; i++)
2334   {
2335     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2336         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2337       return(0);
2338     p++;
2339     q++;
2340   }
2341   return(((*q == 0) && (*p == 0)) ? i : 0);
2342 }
2343 \f
2344 /*
2345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346 %                                                                             %
2347 %                                                                             %
2348 %                                                                             %
2349 %   I m a g e : : M a g i c k                                                 %
2350 %                                                                             %
2351 %                                                                             %
2352 %                                                                             %
2353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2354 %
2355 %
2356 */
2357 MODULE = Image::Magick::@MAGICK_ABI_SUFFIX@ PACKAGE = Image::Magick::@MAGICK_ABI_SUFFIX@
2358
2359 PROTOTYPES: ENABLE
2360
2361 BOOT:
2362   MagickCoreGenesis("PerlMagick",MagickFalse);
2363   SetWarningHandler(NULL);
2364   SetErrorHandler(NULL);
2365   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2366     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2367
2368 void
2369 UNLOAD()
2370   PPCODE:
2371   {
2372     if (magick_registry != (SplayTreeInfo *) NULL)
2373       magick_registry=DestroySplayTree(magick_registry);
2374     MagickCoreTerminus();
2375   }
2376
2377 double
2378 constant(name,argument)
2379   char *name
2380   ssize_t argument
2381 \f
2382 #
2383 ###############################################################################
2384 #                                                                             #
2385 #                                                                             #
2386 #                                                                             #
2387 #   A n i m a t e                                                             #
2388 #                                                                             #
2389 #                                                                             #
2390 #                                                                             #
2391 ###############################################################################
2392 #
2393 #
2394 void
2395 Animate(ref,...)
2396   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2397   ALIAS:
2398     AnimateImage  = 1
2399     animate       = 2
2400     animateimage  = 3
2401   PPCODE:
2402   {
2403     ExceptionInfo
2404       *exception;
2405
2406     Image
2407       *image;
2408
2409     register ssize_t
2410       i;
2411
2412     struct PackageInfo
2413       *info,
2414       *package_info;
2415
2416     SV
2417       *perl_exception,
2418       *reference;
2419
2420     PERL_UNUSED_VAR(ref);
2421     PERL_UNUSED_VAR(ix);
2422     exception=AcquireExceptionInfo();
2423     perl_exception=newSVpv("",0);
2424     package_info=(struct PackageInfo *) NULL;
2425     if (sv_isobject(ST(0)) == 0)
2426       {
2427         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2428           PackageName);
2429         goto PerlException;
2430       }
2431     reference=SvRV(ST(0));
2432     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2433     if (image == (Image *) NULL)
2434       {
2435         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2436           PackageName);
2437         goto PerlException;
2438       }
2439     package_info=ClonePackageInfo(info,exception);
2440     if (items == 2)
2441       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2442     else
2443       if (items > 2)
2444         for (i=2; i < items; i+=2)
2445           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2446             exception);
2447     (void) AnimateImages(package_info->image_info,image,exception);
2448     (void) CatchImageException(image);
2449
2450   PerlException:
2451     if (package_info != (struct PackageInfo *) NULL)
2452       DestroyPackageInfo(package_info);
2453     InheritPerlException(exception,perl_exception);
2454     exception=DestroyExceptionInfo(exception);
2455     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2456     SvPOK_on(perl_exception);
2457     ST(0)=sv_2mortal(perl_exception);
2458     XSRETURN(1);
2459   }
2460 \f
2461 #
2462 ###############################################################################
2463 #                                                                             #
2464 #                                                                             #
2465 #                                                                             #
2466 #   A p p e n d                                                               #
2467 #                                                                             #
2468 #                                                                             #
2469 #                                                                             #
2470 ###############################################################################
2471 #
2472 #
2473 void
2474 Append(ref,...)
2475   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2476   ALIAS:
2477     AppendImage  = 1
2478     append       = 2
2479     appendimage  = 3
2480   PPCODE:
2481   {
2482     AV
2483       *av;
2484
2485     char
2486       *attribute;
2487
2488     ExceptionInfo
2489       *exception;
2490
2491     HV
2492       *hv;
2493
2494     Image
2495       *image;
2496
2497     register ssize_t
2498       i;
2499
2500     ssize_t
2501       stack;
2502
2503     struct PackageInfo
2504       *info;
2505
2506     SV
2507       *av_reference,
2508       *perl_exception,
2509       *reference,
2510       *rv,
2511       *sv;
2512
2513     PERL_UNUSED_VAR(ref);
2514     PERL_UNUSED_VAR(ix);
2515     exception=AcquireExceptionInfo();
2516     perl_exception=newSVpv("",0);
2517     sv=NULL;
2518     attribute=NULL;
2519     av=NULL;
2520     if (sv_isobject(ST(0)) == 0)
2521       {
2522         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2523           PackageName);
2524         goto PerlException;
2525       }
2526     reference=SvRV(ST(0));
2527     hv=SvSTASH(reference);
2528     av=newAV();
2529     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2530     SvREFCNT_dec(av);
2531     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2532     if (image == (Image *) NULL)
2533       {
2534         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2535           PackageName);
2536         goto PerlException;
2537       }
2538     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2539     /*
2540       Get options.
2541     */
2542     stack=MagickTrue;
2543     for (i=2; i < items; i+=2)
2544     {
2545       attribute=(char *) SvPV(ST(i-1),na);
2546       switch (*attribute)
2547       {
2548         case 'S':
2549         case 's':
2550         {
2551           if (LocaleCompare(attribute,"stack") == 0)
2552             {
2553               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2554                 SvPV(ST(i),na));
2555               if (stack < 0)
2556                 {
2557                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2558                     SvPV(ST(i),na));
2559                   return;
2560                 }
2561               break;
2562             }
2563           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2564             attribute);
2565           break;
2566         }
2567         default:
2568         {
2569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2570             attribute);
2571           break;
2572         }
2573       }
2574     }
2575     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2576     if (image == (Image *) NULL)
2577       goto PerlException;
2578     for ( ; image; image=image->next)
2579     {
2580       AddImageToRegistry(sv,image);
2581       rv=newRV(sv);
2582       av_push(av,sv_bless(rv,hv));
2583       SvREFCNT_dec(sv);
2584     }
2585     exception=DestroyExceptionInfo(exception);
2586     ST(0)=av_reference;
2587     SvREFCNT_dec(perl_exception);
2588     XSRETURN(1);
2589
2590   PerlException:
2591     InheritPerlException(exception,perl_exception);
2592     exception=DestroyExceptionInfo(exception);
2593     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2594     SvPOK_on(perl_exception);
2595     ST(0)=sv_2mortal(perl_exception);
2596     XSRETURN(1);
2597   }
2598 \f
2599 #
2600 ###############################################################################
2601 #                                                                             #
2602 #                                                                             #
2603 #                                                                             #
2604 #   A v e r a g e                                                             #
2605 #                                                                             #
2606 #                                                                             #
2607 #                                                                             #
2608 ###############################################################################
2609 #
2610 #
2611 void
2612 Average(ref)
2613   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2614   ALIAS:
2615     AverageImage   = 1
2616     average        = 2
2617     averageimage   = 3
2618   PPCODE:
2619   {
2620     AV
2621       *av;
2622
2623     char
2624       *p;
2625
2626     ExceptionInfo
2627       *exception;
2628
2629     HV
2630       *hv;
2631
2632     Image
2633       *image;
2634
2635     struct PackageInfo
2636       *info;
2637
2638     SV
2639       *perl_exception,
2640       *reference,
2641       *rv,
2642       *sv;
2643
2644     PERL_UNUSED_VAR(ref);
2645     PERL_UNUSED_VAR(ix);
2646     exception=AcquireExceptionInfo();
2647     perl_exception=newSVpv("",0);
2648     sv=NULL;
2649     if (sv_isobject(ST(0)) == 0)
2650       {
2651         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2652           PackageName);
2653         goto PerlException;
2654       }
2655     reference=SvRV(ST(0));
2656     hv=SvSTASH(reference);
2657     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2658     if (image == (Image *) NULL)
2659       {
2660         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2661           PackageName);
2662         goto PerlException;
2663       }
2664     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2665     if (image == (Image *) NULL)
2666       goto PerlException;
2667     /*
2668       Create blessed Perl array for the returned image.
2669     */
2670     av=newAV();
2671     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2672     SvREFCNT_dec(av);
2673     AddImageToRegistry(sv,image);
2674     rv=newRV(sv);
2675     av_push(av,sv_bless(rv,hv));
2676     SvREFCNT_dec(sv);
2677     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2678     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2679       "average-%.*s",(int) (MagickPathExtent-9),
2680       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2681     (void) CopyMagickString(image->filename,info->image_info->filename,
2682       MagickPathExtent);
2683     SetImageInfo(info->image_info,0,exception);
2684     exception=DestroyExceptionInfo(exception);
2685     SvREFCNT_dec(perl_exception);
2686     XSRETURN(1);
2687
2688   PerlException:
2689     InheritPerlException(exception,perl_exception);
2690     exception=DestroyExceptionInfo(exception);
2691     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2692     SvPOK_on(perl_exception);
2693     ST(0)=sv_2mortal(perl_exception);
2694     XSRETURN(1);
2695   }
2696 \f
2697 #
2698 ###############################################################################
2699 #                                                                             #
2700 #                                                                             #
2701 #                                                                             #
2702 #   B l o b T o I m a g e                                                     #
2703 #                                                                             #
2704 #                                                                             #
2705 #                                                                             #
2706 ###############################################################################
2707 #
2708 #
2709 void
2710 BlobToImage(ref,...)
2711   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2712   ALIAS:
2713     BlobToImage  = 1
2714     blobtoimage  = 2
2715     blobto       = 3
2716   PPCODE:
2717   {
2718     AV
2719       *av;
2720
2721     char
2722       **keep,
2723       **list;
2724
2725     ExceptionInfo
2726       *exception;
2727
2728     HV
2729       *hv;
2730
2731     Image
2732       *image;
2733
2734     register char
2735       **p;
2736
2737     register ssize_t
2738       i;
2739
2740     ssize_t
2741       ac,
2742       n,
2743       number_images;
2744
2745     STRLEN
2746       *length;
2747
2748     struct PackageInfo
2749       *info;
2750
2751     SV
2752       *perl_exception,
2753       *reference,
2754       *rv,
2755       *sv;
2756
2757     PERL_UNUSED_VAR(ref);
2758     PERL_UNUSED_VAR(ix);
2759     exception=AcquireExceptionInfo();
2760     perl_exception=newSVpv("",0);
2761     sv=NULL;
2762     number_images=0;
2763     ac=(items < 2) ? 1 : items-1;
2764     length=(STRLEN *) NULL;
2765     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2766     if (list == (char **) NULL)
2767       {
2768         ThrowPerlException(exception,ResourceLimitError,
2769           "MemoryAllocationFailed",PackageName);
2770         goto PerlException;
2771       }
2772     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2773     if (length == (STRLEN *) NULL)
2774       {
2775         ThrowPerlException(exception,ResourceLimitError,
2776           "MemoryAllocationFailed",PackageName);
2777         goto PerlException;
2778       }
2779     if (sv_isobject(ST(0)) == 0)
2780       {
2781         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2782           PackageName);
2783         goto PerlException;
2784       }
2785     reference=SvRV(ST(0));
2786     hv=SvSTASH(reference);
2787     if (SvTYPE(reference) != SVt_PVAV)
2788       {
2789         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2790           PackageName);
2791         goto PerlException;
2792       }
2793     av=(AV *) reference;
2794     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2795       exception);
2796     n=1;
2797     if (items <= 1)
2798       {
2799         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2800         goto PerlException;
2801       }
2802     for (n=0, i=0; i < ac; i++)
2803     {
2804       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2805       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2806         {
2807           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2808           continue;
2809         }
2810       n++;
2811     }
2812     list[n]=(char *) NULL;
2813     keep=list;
2814     for (i=number_images=0; i < n; i++)
2815     {
2816       image=BlobToImage(info->image_info,list[i],length[i],exception);
2817       if (image == (Image *) NULL)
2818         break;
2819       for ( ; image; image=image->next)
2820       {
2821         AddImageToRegistry(sv,image);
2822         rv=newRV(sv);
2823         av_push(av,sv_bless(rv,hv));
2824         SvREFCNT_dec(sv);
2825         number_images++;
2826       }
2827     }
2828     /*
2829       Free resources.
2830     */
2831     for (i=0; i < n; i++)
2832       if (list[i] != (char *) NULL)
2833         for (p=keep; list[i] != *p++; )
2834           if (*p == (char *) NULL)
2835             {
2836               list[i]=(char *) RelinquishMagickMemory(list[i]);
2837               break;
2838             }
2839
2840   PerlException:
2841     if (list)
2842       list=(char **) RelinquishMagickMemory(list);
2843     if (length)
2844       length=(STRLEN *) RelinquishMagickMemory(length);
2845     InheritPerlException(exception,perl_exception);
2846     exception=DestroyExceptionInfo(exception);
2847     sv_setiv(perl_exception,(IV) number_images);
2848     SvPOK_on(perl_exception);
2849     ST(0)=sv_2mortal(perl_exception);
2850     XSRETURN(1);
2851   }
2852 \f
2853 #
2854 ###############################################################################
2855 #                                                                             #
2856 #                                                                             #
2857 #                                                                             #
2858 #   C h a n n e l F x                                                         #
2859 #                                                                             #
2860 #                                                                             #
2861 #                                                                             #
2862 ###############################################################################
2863 #
2864 #
2865 void
2866 ChannelFx(ref,...)
2867   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2868   ALIAS:
2869     ChannelFxImage  = 1
2870     channelfx       = 2
2871     channelfximage  = 3
2872   PPCODE:
2873   {
2874     AV
2875       *av;
2876
2877     char
2878       *attribute,
2879       expression[MagickPathExtent];
2880
2881     ChannelType
2882       channel,
2883       channel_mask;
2884
2885     ExceptionInfo
2886       *exception;
2887
2888     HV
2889       *hv;
2890
2891     Image
2892       *image;
2893
2894     register ssize_t
2895       i;
2896
2897     struct PackageInfo
2898       *info;
2899
2900     SV
2901       *av_reference,
2902       *perl_exception,
2903       *reference,
2904       *rv,
2905       *sv;
2906
2907     PERL_UNUSED_VAR(ref);
2908     PERL_UNUSED_VAR(ix);
2909     exception=AcquireExceptionInfo();
2910     perl_exception=newSVpv("",0);
2911     sv=NULL;
2912     attribute=NULL;
2913     av=NULL;
2914     if (sv_isobject(ST(0)) == 0)
2915       {
2916         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2917           PackageName);
2918         goto PerlException;
2919       }
2920     reference=SvRV(ST(0));
2921     hv=SvSTASH(reference);
2922     av=newAV();
2923     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2924     SvREFCNT_dec(av);
2925     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2926     if (image == (Image *) NULL)
2927       {
2928         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2929           PackageName);
2930         goto PerlException;
2931       }
2932     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2933     /*
2934       Get options.
2935     */
2936     channel=DefaultChannels;
2937     (void) CopyMagickString(expression,"u",MagickPathExtent);
2938     if (items == 2)
2939       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2940     else
2941       for (i=2; i < items; i+=2)
2942       {
2943         attribute=(char *) SvPV(ST(i-1),na);
2944         switch (*attribute)
2945         {
2946           case 'C':
2947           case 'c':
2948           {
2949             if (LocaleCompare(attribute,"channel") == 0)
2950               {
2951                 ssize_t
2952                   option;
2953
2954                 option=ParseChannelOption(SvPV(ST(i),na));
2955                 if (option < 0)
2956                   {
2957                     ThrowPerlException(exception,OptionError,
2958                       "UnrecognizedType",SvPV(ST(i),na));
2959                     return;
2960                   }
2961                 channel=(ChannelType) option;
2962                 break;
2963               }
2964             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2965               attribute);
2966             break;
2967           }
2968           case 'E':
2969           case 'e':
2970           {
2971             if (LocaleCompare(attribute,"expression") == 0)
2972               {
2973                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2974                   MagickPathExtent);
2975                 break;
2976               }
2977             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2978               attribute);
2979             break;
2980           }
2981           default:
2982           {
2983             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2984               attribute);
2985             break;
2986           }
2987         }
2988       }
2989     channel_mask=SetImageChannelMask(image,channel);
2990     image=ChannelFxImage(image,expression,exception);
2991     if (image != (Image *) NULL)
2992       (void) SetImageChannelMask(image,channel_mask);
2993     if (image == (Image *) NULL)
2994       goto PerlException;
2995     for ( ; image; image=image->next)
2996     {
2997       AddImageToRegistry(sv,image);
2998       rv=newRV(sv);
2999       av_push(av,sv_bless(rv,hv));
3000       SvREFCNT_dec(sv);
3001     }
3002     exception=DestroyExceptionInfo(exception);
3003     ST(0)=av_reference;
3004     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3005     XSRETURN(1);
3006
3007   PerlException:
3008     InheritPerlException(exception,perl_exception);
3009     exception=DestroyExceptionInfo(exception);
3010     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3011     SvPOK_on(perl_exception);
3012     ST(0)=sv_2mortal(perl_exception);
3013     XSRETURN(1);
3014   }
3015 \f
3016 #
3017 ###############################################################################
3018 #                                                                             #
3019 #                                                                             #
3020 #                                                                             #
3021 #   C l o n e                                                                 #
3022 #                                                                             #
3023 #                                                                             #
3024 #                                                                             #
3025 ###############################################################################
3026 #
3027 #
3028 void
3029 Clone(ref)
3030   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3031   ALIAS:
3032     CopyImage   = 1
3033     copy        = 2
3034     copyimage   = 3
3035     CloneImage  = 4
3036     clone       = 5
3037     cloneimage  = 6
3038     Clone       = 7
3039   PPCODE:
3040   {
3041     AV
3042       *av;
3043
3044     ExceptionInfo
3045       *exception;
3046
3047     HV
3048       *hv;
3049
3050     Image
3051       *clone,
3052       *image;
3053
3054     struct PackageInfo
3055       *info;
3056
3057     SV
3058       *perl_exception,
3059       *reference,
3060       *rv,
3061       *sv;
3062
3063     PERL_UNUSED_VAR(ref);
3064     PERL_UNUSED_VAR(ix);
3065     exception=AcquireExceptionInfo();
3066     perl_exception=newSVpv("",0);
3067     sv=NULL;
3068     if (sv_isobject(ST(0)) == 0)
3069       {
3070         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3071           PackageName);
3072         goto PerlException;
3073       }
3074     reference=SvRV(ST(0));
3075     hv=SvSTASH(reference);
3076     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3077     if (image == (Image *) NULL)
3078       {
3079         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3080           PackageName);
3081         goto PerlException;
3082       }
3083     /*
3084       Create blessed Perl array for the returned image.
3085     */
3086     av=newAV();
3087     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3088     SvREFCNT_dec(av);
3089     for ( ; image; image=image->next)
3090     {
3091       clone=CloneImage(image,0,0,MagickTrue,exception);
3092       if (clone == (Image *) NULL)
3093         break;
3094       AddImageToRegistry(sv,clone);
3095       rv=newRV(sv);
3096       av_push(av,sv_bless(rv,hv));
3097       SvREFCNT_dec(sv);
3098     }
3099     exception=DestroyExceptionInfo(exception);
3100     SvREFCNT_dec(perl_exception);
3101     XSRETURN(1);
3102
3103   PerlException:
3104     InheritPerlException(exception,perl_exception);
3105     exception=DestroyExceptionInfo(exception);
3106     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3107     SvPOK_on(perl_exception);
3108     ST(0)=sv_2mortal(perl_exception);
3109     XSRETURN(1);
3110   }
3111 \f
3112 #
3113 ###############################################################################
3114 #                                                                             #
3115 #                                                                             #
3116 #                                                                             #
3117 #   C L O N E                                                                 #
3118 #                                                                             #
3119 #                                                                             #
3120 #                                                                             #
3121 ###############################################################################
3122 #
3123 #
3124 void
3125 CLONE(ref,...)
3126   SV *ref;
3127   CODE:
3128   {
3129     PERL_UNUSED_VAR(ref);
3130     if (magick_registry != (SplayTreeInfo *) NULL)
3131       {
3132         register Image
3133           *p;
3134
3135         ResetSplayTreeIterator(magick_registry);
3136         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3137         while (p != (Image *) NULL)
3138         {
3139           ReferenceImage(p);
3140           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3141         }
3142       }
3143   }
3144 \f
3145 #
3146 ###############################################################################
3147 #                                                                             #
3148 #                                                                             #
3149 #                                                                             #
3150 #   C o a l e s c e                                                           #
3151 #                                                                             #
3152 #                                                                             #
3153 #                                                                             #
3154 ###############################################################################
3155 #
3156 #
3157 void
3158 Coalesce(ref)
3159   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3160   ALIAS:
3161     CoalesceImage   = 1
3162     coalesce        = 2
3163     coalesceimage   = 3
3164   PPCODE:
3165   {
3166     AV
3167       *av;
3168
3169     ExceptionInfo
3170       *exception;
3171
3172     HV
3173       *hv;
3174
3175     Image
3176       *image;
3177
3178     struct PackageInfo
3179       *info;
3180
3181     SV
3182       *av_reference,
3183       *perl_exception,
3184       *reference,
3185       *rv,
3186       *sv;
3187
3188     PERL_UNUSED_VAR(ref);
3189     PERL_UNUSED_VAR(ix);
3190     exception=AcquireExceptionInfo();
3191     perl_exception=newSVpv("",0);
3192     sv=NULL;
3193     if (sv_isobject(ST(0)) == 0)
3194       {
3195         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3196           PackageName);
3197         goto PerlException;
3198       }
3199     reference=SvRV(ST(0));
3200     hv=SvSTASH(reference);
3201     av=newAV();
3202     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3203     SvREFCNT_dec(av);
3204     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3205     if (image == (Image *) NULL)
3206       {
3207         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3208           PackageName);
3209         goto PerlException;
3210       }
3211     image=CoalesceImages(image,exception);
3212     if (image == (Image *) NULL)
3213       goto PerlException;
3214     for ( ; image; image=image->next)
3215     {
3216       AddImageToRegistry(sv,image);
3217       rv=newRV(sv);
3218       av_push(av,sv_bless(rv,hv));
3219       SvREFCNT_dec(sv);
3220     }
3221     exception=DestroyExceptionInfo(exception);
3222     ST(0)=av_reference;
3223     SvREFCNT_dec(perl_exception);
3224     XSRETURN(1);
3225
3226   PerlException:
3227     InheritPerlException(exception,perl_exception);
3228     exception=DestroyExceptionInfo(exception);
3229     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3230     SvPOK_on(perl_exception);
3231     ST(0)=sv_2mortal(perl_exception);
3232     XSRETURN(1);
3233   }
3234 \f
3235 #
3236 ###############################################################################
3237 #                                                                             #
3238 #                                                                             #
3239 #                                                                             #
3240 #   C o m p a r e                                                             #
3241 #                                                                             #
3242 #                                                                             #
3243 #                                                                             #
3244 ###############################################################################
3245 #
3246 #
3247 void
3248 Compare(ref,...)
3249   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3250   ALIAS:
3251     CompareImages = 1
3252     compare      = 2
3253     compareimage = 3
3254   PPCODE:
3255   {
3256     AV
3257       *av;
3258
3259     char
3260       *attribute;
3261
3262     double
3263       distortion;
3264
3265     ExceptionInfo
3266       *exception;
3267
3268     HV
3269       *hv;
3270
3271     Image
3272       *difference_image,
3273       *image,
3274       *reconstruct_image;
3275
3276     MetricType
3277       metric;
3278
3279     register ssize_t
3280       i;
3281
3282     ssize_t
3283       option;
3284
3285     struct PackageInfo
3286       *info;
3287
3288     SV
3289       *av_reference,
3290       *perl_exception,
3291       *reference,
3292       *rv,
3293       *sv;
3294
3295     PERL_UNUSED_VAR(ref);
3296     PERL_UNUSED_VAR(ix);
3297     exception=AcquireExceptionInfo();
3298     perl_exception=newSVpv("",0);
3299     sv=NULL;
3300     av=NULL;
3301     attribute=NULL;
3302     if (sv_isobject(ST(0)) == 0)
3303       {
3304         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3305           PackageName);
3306         goto PerlException;
3307       }
3308     reference=SvRV(ST(0));
3309     hv=SvSTASH(reference);
3310     av=newAV();
3311     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3312     SvREFCNT_dec(av);
3313     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3314     if (image == (Image *) NULL)
3315       {
3316         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3317           PackageName);
3318         goto PerlException;
3319       }
3320     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3321     /*
3322       Get attribute.
3323     */
3324     reconstruct_image=image;
3325     metric=RootMeanSquaredErrorMetric;
3326     for (i=2; i < items; i+=2)
3327     {
3328       attribute=(char *) SvPV(ST(i-1),na);
3329       switch (*attribute)
3330       {
3331         case 'C':
3332         case 'c':
3333         {
3334           if (LocaleCompare(attribute,"channel") == 0)
3335             {
3336               ssize_t
3337                 option;
3338
3339               option=ParseChannelOption(SvPV(ST(i),na));
3340               if (option < 0)
3341                 {
3342                   ThrowPerlException(exception,OptionError,
3343                     "UnrecognizedType",SvPV(ST(i),na));
3344                   return;
3345                 }
3346               (void) SetPixelChannelMask(image,(ChannelType) option);
3347               break;
3348             }
3349           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3350             attribute);
3351           break;
3352         }
3353         case 'F':
3354         case 'f':
3355         {
3356           if (LocaleCompare(attribute,"fuzz") == 0)
3357             {
3358               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3359               break;
3360             }
3361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3362             attribute);
3363           break;
3364         }
3365         case 'I':
3366         case 'i':
3367         {
3368           if (LocaleCompare(attribute,"image") == 0)
3369             {
3370               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3371                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3372               break;
3373             }
3374           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3375             attribute);
3376           break;
3377         }
3378         case 'M':
3379         case 'm':
3380         {
3381           if (LocaleCompare(attribute,"metric") == 0)
3382             {
3383               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3384                 SvPV(ST(i),na));
3385               if (option < 0)
3386                 {
3387                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3388                     SvPV(ST(i),na));
3389                   break;
3390                 }
3391               metric=(MetricType) option;
3392               break;
3393             }
3394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3395             attribute);
3396           break;
3397         }
3398         default:
3399         {
3400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3401             attribute);
3402           break;
3403         }
3404       }
3405     }
3406     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3407       exception);
3408     if (difference_image != (Image *) NULL)
3409       {
3410         difference_image->error.mean_error_per_pixel=distortion;
3411         AddImageToRegistry(sv,difference_image);
3412         rv=newRV(sv);
3413         av_push(av,sv_bless(rv,hv));
3414         SvREFCNT_dec(sv);
3415       }
3416     exception=DestroyExceptionInfo(exception);
3417     ST(0)=av_reference;
3418     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3419     XSRETURN(1);
3420
3421   PerlException:
3422     InheritPerlException(exception,perl_exception);
3423     exception=DestroyExceptionInfo(exception);
3424     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3425     SvPOK_on(perl_exception);
3426     ST(0)=sv_2mortal(perl_exception);
3427     XSRETURN(1);
3428   }
3429 \f
3430 #
3431 ###############################################################################
3432 #                                                                             #
3433 #                                                                             #
3434 #                                                                             #
3435 #   C o m p l e x I m a g e s                                                 #
3436 #                                                                             #
3437 #                                                                             #
3438 #                                                                             #
3439 ###############################################################################
3440 #
3441 #
3442 void
3443 ComplexImages(ref)
3444   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3445   ALIAS:
3446     ComplexImages   = 1
3447     compleximages   = 2
3448   PPCODE:
3449   {
3450     AV
3451       *av;
3452
3453     char
3454       *attribute,
3455       *p;
3456
3457     ComplexOperator
3458       op;
3459
3460     ExceptionInfo
3461       *exception;
3462
3463     HV
3464       *hv;
3465
3466     Image
3467       *image;
3468
3469     register ssize_t
3470       i;
3471
3472     struct PackageInfo
3473       *info;
3474
3475     SV
3476       *perl_exception,
3477       *reference,
3478       *rv,
3479       *sv;
3480
3481     PERL_UNUSED_VAR(ref);
3482     PERL_UNUSED_VAR(ix);
3483     exception=AcquireExceptionInfo();
3484     perl_exception=newSVpv("",0);
3485     sv=NULL;
3486     if (sv_isobject(ST(0)) == 0)
3487       {
3488         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3489           PackageName);
3490         goto PerlException;
3491       }
3492     reference=SvRV(ST(0));
3493     hv=SvSTASH(reference);
3494     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3495     if (image == (Image *) NULL)
3496       {
3497         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3498           PackageName);
3499         goto PerlException;
3500       }
3501     op=UndefinedComplexOperator;
3502     if (items == 2)
3503       {
3504         ssize_t
3505           in;
3506
3507         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3508           SvPV(ST(1),na));
3509         if (in < 0)
3510           {
3511             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3512               SvPV(ST(1),na));
3513             return;
3514           }
3515         op=(ComplexOperator) in;
3516       }
3517     else
3518       for (i=2; i < items; i+=2)
3519       {
3520         attribute=(char *) SvPV(ST(i-1),na);
3521         switch (*attribute)
3522         {
3523           case 'O':
3524           case 'o':
3525           {
3526             if (LocaleCompare(attribute,"operator") == 0)
3527               {
3528                 ssize_t
3529                   in;
3530
3531                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3532                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3533                 if (in < 0)
3534                   {
3535                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3536                       SvPV(ST(i),na));
3537                     return;
3538                   }
3539                 op=(ComplexOperator) in;
3540                 break;
3541               }
3542             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3543               attribute);
3544             break;
3545           }
3546           default:
3547           {
3548             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3549               attribute);
3550             break;
3551           }
3552         }
3553       }
3554     image=ComplexImages(image,op,exception);
3555     if (image == (Image *) NULL)
3556       goto PerlException;
3557     /*
3558       Create blessed Perl array for the returned image.
3559     */
3560     av=newAV();
3561     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3562     SvREFCNT_dec(av);
3563     AddImageToRegistry(sv,image);
3564     rv=newRV(sv);
3565     av_push(av,sv_bless(rv,hv));
3566     SvREFCNT_dec(sv);
3567     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3568     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3569       "complex-%.*s",(int) (MagickPathExtent-9),
3570       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3571     (void) CopyMagickString(image->filename,info->image_info->filename,
3572       MagickPathExtent);
3573     SetImageInfo(info->image_info,0,exception);
3574     exception=DestroyExceptionInfo(exception);
3575     SvREFCNT_dec(perl_exception);
3576     XSRETURN(1);
3577
3578   PerlException:
3579     InheritPerlException(exception,perl_exception);
3580     exception=DestroyExceptionInfo(exception);
3581     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3582     SvPOK_on(perl_exception);
3583     ST(0)=sv_2mortal(perl_exception);
3584     XSRETURN(1);
3585   }
3586 \f
3587 #
3588 ###############################################################################
3589 #                                                                             #
3590 #                                                                             #
3591 #                                                                             #
3592 #   C o m p a r e L a y e r s                                                 #
3593 #                                                                             #
3594 #                                                                             #
3595 #                                                                             #
3596 ###############################################################################
3597 #
3598 #
3599 void
3600 CompareLayers(ref)
3601   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3602   ALIAS:
3603     CompareImagesLayers   = 1
3604     comparelayers        = 2
3605     compareimagelayers   = 3
3606   PPCODE:
3607   {
3608     AV
3609       *av;
3610
3611     char
3612       *attribute;
3613
3614     ExceptionInfo
3615       *exception;
3616
3617     HV
3618       *hv;
3619
3620     Image
3621       *image;
3622
3623     LayerMethod
3624       method;
3625
3626     register ssize_t
3627       i;
3628
3629     ssize_t
3630       option;
3631
3632     struct PackageInfo
3633       *info;
3634
3635     SV
3636       *av_reference,
3637       *perl_exception,
3638       *reference,
3639       *rv,
3640       *sv;
3641
3642     PERL_UNUSED_VAR(ref);
3643     PERL_UNUSED_VAR(ix);
3644     exception=AcquireExceptionInfo();
3645     perl_exception=newSVpv("",0);
3646     sv=NULL;
3647     if (sv_isobject(ST(0)) == 0)
3648       {
3649         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3650           PackageName);
3651         goto PerlException;
3652       }
3653     reference=SvRV(ST(0));
3654     hv=SvSTASH(reference);
3655     av=newAV();
3656     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3657     SvREFCNT_dec(av);
3658     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3659     if (image == (Image *) NULL)
3660       {
3661         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3662           PackageName);
3663         goto PerlException;
3664       }
3665     method=CompareAnyLayer;
3666     for (i=2; i < items; i+=2)
3667     {
3668       attribute=(char *) SvPV(ST(i-1),na);
3669       switch (*attribute)
3670       {
3671         case 'M':
3672         case 'm':
3673         {
3674           if (LocaleCompare(attribute,"method") == 0)
3675             {
3676               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3677                 SvPV(ST(i),na));
3678               if (option < 0)
3679                 {
3680                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3681                     SvPV(ST(i),na));
3682                   break;
3683                 }
3684                method=(LayerMethod) option;
3685               break;
3686             }
3687           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3688             attribute);
3689           break;
3690         }
3691         default:
3692         {
3693           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3694             attribute);
3695           break;
3696         }
3697       }
3698     }
3699     image=CompareImagesLayers(image,method,exception);
3700     if (image == (Image *) NULL)
3701       goto PerlException;
3702     for ( ; image; image=image->next)
3703     {
3704       AddImageToRegistry(sv,image);
3705       rv=newRV(sv);
3706       av_push(av,sv_bless(rv,hv));
3707       SvREFCNT_dec(sv);
3708     }
3709     exception=DestroyExceptionInfo(exception);
3710     ST(0)=av_reference;
3711     SvREFCNT_dec(perl_exception);
3712     XSRETURN(1);
3713
3714   PerlException:
3715     InheritPerlException(exception,perl_exception);
3716     exception=DestroyExceptionInfo(exception);
3717     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3718     SvPOK_on(perl_exception);
3719     ST(0)=sv_2mortal(perl_exception);
3720     XSRETURN(1);
3721   }
3722 \f
3723 #
3724 ###############################################################################
3725 #                                                                             #
3726 #                                                                             #
3727 #                                                                             #
3728 #   D e s t r o y                                                             #
3729 #                                                                             #
3730 #                                                                             #
3731 #                                                                             #
3732 ###############################################################################
3733 #
3734 #
3735 void
3736 DESTROY(ref)
3737   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3738   PPCODE:
3739   {
3740     SV
3741       *reference;
3742
3743     PERL_UNUSED_VAR(ref);
3744     if (sv_isobject(ST(0)) == 0)
3745       croak("ReferenceIsNotMyType");
3746     reference=SvRV(ST(0));
3747     switch (SvTYPE(reference))
3748     {
3749       case SVt_PVAV:
3750       {
3751         char
3752           message[MagickPathExtent];
3753
3754         const SV
3755           *key;
3756
3757         HV
3758           *hv;
3759
3760         GV
3761           **gvp;
3762
3763         struct PackageInfo
3764           *info;
3765
3766         SV
3767           *sv;
3768
3769         /*
3770           Array (AV *) reference
3771         */
3772         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3773           XS_VERSION,reference);
3774         hv=gv_stashpv(PackageName, FALSE);
3775         if (!hv)
3776           break;
3777         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3778         if (!gvp)
3779           break;
3780         sv=GvSV(*gvp);
3781         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3782           {
3783             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3784             DestroyPackageInfo(info);
3785           }
3786         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3787         (void) key;
3788         break;
3789       }
3790       case SVt_PVMG:
3791       {
3792         Image
3793           *image;
3794
3795         /*
3796           Blessed scalar = (Image *) SvIV(reference)
3797         */
3798         image=INT2PTR(Image *,SvIV(reference));
3799         if (image != (Image *) NULL)
3800           DeleteImageFromRegistry(reference,image);
3801         break;
3802       }
3803       default:
3804         break;
3805     }
3806   }
3807 \f
3808 #
3809 ###############################################################################
3810 #                                                                             #
3811 #                                                                             #
3812 #                                                                             #
3813 #   D i s p l a y                                                             #
3814 #                                                                             #
3815 #                                                                             #
3816 #                                                                             #
3817 ###############################################################################
3818 #
3819 #
3820 void
3821 Display(ref,...)
3822   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3823   ALIAS:
3824     DisplayImage  = 1
3825     display       = 2
3826     displayimage  = 3
3827   PPCODE:
3828   {
3829     ExceptionInfo
3830       *exception;
3831
3832     Image
3833       *image;
3834
3835     register ssize_t
3836       i;
3837
3838     struct PackageInfo
3839       *info,
3840       *package_info;
3841
3842     SV
3843       *perl_exception,
3844       *reference;
3845
3846     PERL_UNUSED_VAR(ref);
3847     PERL_UNUSED_VAR(ix);
3848     exception=AcquireExceptionInfo();
3849     perl_exception=newSVpv("",0);
3850     package_info=(struct PackageInfo *) NULL;
3851     if (sv_isobject(ST(0)) == 0)
3852       {
3853         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3854           PackageName);
3855         goto PerlException;
3856       }
3857     reference=SvRV(ST(0));
3858     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3859     if (image == (Image *) NULL)
3860       {
3861         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3862           PackageName);
3863         goto PerlException;
3864       }
3865     package_info=ClonePackageInfo(info,exception);
3866     if (items == 2)
3867       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3868     else
3869       if (items > 2)
3870         for (i=2; i < items; i+=2)
3871           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3872             exception);
3873     (void) DisplayImages(package_info->image_info,image,exception);
3874     (void) CatchImageException(image);
3875
3876   PerlException:
3877     if (package_info != (struct PackageInfo *) NULL)
3878       DestroyPackageInfo(package_info);
3879     InheritPerlException(exception,perl_exception);
3880     exception=DestroyExceptionInfo(exception);
3881     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3882     SvPOK_on(perl_exception);
3883     ST(0)=sv_2mortal(perl_exception);
3884     XSRETURN(1);
3885   }
3886 \f
3887 #
3888 ###############################################################################
3889 #                                                                             #
3890 #                                                                             #
3891 #                                                                             #
3892 #   E v a l u a t e I m a g e s                                               #
3893 #                                                                             #
3894 #                                                                             #
3895 #                                                                             #
3896 ###############################################################################
3897 #
3898 #
3899 void
3900 EvaluateImages(ref)
3901   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3902   ALIAS:
3903     EvaluateImages   = 1
3904     evaluateimages   = 2
3905   PPCODE:
3906   {
3907     AV
3908       *av;
3909
3910     char
3911       *attribute,
3912       *p;
3913
3914     ExceptionInfo
3915       *exception;
3916
3917     HV
3918       *hv;
3919
3920     Image
3921       *image;
3922
3923     MagickEvaluateOperator
3924       op;
3925
3926     register ssize_t
3927       i;
3928
3929     struct PackageInfo
3930       *info;
3931
3932     SV
3933       *perl_exception,
3934       *reference,
3935       *rv,
3936       *sv;
3937
3938     PERL_UNUSED_VAR(ref);
3939     PERL_UNUSED_VAR(ix);
3940     exception=AcquireExceptionInfo();
3941     perl_exception=newSVpv("",0);
3942     sv=NULL;
3943     if (sv_isobject(ST(0)) == 0)
3944       {
3945         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3946           PackageName);
3947         goto PerlException;
3948       }
3949     reference=SvRV(ST(0));
3950     hv=SvSTASH(reference);
3951     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3952     if (image == (Image *) NULL)
3953       {
3954         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3955           PackageName);
3956         goto PerlException;
3957       }
3958     op=MeanEvaluateOperator;
3959     if (items == 2)
3960       {
3961         ssize_t
3962           in;
3963
3964         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3965           SvPV(ST(1),na));
3966         if (in < 0)
3967           {
3968             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3969               SvPV(ST(1),na));
3970             return;
3971           }
3972         op=(MagickEvaluateOperator) in;
3973       }
3974     else
3975       for (i=2; i < items; i+=2)
3976       {
3977         attribute=(char *) SvPV(ST(i-1),na);
3978         switch (*attribute)
3979         {
3980           case 'O':
3981           case 'o':
3982           {
3983             if (LocaleCompare(attribute,"operator") == 0)
3984               {
3985                 ssize_t
3986                   in;
3987
3988                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3989                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3990                 if (in < 0)
3991                   {
3992                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3993                       SvPV(ST(i),na));
3994                     return;
3995                   }
3996                 op=(MagickEvaluateOperator) in;
3997                 break;
3998               }
3999             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4000               attribute);
4001             break;
4002           }
4003           default:
4004           {
4005             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4006               attribute);
4007             break;
4008           }
4009         }
4010       }
4011     image=EvaluateImages(image,op,exception);
4012     if (image == (Image *) NULL)
4013       goto PerlException;
4014     /*
4015       Create blessed Perl array for the returned image.
4016     */
4017     av=newAV();
4018     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4019     SvREFCNT_dec(av);
4020     AddImageToRegistry(sv,image);
4021     rv=newRV(sv);
4022     av_push(av,sv_bless(rv,hv));
4023     SvREFCNT_dec(sv);
4024     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4025     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4026       "evaluate-%.*s",(int) (MagickPathExtent-9),
4027       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4028     (void) CopyMagickString(image->filename,info->image_info->filename,
4029       MagickPathExtent);
4030     SetImageInfo(info->image_info,0,exception);
4031     exception=DestroyExceptionInfo(exception);
4032     SvREFCNT_dec(perl_exception);
4033     XSRETURN(1);
4034
4035   PerlException:
4036     InheritPerlException(exception,perl_exception);
4037     exception=DestroyExceptionInfo(exception);
4038     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4039     SvPOK_on(perl_exception);
4040     ST(0)=sv_2mortal(perl_exception);
4041     XSRETURN(1);
4042   }
4043 \f
4044 #
4045 ###############################################################################
4046 #                                                                             #
4047 #                                                                             #
4048 #                                                                             #
4049 #   F e a t u r e s                                                           #
4050 #                                                                             #
4051 #                                                                             #
4052 #                                                                             #
4053 ###############################################################################
4054 #
4055 #
4056 void
4057 Features(ref,...)
4058   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4059   ALIAS:
4060     FeaturesImage = 1
4061     features      = 2
4062     featuresimage = 3
4063   PPCODE:
4064   {
4065 #define ChannelFeatures(channel,direction) \
4066 { \
4067   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4068     channel_features[channel].angular_second_moment[direction]); \
4069   PUSHs(sv_2mortal(newSVpv(message,0))); \
4070   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4071     channel_features[channel].contrast[direction]); \
4072   PUSHs(sv_2mortal(newSVpv(message,0))); \
4073   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4074     channel_features[channel].contrast[direction]); \
4075   PUSHs(sv_2mortal(newSVpv(message,0))); \
4076   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4077     channel_features[channel].variance_sum_of_squares[direction]); \
4078   PUSHs(sv_2mortal(newSVpv(message,0))); \
4079   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4080     channel_features[channel].inverse_difference_moment[direction]); \
4081   PUSHs(sv_2mortal(newSVpv(message,0))); \
4082   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4083     channel_features[channel].sum_average[direction]); \
4084   PUSHs(sv_2mortal(newSVpv(message,0))); \
4085   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4086     channel_features[channel].sum_variance[direction]); \
4087   PUSHs(sv_2mortal(newSVpv(message,0))); \
4088   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4089     channel_features[channel].sum_entropy[direction]); \
4090   PUSHs(sv_2mortal(newSVpv(message,0))); \
4091   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4092     channel_features[channel].entropy[direction]); \
4093   PUSHs(sv_2mortal(newSVpv(message,0))); \
4094   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4095     channel_features[channel].difference_variance[direction]); \
4096   PUSHs(sv_2mortal(newSVpv(message,0))); \
4097   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4098     channel_features[channel].difference_entropy[direction]); \
4099   PUSHs(sv_2mortal(newSVpv(message,0))); \
4100   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4101     channel_features[channel].measure_of_correlation_1[direction]); \
4102   PUSHs(sv_2mortal(newSVpv(message,0))); \
4103   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4104     channel_features[channel].measure_of_correlation_2[direction]); \
4105   PUSHs(sv_2mortal(newSVpv(message,0))); \
4106   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4107     channel_features[channel].maximum_correlation_coefficient[direction]); \
4108   PUSHs(sv_2mortal(newSVpv(message,0))); \
4109 }
4110
4111     AV
4112       *av;
4113
4114     char
4115       *attribute,
4116       message[MagickPathExtent];
4117
4118     ChannelFeatures
4119       *channel_features;
4120
4121     double
4122       distance;
4123
4124     ExceptionInfo
4125       *exception;
4126
4127     Image
4128       *image;
4129
4130     register ssize_t
4131       i;
4132
4133     ssize_t
4134       count;
4135
4136     struct PackageInfo
4137       *info;
4138
4139     SV
4140       *perl_exception,
4141       *reference;
4142
4143     PERL_UNUSED_VAR(ref);
4144     PERL_UNUSED_VAR(ix);
4145     exception=AcquireExceptionInfo();
4146     perl_exception=newSVpv("",0);
4147     av=NULL;
4148     if (sv_isobject(ST(0)) == 0)
4149       {
4150         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4151           PackageName);
4152         goto PerlException;
4153       }
4154     reference=SvRV(ST(0));
4155     av=newAV();
4156     SvREFCNT_dec(av);
4157     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4158     if (image == (Image *) NULL)
4159       {
4160         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4161           PackageName);
4162         goto PerlException;
4163       }
4164     distance=1.0;
4165     for (i=2; i < items; i+=2)
4166     {
4167       attribute=(char *) SvPV(ST(i-1),na);
4168       switch (*attribute)
4169       {
4170         case 'D':
4171         case 'd':
4172         {
4173           if (LocaleCompare(attribute,"distance") == 0)
4174             {
4175               distance=StringToLong((char *) SvPV(ST(1),na));
4176               break;
4177             }
4178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4179             attribute);
4180           break;
4181         }
4182         default:
4183         {
4184           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4185             attribute);
4186           break;
4187         }
4188       }
4189     }
4190     count=0;
4191     for ( ; image; image=image->next)
4192     {
4193       channel_features=GetImageFeatures(image,distance,exception);
4194       if (channel_features == (ChannelFeatures *) NULL)
4195         continue;
4196       count++;
4197       EXTEND(sp,280*count);
4198       for (i=0; i < 4; i++)
4199       {
4200         ChannelFeatures(RedChannel,i);
4201         ChannelFeatures(GreenChannel,i);
4202         ChannelFeatures(BlueChannel,i);
4203         if (image->colorspace == CMYKColorspace)
4204           ChannelFeatures(BlackChannel,i);
4205         if (image->alpha_trait != UndefinedPixelTrait)
4206           ChannelFeatures(AlphaChannel,i);
4207       }
4208       channel_features=(ChannelFeatures *)
4209         RelinquishMagickMemory(channel_features);
4210     }
4211
4212   PerlException:
4213     InheritPerlException(exception,perl_exception);
4214     exception=DestroyExceptionInfo(exception);
4215     SvREFCNT_dec(perl_exception);
4216   }
4217 \f
4218 #
4219 ###############################################################################
4220 #                                                                             #
4221 #                                                                             #
4222 #                                                                             #
4223 #   F l a t t e n                                                             #
4224 #                                                                             #
4225 #                                                                             #
4226 #                                                                             #
4227 ###############################################################################
4228 #
4229 #
4230 void
4231 Flatten(ref)
4232   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4233   ALIAS:
4234     FlattenImage   = 1
4235     flatten        = 2
4236     flattenimage   = 3
4237   PPCODE:
4238   {
4239     AV
4240       *av;
4241
4242     char
4243       *attribute,
4244       *p;
4245
4246     ExceptionInfo
4247       *exception;
4248
4249     HV
4250       *hv;
4251
4252     Image
4253       *image;
4254
4255     PixelInfo
4256       background_color;
4257
4258     register ssize_t
4259       i;
4260
4261     struct PackageInfo
4262       *info;
4263
4264     SV
4265       *perl_exception,
4266       *reference,
4267       *rv,
4268       *sv;
4269
4270     PERL_UNUSED_VAR(ref);
4271     PERL_UNUSED_VAR(ix);
4272     exception=AcquireExceptionInfo();
4273     perl_exception=newSVpv("",0);
4274     sv=NULL;
4275     if (sv_isobject(ST(0)) == 0)
4276       {
4277         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4278           PackageName);
4279         goto PerlException;
4280       }
4281     reference=SvRV(ST(0));
4282     hv=SvSTASH(reference);
4283     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4284     if (image == (Image *) NULL)
4285       {
4286         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4287           PackageName);
4288         goto PerlException;
4289       }
4290     background_color=image->background_color;
4291     if (items == 2)
4292       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4293         &background_color,exception);
4294     else
4295       for (i=2; i < items; i+=2)
4296       {
4297         attribute=(char *) SvPV(ST(i-1),na);
4298         switch (*attribute)
4299         {
4300           case 'B':
4301           case 'b':
4302           {
4303             if (LocaleCompare(attribute,"background") == 0)
4304               {
4305                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4306                   AllCompliance,&background_color,exception);
4307                 break;
4308               }
4309             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4310               attribute);
4311             break;
4312           }
4313           default:
4314           {
4315             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4316               attribute);
4317             break;
4318           }
4319         }
4320       }
4321     image->background_color=background_color;
4322     image=MergeImageLayers(image,FlattenLayer,exception);
4323     if (image == (Image *) NULL)
4324       goto PerlException;
4325     /*
4326       Create blessed Perl array for the returned image.
4327     */
4328     av=newAV();
4329     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4330     SvREFCNT_dec(av);
4331     AddImageToRegistry(sv,image);
4332     rv=newRV(sv);
4333     av_push(av,sv_bless(rv,hv));
4334     SvREFCNT_dec(sv);
4335     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4336     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4337       "flatten-%.*s",(int) (MagickPathExtent-9),
4338       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4339     (void) CopyMagickString(image->filename,info->image_info->filename,
4340       MagickPathExtent);
4341     SetImageInfo(info->image_info,0,exception);
4342     exception=DestroyExceptionInfo(exception);
4343     SvREFCNT_dec(perl_exception);
4344     XSRETURN(1);
4345
4346   PerlException:
4347     InheritPerlException(exception,perl_exception);
4348     exception=DestroyExceptionInfo(exception);
4349     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4350     SvPOK_on(perl_exception);  /* return messages in string context */
4351     ST(0)=sv_2mortal(perl_exception);
4352     XSRETURN(1);
4353   }
4354 \f
4355 #
4356 ###############################################################################
4357 #                                                                             #
4358 #                                                                             #
4359 #                                                                             #
4360 #   F x                                                                       #
4361 #                                                                             #
4362 #                                                                             #
4363 #                                                                             #
4364 ###############################################################################
4365 #
4366 #
4367 void
4368 Fx(ref,...)
4369   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4370   ALIAS:
4371     FxImage  = 1
4372     fx       = 2
4373     fximage  = 3
4374   PPCODE:
4375   {
4376     AV
4377       *av;
4378
4379     char
4380       *attribute,
4381       expression[MagickPathExtent];
4382
4383     ChannelType
4384       channel,
4385       channel_mask;
4386
4387     ExceptionInfo
4388       *exception;
4389
4390     HV
4391       *hv;
4392
4393     Image
4394       *image;
4395
4396     register ssize_t
4397       i;
4398
4399     struct PackageInfo
4400       *info;
4401
4402     SV
4403       *av_reference,
4404       *perl_exception,
4405       *reference,
4406       *rv,
4407       *sv;
4408
4409     PERL_UNUSED_VAR(ref);
4410     PERL_UNUSED_VAR(ix);
4411     exception=AcquireExceptionInfo();
4412     perl_exception=newSVpv("",0);
4413     sv=NULL;
4414     attribute=NULL;
4415     av=NULL;
4416     if (sv_isobject(ST(0)) == 0)
4417       {
4418         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4419           PackageName);
4420         goto PerlException;
4421       }
4422     reference=SvRV(ST(0));
4423     hv=SvSTASH(reference);
4424     av=newAV();
4425     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4426     SvREFCNT_dec(av);
4427     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4428     if (image == (Image *) NULL)
4429       {
4430         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4431           PackageName);
4432         goto PerlException;
4433       }
4434     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4435     /*
4436       Get options.
4437     */
4438     channel=DefaultChannels;
4439     (void) CopyMagickString(expression,"u",MagickPathExtent);
4440     if (items == 2)
4441       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4442     else
4443       for (i=2; i < items; i+=2)
4444       {
4445         attribute=(char *) SvPV(ST(i-1),na);
4446         switch (*attribute)
4447         {
4448           case 'C':
4449           case 'c':
4450           {
4451             if (LocaleCompare(attribute,"channel") == 0)
4452               {
4453                 ssize_t
4454                   option;
4455
4456                 option=ParseChannelOption(SvPV(ST(i),na));
4457                 if (option < 0)
4458                   {
4459                     ThrowPerlException(exception,OptionError,
4460                       "UnrecognizedType",SvPV(ST(i),na));
4461                     return;
4462                   }
4463                 channel=(ChannelType) option;
4464                 break;
4465               }
4466             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4467               attribute);
4468             break;
4469           }
4470           case 'E':
4471           case 'e':
4472           {
4473             if (LocaleCompare(attribute,"expression") == 0)
4474               {
4475                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4476                   MagickPathExtent);
4477                 break;
4478               }
4479             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4480               attribute);
4481             break;
4482           }
4483           default:
4484           {
4485             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4486               attribute);
4487             break;
4488           }
4489         }
4490       }
4491     channel_mask=SetImageChannelMask(image,channel);
4492     image=FxImage(image,expression,exception);
4493     if (image != (Image *) NULL)
4494       (void) SetImageChannelMask(image,channel_mask);
4495     if (image == (Image *) NULL)
4496       goto PerlException;
4497     for ( ; image; image=image->next)
4498     {
4499       AddImageToRegistry(sv,image);
4500       rv=newRV(sv);
4501       av_push(av,sv_bless(rv,hv));
4502       SvREFCNT_dec(sv);
4503     }
4504     exception=DestroyExceptionInfo(exception);
4505     ST(0)=av_reference;
4506     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4507     XSRETURN(1);
4508
4509   PerlException:
4510     InheritPerlException(exception,perl_exception);
4511     exception=DestroyExceptionInfo(exception);
4512     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4513     SvPOK_on(perl_exception);
4514     ST(0)=sv_2mortal(perl_exception);
4515     XSRETURN(1);
4516   }
4517 \f
4518 #
4519 ###############################################################################
4520 #                                                                             #
4521 #                                                                             #
4522 #                                                                             #
4523 #   G e t                                                                     #
4524 #                                                                             #
4525 #                                                                             #
4526 #                                                                             #
4527 ###############################################################################
4528 #
4529 #
4530 void
4531 Get(ref,...)
4532   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4533   ALIAS:
4534     GetAttributes = 1
4535     GetAttribute  = 2
4536     get           = 3
4537     getattributes = 4
4538     getattribute  = 5
4539   PPCODE:
4540   {
4541     char
4542       *attribute,
4543       color[MagickPathExtent];
4544
4545     const char
4546       *value;
4547
4548     ExceptionInfo
4549       *exception;
4550
4551     Image
4552       *image;
4553
4554     long
4555       j;
4556
4557     register ssize_t
4558       i;
4559
4560     struct PackageInfo
4561       *info;
4562
4563     SV
4564       *perl_exception,
4565       *reference,
4566       *s;
4567
4568     PERL_UNUSED_VAR(ref);
4569     PERL_UNUSED_VAR(ix);
4570     exception=AcquireExceptionInfo();
4571     perl_exception=newSVpv("",0);
4572     if (sv_isobject(ST(0)) == 0)
4573       {
4574         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4575           PackageName);
4576         XSRETURN_EMPTY;
4577       }
4578     reference=SvRV(ST(0));
4579     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4580     if (image == (Image *) NULL && !info)
4581       XSRETURN_EMPTY;
4582     EXTEND(sp,items);
4583     for (i=1; i < items; i++)
4584     {
4585       attribute=(char *) SvPV(ST(i),na);
4586       s=NULL;
4587       switch (*attribute)
4588       {
4589         case 'A':
4590         case 'a':
4591         {
4592           if (LocaleCompare(attribute,"adjoin") == 0)
4593             {
4594               if (info)
4595                 s=newSViv((ssize_t) info->image_info->adjoin);
4596               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4597               continue;
4598             }
4599           if (LocaleCompare(attribute,"antialias") == 0)
4600             {
4601               if (info)
4602                 s=newSViv((ssize_t) info->image_info->antialias);
4603               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4604               continue;
4605             }
4606           if (LocaleCompare(attribute,"area") == 0)
4607             {
4608               s=newSViv(GetMagickResource(AreaResource));
4609               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4610               continue;
4611             }
4612           if (LocaleCompare(attribute,"attenuate") == 0)
4613             {
4614               const char
4615                 *value;
4616
4617               value=GetImageProperty(image,attribute,exception);
4618               if (value != (const char *) NULL)
4619                 s=newSVpv(value,0);
4620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621               continue;
4622             }
4623           if (LocaleCompare(attribute,"authenticate") == 0)
4624             {
4625               if (info)
4626                 {
4627                   const char
4628                     *option;
4629
4630                   option=GetImageOption(info->image_info,attribute);
4631                   if (option != (const char *) NULL)
4632                     s=newSVpv(option,0);
4633                 }
4634               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4635               continue;
4636             }
4637           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4638             attribute);
4639           break;
4640         }
4641         case 'B':
4642         case 'b':
4643         {
4644           if (LocaleCompare(attribute,"background") == 0)
4645             {
4646               if (image == (Image *) NULL)
4647                 break;
4648               (void) FormatLocaleString(color,MagickPathExtent,
4649                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4650                 (double) image->background_color.green,
4651                 (double) image->background_color.blue,
4652                 (double) image->background_color.alpha);
4653               s=newSVpv(color,0);
4654               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4655               continue;
4656             }
4657           if (LocaleCompare(attribute,"base-columns") == 0)
4658             {
4659               if (image != (Image *) NULL)
4660                 s=newSViv((ssize_t) image->magick_columns);
4661               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4662               continue;
4663             }
4664           if (LocaleCompare(attribute,"base-filename") == 0)
4665             {
4666               if (image != (Image *) NULL)
4667                 s=newSVpv(image->magick_filename,0);
4668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4669               continue;
4670             }
4671           if (LocaleCompare(attribute,"base-height") == 0)
4672             {
4673               if (image != (Image *) NULL)
4674                 s=newSViv((ssize_t) image->magick_rows);
4675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4676               continue;
4677             }
4678           if (LocaleCompare(attribute,"base-rows") == 0)
4679             {
4680               if (image != (Image *) NULL)
4681                 s=newSViv((ssize_t) image->magick_rows);
4682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683               continue;
4684             }
4685           if (LocaleCompare(attribute,"base-width") == 0)
4686             {
4687               if (image != (Image *) NULL)
4688                 s=newSViv((ssize_t) image->magick_columns);
4689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4690               continue;
4691             }
4692           if (LocaleCompare(attribute,"blue-primary") == 0)
4693             {
4694               if (image == (Image *) NULL)
4695                 break;
4696               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4697                 image->chromaticity.blue_primary.x,
4698                 image->chromaticity.blue_primary.y);
4699               s=newSVpv(color,0);
4700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701               continue;
4702             }
4703           if (LocaleCompare(attribute,"bordercolor") == 0)
4704             {
4705               if (image == (Image *) NULL)
4706                 break;
4707               (void) FormatLocaleString(color,MagickPathExtent,
4708                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4709                 (double) image->border_color.green,
4710                 (double) image->border_color.blue,
4711                 (double) image->border_color.alpha);
4712               s=newSVpv(color,0);
4713               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4714               continue;
4715             }
4716           if (LocaleCompare(attribute,"bounding-box") == 0)
4717             {
4718               char
4719                 geometry[MagickPathExtent];
4720
4721               RectangleInfo
4722                 page;
4723
4724               if (image == (Image *) NULL)
4725                 break;
4726               page=GetImageBoundingBox(image,exception);
4727               (void) FormatLocaleString(geometry,MagickPathExtent,
4728                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4729                 page.height,(double) page.x,(double) page.y);
4730               s=newSVpv(geometry,0);
4731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4732               continue;
4733             }
4734           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4735             attribute);
4736           break;
4737         }
4738         case 'C':
4739         case 'c':
4740         {
4741           if (LocaleCompare(attribute,"class") == 0)
4742             {
4743               if (image == (Image *) NULL)
4744                 break;
4745               s=newSViv(image->storage_class);
4746               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4747                 image->storage_class));
4748               SvIOK_on(s);
4749               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4750               continue;
4751             }
4752           if (LocaleCompare(attribute,"clip-mask") == 0)
4753             {
4754               if (image != (Image *) NULL)
4755                 {
4756                   Image
4757                     *mask_image;
4758
4759                   SV
4760                     *sv;
4761
4762                   sv=NULL;
4763                   if (image->read_mask == MagickFalse)
4764                     ClipImage(image,exception);
4765                   mask_image=GetImageMask(image,exception);
4766                   if (mask_image != (Image *) NULL)
4767                     {
4768                       AddImageToRegistry(sv,mask_image);
4769                       s=sv_bless(newRV(sv),SvSTASH(reference));
4770                     }
4771                 }
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           if (LocaleCompare(attribute,"clip-path") == 0)
4776             {
4777               if (image != (Image *) NULL)
4778                 {
4779                   Image
4780                     *mask_image;
4781
4782                   SV
4783                     *sv;
4784
4785                   sv=NULL;
4786                   if (image->read_mask != MagickFalse)
4787                     ClipImage(image,exception);
4788                   mask_image=GetImageMask(image,exception);
4789                   if (mask_image != (Image *) NULL)
4790                     {
4791                       AddImageToRegistry(sv,mask_image);
4792                       s=sv_bless(newRV(sv),SvSTASH(reference));
4793                     }
4794                 }
4795               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4796               continue;
4797             }
4798           if (LocaleCompare(attribute,"compression") == 0)
4799             {
4800               j=info ? info->image_info->compression : image ?
4801                 image->compression : UndefinedCompression;
4802               if (info)
4803                 if (info->image_info->compression == UndefinedCompression)
4804                   j=image->compression;
4805               s=newSViv(j);
4806               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4807                 j));
4808               SvIOK_on(s);
4809               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4810               continue;
4811             }
4812           if (LocaleCompare(attribute,"colorspace") == 0)
4813             {
4814               j=image ? image->colorspace : RGBColorspace;
4815               s=newSViv(j);
4816               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4817                 j));
4818               SvIOK_on(s);
4819               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4820               continue;
4821             }
4822           if (LocaleCompare(attribute,"colors") == 0)
4823             {
4824               if (image != (Image *) NULL)
4825                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4826                   exception));
4827               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4828               continue;
4829             }
4830           if (LocaleNCompare(attribute,"colormap",8) == 0)
4831             {
4832               int
4833                 items;
4834
4835               if (image == (Image *) NULL || !image->colormap)
4836                 break;
4837               j=0;
4838               items=sscanf(attribute,"%*[^[][%ld",&j);
4839               (void) items;
4840               if (j > (ssize_t) image->colors)
4841                 j%=image->colors;
4842               (void) FormatLocaleString(color,MagickPathExtent,
4843                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4844                 (double) image->colormap[j].green,
4845                 (double) image->colormap[j].blue,
4846                 (double) image->colormap[j].alpha);
4847               s=newSVpv(color,0);
4848               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4849               continue;
4850             }
4851           if (LocaleCompare(attribute,"columns") == 0)
4852             {
4853               if (image != (Image *) NULL)
4854                 s=newSViv((ssize_t) image->columns);
4855               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4856               continue;
4857             }
4858           if (LocaleCompare(attribute,"comment") == 0)
4859             {
4860               const char
4861                 *value;
4862
4863               value=GetImageProperty(image,attribute,exception);
4864               if (value != (const char *) NULL)
4865                 s=newSVpv(value,0);
4866               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867               continue;
4868             }
4869           if (LocaleCompare(attribute,"copyright") == 0)
4870             {
4871               s=newSVpv(GetMagickCopyright(),0);
4872               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4873               continue;
4874             }
4875           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4876             attribute);
4877           break;
4878         }
4879         case 'D':
4880         case 'd':
4881         {
4882           if (LocaleCompare(attribute,"density") == 0)
4883             {
4884               char
4885                 geometry[MagickPathExtent];
4886
4887               if (image == (Image *) NULL)
4888                 break;
4889               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4890                 image->resolution.x,image->resolution.y);
4891               s=newSVpv(geometry,0);
4892               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4893               continue;
4894             }
4895           if (LocaleCompare(attribute,"delay") == 0)
4896             {
4897               if (image != (Image *) NULL)
4898                 s=newSViv((ssize_t) image->delay);
4899               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4900               continue;
4901             }
4902           if (LocaleCompare(attribute,"depth") == 0)
4903             {
4904               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4905               if (image != (Image *) NULL)
4906                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4907               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4908               continue;
4909             }
4910           if (LocaleCompare(attribute,"directory") == 0)
4911             {
4912               if (image && image->directory)
4913                 s=newSVpv(image->directory,0);
4914               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4915               continue;
4916             }
4917           if (LocaleCompare(attribute,"dispose") == 0)
4918             {
4919               if (image == (Image *) NULL)
4920                 break;
4921
4922               s=newSViv(image->dispose);
4923               (void) sv_setpv(s,
4924                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4925               SvIOK_on(s);
4926               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4927               continue;
4928             }
4929           if (LocaleCompare(attribute,"disk") == 0)
4930             {
4931               s=newSViv(GetMagickResource(DiskResource));
4932               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4933               continue;
4934             }
4935           if (LocaleCompare(attribute,"dither") == 0)
4936             {
4937               if (info)
4938                 s=newSViv((ssize_t) info->image_info->dither);
4939               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4940               continue;
4941             }
4942           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4943             {
4944               if (info && info->image_info->server_name)
4945                 s=newSVpv(info->image_info->server_name,0);
4946               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4947               continue;
4948             }
4949           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4950             attribute);
4951           break;
4952         }
4953         case 'E':
4954         case 'e':
4955         {
4956           if (LocaleCompare(attribute,"elapsed-time") == 0)
4957             {
4958               if (image != (Image *) NULL)
4959                 s=newSVnv(GetElapsedTime(&image->timer));
4960               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4961               continue;
4962             }
4963           if (LocaleCompare(attribute,"endian") == 0)
4964             {
4965               j=info ? info->image_info->endian : image ? image->endian :
4966                 UndefinedEndian;
4967               s=newSViv(j);
4968               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4969               SvIOK_on(s);
4970               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4971               continue;
4972             }
4973           if (LocaleCompare(attribute,"error") == 0)
4974             {
4975               if (image != (Image *) NULL)
4976                 s=newSVnv(image->error.mean_error_per_pixel);
4977               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4978               continue;
4979             }
4980           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4981             attribute);
4982           break;
4983         }
4984         case 'F':
4985         case 'f':
4986         {
4987           if (LocaleCompare(attribute,"filesize") == 0)
4988             {
4989               if (image != (Image *) NULL)
4990                 s=newSViv((ssize_t) GetBlobSize(image));
4991               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4992               continue;
4993             }
4994           if (LocaleCompare(attribute,"filename") == 0)
4995             {
4996               if (info && info->image_info->filename &&
4997                   *info->image_info->filename)
4998                 s=newSVpv(info->image_info->filename,0);
4999               if (image != (Image *) NULL)
5000                 s=newSVpv(image->filename,0);
5001               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002               continue;
5003             }
5004           if (LocaleCompare(attribute,"filter") == 0)
5005             {
5006               s=image ? newSViv(image->filter) : newSViv(0);
5007               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5008                 image->filter));
5009               SvIOK_on(s);
5010               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5011               continue;
5012             }
5013           if (LocaleCompare(attribute,"font") == 0)
5014             {
5015               if (info && info->image_info->font)
5016                 s=newSVpv(info->image_info->font,0);
5017               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018               continue;
5019             }
5020           if (LocaleCompare(attribute,"foreground") == 0)
5021             continue;
5022           if (LocaleCompare(attribute,"format") == 0)
5023             {
5024               const MagickInfo
5025                 *magick_info;
5026
5027               magick_info=(const MagickInfo *) NULL;
5028               if (info && (*info->image_info->magick != '\0'))
5029                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5030               if (image != (Image *) NULL)
5031                 magick_info=GetMagickInfo(image->magick,exception);
5032               if ((magick_info != (const MagickInfo *) NULL) &&
5033                   (*magick_info->description != '\0'))
5034                 s=newSVpv((char *) magick_info->description,0);
5035               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5036               continue;
5037             }
5038           if (LocaleCompare(attribute,"fuzz") == 0)
5039             {
5040               if (info)
5041                 s=newSVnv(info->image_info->fuzz);
5042               if (image != (Image *) NULL)
5043                 s=newSVnv(image->fuzz);
5044               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5045               continue;
5046             }
5047           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5048             attribute);
5049           break;
5050         }
5051         case 'G':
5052         case 'g':
5053         {
5054           if (LocaleCompare(attribute,"gamma") == 0)
5055             {
5056               if (image != (Image *) NULL)
5057                 s=newSVnv(image->gamma);
5058               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5059               continue;
5060             }
5061           if (LocaleCompare(attribute,"geometry") == 0)
5062             {
5063               if (image && image->geometry)
5064                 s=newSVpv(image->geometry,0);
5065               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5066               continue;
5067             }
5068           if (LocaleCompare(attribute,"gravity") == 0)
5069             {
5070               s=image ? newSViv(image->gravity) : newSViv(0);
5071               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5072                 image->gravity));
5073               SvIOK_on(s);
5074               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5075               continue;
5076             }
5077           if (LocaleCompare(attribute,"green-primary") == 0)
5078             {
5079               if (image == (Image *) NULL)
5080                 break;
5081               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5082                 image->chromaticity.green_primary.x,
5083                 image->chromaticity.green_primary.y);
5084               s=newSVpv(color,0);
5085               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5086               continue;
5087             }
5088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5089             attribute);
5090           break;
5091         }
5092         case 'H':
5093         case 'h':
5094         {
5095           if (LocaleCompare(attribute,"height") == 0)
5096             {
5097               if (image != (Image *) NULL)
5098                 s=newSViv((ssize_t) image->rows);
5099               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5100               continue;
5101             }
5102           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5103             attribute);
5104           break;
5105         }
5106         case 'I':
5107         case 'i':
5108         {
5109           if (LocaleCompare(attribute,"icc") == 0)
5110             {
5111               if (image != (Image *) NULL)
5112                 {
5113                   const StringInfo
5114                     *profile;
5115
5116                   profile=GetImageProfile(image,"icc");
5117                   if (profile != (StringInfo *) NULL)
5118                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5119                       GetStringInfoLength(profile));
5120                 }
5121               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122               continue;
5123             }
5124           if (LocaleCompare(attribute,"icm") == 0)
5125             {
5126               if (image != (Image *) NULL)
5127                 {
5128                   const StringInfo
5129                     *profile;
5130
5131                   profile=GetImageProfile(image,"icm");
5132                   if (profile != (const StringInfo *) NULL)
5133                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5134                       GetStringInfoLength(profile));
5135                 }
5136               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5137               continue;
5138             }
5139           if (LocaleCompare(attribute,"id") == 0)
5140             {
5141               if (image != (Image *) NULL)
5142                 {
5143                   char
5144                     key[MagickPathExtent];
5145
5146                   MagickBooleanType
5147                     status;
5148
5149                   static ssize_t
5150                     id = 0;
5151
5152                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5153                     id);
5154                   status=SetImageRegistry(ImageRegistryType,key,image,
5155                     exception);
5156                   (void) status;
5157                   s=newSViv(id++);
5158                 }
5159               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160               continue;
5161             }
5162           if (LocaleNCompare(attribute,"index",5) == 0)
5163             {
5164               char
5165                 name[MagickPathExtent];
5166
5167               int
5168                 items;
5169
5170               long
5171                 x,
5172                 y;
5173
5174               register const Quantum
5175                 *p;
5176
5177               CacheView
5178                 *image_view;
5179
5180               if (image == (Image *) NULL)
5181                 break;
5182               if (image->storage_class != PseudoClass)
5183                 break;
5184               x=0;
5185               y=0;
5186               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5187               (void) items;
5188               image_view=AcquireVirtualCacheView(image,exception);
5189               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5190               if (p != (const Quantum *) NULL)
5191                 {
5192                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5193                     GetPixelIndex(image,p));
5194                   s=newSVpv(name,0);
5195                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5196                 }
5197               image_view=DestroyCacheView(image_view);
5198               continue;
5199             }
5200           if (LocaleCompare(attribute,"iptc") == 0)
5201             {
5202               if (image != (Image *) NULL)
5203                 {
5204                   const StringInfo
5205                     *profile;
5206
5207                   profile=GetImageProfile(image,"iptc");
5208                   if (profile != (const StringInfo *) NULL)
5209                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5210                       GetStringInfoLength(profile));
5211                 }
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5216             {
5217               if (image != (Image *) NULL)
5218                 s=newSViv((ssize_t) image->iterations);
5219               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220               continue;
5221             }
5222           if (LocaleCompare(attribute,"interlace") == 0)
5223             {
5224               j=info ? info->image_info->interlace : image ? image->interlace :
5225                 UndefinedInterlace;
5226               s=newSViv(j);
5227               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5228                 j));
5229               SvIOK_on(s);
5230               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5231               continue;
5232             }
5233           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5234             attribute);
5235           break;
5236         }
5237         case 'L':
5238         case 'l':
5239         {
5240           if (LocaleCompare(attribute,"label") == 0)
5241             {
5242               const char
5243                 *value;
5244
5245               if (image == (Image *) NULL)
5246                 break;
5247               value=GetImageProperty(image,"Label",exception);
5248               if (value != (const char *) NULL)
5249                 s=newSVpv(value,0);
5250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5251               continue;
5252             }
5253           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5254             {
5255               if (image != (Image *) NULL)
5256                 s=newSViv((ssize_t) image->iterations);
5257               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5258               continue;
5259             }
5260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5261             attribute);
5262           break;
5263         }
5264         case 'M':
5265         case 'm':
5266         {
5267           if (LocaleCompare(attribute,"magick") == 0)
5268             {
5269               if (info && *info->image_info->magick)
5270                 s=newSVpv(info->image_info->magick,0);
5271               if (image != (Image *) NULL)
5272                 s=newSVpv(image->magick,0);
5273               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5274               continue;
5275             }
5276           if (LocaleCompare(attribute,"map") == 0)
5277             {
5278               s=newSViv(GetMagickResource(MapResource));
5279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5280               continue;
5281             }
5282           if (LocaleCompare(attribute,"maximum-error") == 0)
5283             {
5284               if (image != (Image *) NULL)
5285                 s=newSVnv(image->error.normalized_maximum_error);
5286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5287               continue;
5288             }
5289           if (LocaleCompare(attribute,"memory") == 0)
5290             {
5291               s=newSViv(GetMagickResource(MemoryResource));
5292               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5293               continue;
5294             }
5295           if (LocaleCompare(attribute,"mean-error") == 0)
5296             {
5297               if (image != (Image *) NULL)
5298                 s=newSVnv(image->error.normalized_mean_error);
5299               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5300               continue;
5301             }
5302           if (LocaleCompare(attribute,"mime") == 0)
5303             {
5304               if (info && *info->image_info->magick)
5305                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5306               if (image != (Image *) NULL)
5307                 s=newSVpv(MagickToMime(image->magick),0);
5308               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5309               continue;
5310             }
5311           if (LocaleCompare(attribute,"mattecolor") == 0)
5312             {
5313               if (image == (Image *) NULL)
5314                 break;
5315               (void) FormatLocaleString(color,MagickPathExtent,
5316                 "%.20g,%.20g,%.20g,%.20g",(double) image->matte_color.red,
5317                 (double) image->matte_color.green,
5318                 (double) image->matte_color.blue,
5319                 (double) image->matte_color.alpha);
5320               s=newSVpv(color,0);
5321               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5322               continue;
5323             }
5324           if (LocaleCompare(attribute,"matte") == 0)
5325             {
5326               if (image != (Image *) NULL)
5327                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5328                   1 : 0);
5329               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5330               continue;
5331             }
5332           if (LocaleCompare(attribute,"mime") == 0)
5333             {
5334               const char
5335                 *magick;
5336
5337               magick=NULL;
5338               if (info && *info->image_info->magick)
5339                 magick=info->image_info->magick;
5340               if (image != (Image *) NULL)
5341                 magick=image->magick;
5342               if (magick)
5343                 {
5344                   char
5345                     *mime;
5346
5347                   mime=MagickToMime(magick);
5348                   s=newSVpv(mime,0);
5349                   mime=(char *) RelinquishMagickMemory(mime);
5350                 }
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           if (LocaleCompare(attribute,"monochrome") == 0)
5355             {
5356               if (image == (Image *) NULL)
5357                 continue;
5358               j=info ? info->image_info->monochrome :
5359                 SetImageMonochrome(image,exception);
5360               s=newSViv(j);
5361               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5362               continue;
5363             }
5364           if (LocaleCompare(attribute,"montage") == 0)
5365             {
5366               if (image && image->montage)
5367                 s=newSVpv(image->montage,0);
5368               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5369               continue;
5370             }
5371           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5372             attribute);
5373           break;
5374         }
5375         case 'O':
5376         case 'o':
5377         {
5378           if (LocaleCompare(attribute,"orientation") == 0)
5379             {
5380               j=info ? info->image_info->orientation : image ?
5381                 image->orientation : UndefinedOrientation;
5382               s=newSViv(j);
5383               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5384                 j));
5385               SvIOK_on(s);
5386               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5387               continue;
5388             }
5389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5390             attribute);
5391           break;
5392         }
5393         case 'P':
5394         case 'p':
5395         {
5396           if (LocaleCompare(attribute,"page") == 0)
5397             {
5398               if (info && info->image_info->page)
5399                 s=newSVpv(info->image_info->page,0);
5400               if (image != (Image *) NULL)
5401                 {
5402                   char
5403                     geometry[MagickPathExtent];
5404
5405                   (void) FormatLocaleString(geometry,MagickPathExtent,
5406                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5407                     (double) image->page.height,(double) image->page.x,(double)
5408                     image->page.y);
5409                   s=newSVpv(geometry,0);
5410                 }
5411               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5412               continue;
5413             }
5414           if (LocaleCompare(attribute,"page.x") == 0)
5415             {
5416               if (image != (Image *) NULL)
5417                 s=newSViv((ssize_t) image->page.x);
5418               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5419               continue;
5420             }
5421           if (LocaleCompare(attribute,"page.y") == 0)
5422             {
5423               if (image != (Image *) NULL)
5424                 s=newSViv((ssize_t) image->page.y);
5425               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5426               continue;
5427             }
5428           if (LocaleNCompare(attribute,"pixel",5) == 0)
5429             {
5430               char
5431                 tuple[MagickPathExtent];
5432
5433               int
5434                 items;
5435
5436               long
5437                 x,
5438                 y;
5439
5440               register const Quantum
5441                 *p;
5442
5443               if (image == (Image *) NULL)
5444                 break;
5445               x=0;
5446               y=0;
5447               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5448               (void) items;
5449               p=GetVirtualPixels(image,x,y,1,1,exception);
5450               if (image->colorspace != CMYKColorspace)
5451                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5452                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5453                   GetPixelRed(image,p),GetPixelGreen(image,p),
5454                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5455               else
5456                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5457                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5458                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5459                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5460                   GetPixelAlpha(image,p));
5461               s=newSVpv(tuple,0);
5462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5463               continue;
5464             }
5465           if (LocaleCompare(attribute,"pointsize") == 0)
5466             {
5467               if (info)
5468                 s=newSViv((ssize_t) info->image_info->pointsize);
5469               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5470               continue;
5471             }
5472           if (LocaleCompare(attribute,"preview") == 0)
5473             {
5474               s=newSViv(info->image_info->preview_type);
5475               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5476                 info->image_info->preview_type));
5477               SvIOK_on(s);
5478               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5479               continue;
5480             }
5481           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5482             attribute);
5483           break;
5484         }
5485         case 'Q':
5486         case 'q':
5487         {
5488           if (LocaleCompare(attribute,"quality") == 0)
5489             {
5490               if (info)
5491                 s=newSViv((ssize_t) info->image_info->quality);
5492               if (image != (Image *) NULL)
5493                 s=newSViv((ssize_t) image->quality);
5494               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5495               continue;
5496             }
5497           if (LocaleCompare(attribute,"quantum") == 0)
5498             {
5499               if (info)
5500                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5501               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5502               continue;
5503             }
5504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5505             attribute);
5506           break;
5507         }
5508         case 'R':
5509         case 'r':
5510         {
5511           if (LocaleCompare(attribute,"rendering-intent") == 0)
5512             {
5513               s=newSViv(image->rendering_intent);
5514               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5515                 image->rendering_intent));
5516               SvIOK_on(s);
5517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5518               continue;
5519             }
5520           if (LocaleCompare(attribute,"red-primary") == 0)
5521             {
5522               if (image == (Image *) NULL)
5523                 break;
5524               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5525                 image->chromaticity.red_primary.x,
5526                 image->chromaticity.red_primary.y);
5527               s=newSVpv(color,0);
5528               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5529               continue;
5530             }
5531           if (LocaleCompare(attribute,"rows") == 0)
5532             {
5533               if (image != (Image *) NULL)
5534                 s=newSViv((ssize_t) image->rows);
5535               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5536               continue;
5537             }
5538           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5539             attribute);
5540           break;
5541         }
5542         case 'S':
5543         case 's':
5544         {
5545           if (LocaleCompare(attribute,"sampling-factor") == 0)
5546             {
5547               if (info && info->image_info->sampling_factor)
5548                 s=newSVpv(info->image_info->sampling_factor,0);
5549               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5550               continue;
5551             }
5552           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5553             {
5554               if (info && info->image_info->server_name)
5555                 s=newSVpv(info->image_info->server_name,0);
5556               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5557               continue;
5558             }
5559           if (LocaleCompare(attribute,"size") == 0)
5560             {
5561               if (info && info->image_info->size)
5562                 s=newSVpv(info->image_info->size,0);
5563               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5564               continue;
5565             }
5566           if (LocaleCompare(attribute,"scene") == 0)
5567             {
5568               if (image != (Image *) NULL)
5569                 s=newSViv((ssize_t) image->scene);
5570               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5571               continue;
5572             }
5573           if (LocaleCompare(attribute,"scenes") == 0)
5574             {
5575               if (image != (Image *) NULL)
5576                 s=newSViv((ssize_t) info->image_info->number_scenes);
5577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5578               continue;
5579             }
5580           if (LocaleCompare(attribute,"signature") == 0)
5581             {
5582               const char
5583                 *value;
5584
5585               if (image == (Image *) NULL)
5586                 break;
5587               (void) SignatureImage(image,exception);
5588               value=GetImageProperty(image,"Signature",exception);
5589               if (value != (const char *) NULL)
5590                 s=newSVpv(value,0);
5591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5592               continue;
5593             }
5594           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5595             attribute);
5596           break;
5597         }
5598         case 'T':
5599         case 't':
5600         {
5601           if (LocaleCompare(attribute,"taint") == 0)
5602             {
5603               if (image != (Image *) NULL)
5604                 s=newSViv((ssize_t) IsTaintImage(image));
5605               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5606               continue;
5607             }
5608           if (LocaleCompare(attribute,"texture") == 0)
5609             {
5610               if (info && info->image_info->texture)
5611                 s=newSVpv(info->image_info->texture,0);
5612               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5613               continue;
5614             }
5615           if (LocaleCompare(attribute,"total-ink-density") == 0)
5616             {
5617               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5618               if (image != (Image *) NULL)
5619                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5621               continue;
5622             }
5623           if (LocaleCompare(attribute,"transparent-color") == 0)
5624             {
5625               if (image == (Image *) NULL)
5626                 break;
5627               (void) FormatLocaleString(color,MagickPathExtent,
5628                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5629                 (double) image->transparent_color.green,
5630                 (double) image->transparent_color.blue,
5631                 (double) image->transparent_color.alpha);
5632               s=newSVpv(color,0);
5633               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5634               continue;
5635             }
5636           if (LocaleCompare(attribute,"type") == 0)
5637             {
5638               if (image == (Image *) NULL)
5639                 break;
5640               j=(ssize_t) GetImageType(image,exception);
5641               s=newSViv(j);
5642               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5643               SvIOK_on(s);
5644               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5645               continue;
5646             }
5647           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5648             attribute);
5649           break;
5650         }
5651         case 'U':
5652         case 'u':
5653         {
5654           if (LocaleCompare(attribute,"units") == 0)
5655             {
5656               j=info ? info->image_info->units : image ? image->units :
5657                 UndefinedResolution;
5658               if (info && (info->image_info->units == UndefinedResolution))
5659                 if (image)
5660                   j=image->units;
5661               if (j == UndefinedResolution)
5662                 s=newSVpv("undefined units",0);
5663               else
5664                 if (j == PixelsPerInchResolution)
5665                   s=newSVpv("pixels / inch",0);
5666                 else
5667                   s=newSVpv("pixels / centimeter",0);
5668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5669               continue;
5670             }
5671           if (LocaleCompare(attribute,"user-time") == 0)
5672             {
5673               if (image != (Image *) NULL)
5674                 s=newSVnv(GetUserTime(&image->timer));
5675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5676               continue;
5677             }
5678           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5679             attribute);
5680           break;
5681         }
5682         case 'V':
5683         case 'v':
5684         {
5685           if (LocaleCompare(attribute,"verbose") == 0)
5686             {
5687               if (info)
5688                 s=newSViv((ssize_t) info->image_info->verbose);
5689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5690               continue;
5691             }
5692           if (LocaleCompare(attribute,"version") == 0)
5693             {
5694               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5695               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5696               continue;
5697             }
5698           if (LocaleCompare(attribute,"view") == 0)
5699             {
5700               if (info && info->image_info->view)
5701                 s=newSVpv(info->image_info->view,0);
5702               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5703               continue;
5704             }
5705           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5706             {
5707               if (image == (Image *) NULL)
5708                 break;
5709               j=(ssize_t) GetImageVirtualPixelMethod(image);
5710               s=newSViv(j);
5711               (void) sv_setpv(s,CommandOptionToMnemonic(
5712                 MagickVirtualPixelOptions,j));
5713               SvIOK_on(s);
5714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5715               continue;
5716             }
5717           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5718             attribute);
5719           break;
5720         }
5721         case 'W':
5722         case 'w':
5723         {
5724           if (LocaleCompare(attribute,"white-point") == 0)
5725             {
5726               if (image == (Image *) NULL)
5727                 break;
5728               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5729                 image->chromaticity.white_point.x,
5730                 image->chromaticity.white_point.y);
5731               s=newSVpv(color,0);
5732               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5733               continue;
5734             }
5735           if (LocaleCompare(attribute,"width") == 0)
5736             {
5737               if (image != (Image *) NULL)
5738                 s=newSViv((ssize_t) image->columns);
5739               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5740               continue;
5741             }
5742           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5743              attribute);
5744           break;
5745         }
5746         case 'X':
5747         case 'x':
5748         {
5749           if (LocaleCompare(attribute,"x-resolution") == 0)
5750             {
5751               if (image != (Image *) NULL)
5752                 s=newSVnv(image->resolution.x);
5753               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5754               continue;
5755             }
5756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5757             attribute);
5758           break;
5759         }
5760         case 'Y':
5761         case 'y':
5762         {
5763           if (LocaleCompare(attribute,"y-resolution") == 0)
5764             {
5765               if (image != (Image *) NULL)
5766                 s=newSVnv(image->resolution.y);
5767               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5768               continue;
5769             }
5770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5771             attribute);
5772           break;
5773         }
5774         default:
5775           break;
5776       }
5777       if (image == (Image *) NULL)
5778         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5779           attribute)
5780       else
5781         {
5782           value=GetImageProperty(image,attribute,exception);
5783           if (value != (const char *) NULL)
5784             {
5785               s=newSVpv(value,0);
5786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5787             }
5788           else
5789             if (*attribute != '%')
5790               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5791                 attribute)
5792             else
5793               {
5794                  char
5795                    *meta;
5796
5797                  meta=InterpretImageProperties(info ? info->image_info :
5798                    (ImageInfo *) NULL,image,attribute,exception);
5799                  s=newSVpv(meta,0);
5800                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5801                  meta=(char *) RelinquishMagickMemory(meta);
5802               }
5803         }
5804     }
5805     exception=DestroyExceptionInfo(exception);
5806     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5807   }
5808 \f
5809 #
5810 ###############################################################################
5811 #                                                                             #
5812 #                                                                             #
5813 #                                                                             #
5814 #   G e t A u t h e n t i c P i x e l s                                       #
5815 #                                                                             #
5816 #                                                                             #
5817 #                                                                             #
5818 ###############################################################################
5819 #
5820 #
5821 void *
5822 GetAuthenticPixels(ref,...)
5823   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5824   ALIAS:
5825     getauthenticpixels = 1
5826     GetImagePixels = 2
5827     getimagepixels = 3
5828   CODE:
5829   {
5830     char
5831       *attribute;
5832
5833     ExceptionInfo
5834       *exception;
5835
5836     Image
5837       *image;
5838
5839     RectangleInfo
5840       region;
5841
5842     ssize_t
5843       i;
5844
5845     struct PackageInfo
5846       *info;
5847
5848     SV
5849       *perl_exception,
5850       *reference;
5851
5852     void
5853       *blob = NULL;
5854
5855     PERL_UNUSED_VAR(ref);
5856     PERL_UNUSED_VAR(ix);
5857     exception=AcquireExceptionInfo();
5858     perl_exception=newSVpv("",0);
5859     if (sv_isobject(ST(0)) == 0)
5860       {
5861         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5862           PackageName);
5863         goto PerlException;
5864       }
5865     reference=SvRV(ST(0));
5866
5867     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5868     if (image == (Image *) NULL)
5869       {
5870         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5871           PackageName);
5872         goto PerlException;
5873       }
5874
5875     region.x=0;
5876     region.y=0;
5877     region.width=image->columns;
5878     region.height=1;
5879     if (items == 1)
5880       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5881     for (i=2; i < items; i+=2)
5882     {
5883       attribute=(char *) SvPV(ST(i-1),na);
5884       switch (*attribute)
5885       {
5886         case 'g':
5887         case 'G':
5888         {
5889           if (LocaleCompare(attribute,"geometry") == 0)
5890             {
5891               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5892               break;
5893             }
5894           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5895             attribute);
5896           break;
5897         }
5898         case 'H':
5899         case 'h':
5900         {
5901           if (LocaleCompare(attribute,"height") == 0)
5902             {
5903               region.height=SvIV(ST(i));
5904               continue;
5905             }
5906           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5907             attribute);
5908           break;
5909         }
5910         case 'X':
5911         case 'x':
5912         {
5913           if (LocaleCompare(attribute,"x") == 0)
5914             {
5915               region.x=SvIV(ST(i));
5916               continue;
5917             }
5918           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5919             attribute);
5920           break;
5921         }
5922         case 'Y':
5923         case 'y':
5924         {
5925           if (LocaleCompare(attribute,"y") == 0)
5926             {
5927               region.y=SvIV(ST(i));
5928               continue;
5929             }
5930           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5931             attribute);
5932           break;
5933         }
5934         case 'W':
5935         case 'w':
5936         {
5937           if (LocaleCompare(attribute,"width") == 0)
5938             {
5939               region.width=SvIV(ST(i));
5940               continue;
5941             }
5942           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5943             attribute);
5944           break;
5945         }
5946       }
5947     }
5948     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5949       region.height,exception);
5950     if (blob != (void *) NULL)
5951       goto PerlEnd;
5952
5953   PerlException:
5954     InheritPerlException(exception,perl_exception);
5955     exception=DestroyExceptionInfo(exception);
5956     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5957
5958   PerlEnd:
5959     RETVAL = blob;
5960   }
5961   OUTPUT:
5962     RETVAL
5963 \f
5964 #
5965 ###############################################################################
5966 #                                                                             #
5967 #                                                                             #
5968 #                                                                             #
5969 #   G e t V i r t u a l P i x e l s                                           #
5970 #                                                                             #
5971 #                                                                             #
5972 #                                                                             #
5973 ###############################################################################
5974 #
5975 #
5976 void *
5977 GetVirtualPixels(ref,...)
5978   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5979   ALIAS:
5980     getvirtualpixels = 1
5981     AcquireImagePixels = 2
5982     acquireimagepixels = 3
5983   CODE:
5984   {
5985     char
5986       *attribute;
5987
5988     const void
5989       *blob = NULL;
5990
5991     ExceptionInfo
5992       *exception;
5993
5994     Image
5995       *image;
5996
5997     RectangleInfo
5998       region;
5999
6000     ssize_t
6001       i;
6002
6003     struct PackageInfo
6004       *info;
6005
6006     SV
6007       *perl_exception,
6008       *reference;
6009
6010     PERL_UNUSED_VAR(ref);
6011     PERL_UNUSED_VAR(ix);
6012     exception=AcquireExceptionInfo();
6013     perl_exception=newSVpv("",0);
6014     if (sv_isobject(ST(0)) == 0)
6015       {
6016         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6017           PackageName);
6018         goto PerlException;
6019       }
6020     reference=SvRV(ST(0));
6021
6022     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6023     if (image == (Image *) NULL)
6024       {
6025         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6026           PackageName);
6027         goto PerlException;
6028       }
6029
6030     region.x=0;
6031     region.y=0;
6032     region.width=image->columns;
6033     region.height=1;
6034     if (items == 1)
6035       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6036     for (i=2; i < items; i+=2)
6037     {
6038       attribute=(char *) SvPV(ST(i-1),na);
6039       switch (*attribute)
6040       {
6041         case 'g':
6042         case 'G':
6043         {
6044           if (LocaleCompare(attribute,"geometry") == 0)
6045             {
6046               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6047               break;
6048             }
6049           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6050             attribute);
6051           break;
6052         }
6053         case 'H':
6054         case 'h':
6055         {
6056           if (LocaleCompare(attribute,"height") == 0)
6057             {
6058               region.height=SvIV(ST(i));
6059               continue;
6060             }
6061           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6062             attribute);
6063           break;
6064         }
6065         case 'X':
6066         case 'x':
6067         {
6068           if (LocaleCompare(attribute,"x") == 0)
6069             {
6070               region.x=SvIV(ST(i));
6071               continue;
6072             }
6073           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6074             attribute);
6075           break;
6076         }
6077         case 'Y':
6078         case 'y':
6079         {
6080           if (LocaleCompare(attribute,"y") == 0)
6081             {
6082               region.y=SvIV(ST(i));
6083               continue;
6084             }
6085           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6086             attribute);
6087           break;
6088         }
6089         case 'W':
6090         case 'w':
6091         {
6092           if (LocaleCompare(attribute,"width") == 0)
6093             {
6094               region.width=SvIV(ST(i));
6095               continue;
6096             }
6097           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6098             attribute);
6099           break;
6100         }
6101       }
6102     }
6103     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6104       region.height,exception);
6105     if (blob != (void *) NULL)
6106       goto PerlEnd;
6107
6108   PerlException:
6109     InheritPerlException(exception,perl_exception);
6110     exception=DestroyExceptionInfo(exception);
6111     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6112
6113   PerlEnd:
6114     RETVAL = (void *) blob;
6115   }
6116   OUTPUT:
6117     RETVAL
6118 \f
6119 #
6120 ###############################################################################
6121 #                                                                             #
6122 #                                                                             #
6123 #                                                                             #
6124 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6125 #                                                                             #
6126 #                                                                             #
6127 #                                                                             #
6128 ###############################################################################
6129 #
6130 #
6131 void *
6132 GetAuthenticMetacontent(ref,...)
6133   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6134   ALIAS:
6135     getauthenticmetacontent = 1
6136     GetMetacontent = 2
6137     getmetacontent = 3
6138   CODE:
6139   {
6140     ExceptionInfo
6141       *exception;
6142
6143     Image
6144       *image;
6145
6146     struct PackageInfo
6147       *info;
6148
6149     SV
6150       *perl_exception,
6151       *reference;
6152
6153     void
6154       *blob = NULL;
6155
6156     PERL_UNUSED_VAR(ref);
6157     PERL_UNUSED_VAR(ix);
6158     exception=AcquireExceptionInfo();
6159     perl_exception=newSVpv("",0);
6160     if (sv_isobject(ST(0)) == 0)
6161       {
6162         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6163           PackageName);
6164         goto PerlException;
6165       }
6166     reference=SvRV(ST(0));
6167
6168     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6169     if (image == (Image *) NULL)
6170       {
6171         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6172           PackageName);
6173         goto PerlException;
6174       }
6175
6176     blob=(void *) GetAuthenticMetacontent(image);
6177     if (blob != (void *) NULL)
6178       goto PerlEnd;
6179
6180   PerlException:
6181     InheritPerlException(exception,perl_exception);
6182     exception=DestroyExceptionInfo(exception);
6183     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6184
6185   PerlEnd:
6186     RETVAL = blob;
6187   }
6188   OUTPUT:
6189     RETVAL
6190 \f
6191 #
6192 ###############################################################################
6193 #                                                                             #
6194 #                                                                             #
6195 #                                                                             #
6196 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6197 #                                                                             #
6198 #                                                                             #
6199 #                                                                             #
6200 ###############################################################################
6201 #
6202 #
6203 void *
6204 GetVirtualMetacontent(ref,...)
6205   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6206   ALIAS:
6207     getvirtualmetacontent = 1
6208   CODE:
6209   {
6210     ExceptionInfo
6211       *exception;
6212
6213     Image
6214       *image;
6215
6216     struct PackageInfo
6217       *info;
6218
6219     SV
6220       *perl_exception,
6221       *reference;
6222
6223     void
6224       *blob = NULL;
6225
6226     PERL_UNUSED_VAR(ref);
6227     PERL_UNUSED_VAR(ix);
6228     exception=AcquireExceptionInfo();
6229     perl_exception=newSVpv("",0);
6230     if (sv_isobject(ST(0)) == 0)
6231       {
6232         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6233           PackageName);
6234         goto PerlException;
6235       }
6236     reference=SvRV(ST(0));
6237
6238     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6239     if (image == (Image *) NULL)
6240       {
6241         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6242           PackageName);
6243         goto PerlException;
6244       }
6245
6246     blob=(void *) GetVirtualMetacontent(image);
6247     if (blob != (void *) NULL)
6248       goto PerlEnd;
6249
6250   PerlException:
6251     InheritPerlException(exception,perl_exception);
6252     exception=DestroyExceptionInfo(exception);
6253     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6254
6255   PerlEnd:
6256     RETVAL = blob;
6257   }
6258   OUTPUT:
6259     RETVAL
6260 \f
6261 #
6262 ###############################################################################
6263 #                                                                             #
6264 #                                                                             #
6265 #                                                                             #
6266 #   H i s t o g r a m                                                         #
6267 #                                                                             #
6268 #                                                                             #
6269 #                                                                             #
6270 ###############################################################################
6271 #
6272 #
6273 void
6274 Histogram(ref,...)
6275   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6276   ALIAS:
6277     HistogramImage = 1
6278     histogram      = 2
6279     histogramimage = 3
6280   PPCODE:
6281   {
6282     AV
6283       *av;
6284
6285     char
6286       message[MagickPathExtent];
6287
6288     PixelInfo
6289       *histogram;
6290
6291     ExceptionInfo
6292       *exception;
6293
6294     Image
6295       *image;
6296
6297     register ssize_t
6298       i;
6299
6300     ssize_t
6301       count;
6302
6303     struct PackageInfo
6304       *info;
6305
6306     SV
6307       *perl_exception,
6308       *reference;
6309
6310     size_t
6311       number_colors;
6312
6313     PERL_UNUSED_VAR(ref);
6314     PERL_UNUSED_VAR(ix);
6315     exception=AcquireExceptionInfo();
6316     perl_exception=newSVpv("",0);
6317     av=NULL;
6318     if (sv_isobject(ST(0)) == 0)
6319       {
6320         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6321           PackageName);
6322         goto PerlException;
6323       }
6324     reference=SvRV(ST(0));
6325     av=newAV();
6326     SvREFCNT_dec(av);
6327     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6328     if (image == (Image *) NULL)
6329       {
6330         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6331           PackageName);
6332         goto PerlException;
6333       }
6334     count=0;
6335     for ( ; image; image=image->next)
6336     {
6337       histogram=GetImageHistogram(image,&number_colors,exception);
6338       if (histogram == (PixelInfo *) NULL)
6339         continue;
6340       count+=(ssize_t) number_colors;
6341       EXTEND(sp,6*count);
6342       for (i=0; i < (ssize_t) number_colors; i++)
6343       {
6344         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6345           histogram[i].red);
6346         PUSHs(sv_2mortal(newSVpv(message,0)));
6347         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6348           histogram[i].green);
6349         PUSHs(sv_2mortal(newSVpv(message,0)));
6350         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6351           histogram[i].blue);
6352         PUSHs(sv_2mortal(newSVpv(message,0)));
6353         if (image->colorspace == CMYKColorspace)
6354           {
6355             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6356               histogram[i].black);
6357             PUSHs(sv_2mortal(newSVpv(message,0)));
6358           }
6359         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6360           histogram[i].alpha);
6361         PUSHs(sv_2mortal(newSVpv(message,0)));
6362         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6363           histogram[i].count);
6364         PUSHs(sv_2mortal(newSVpv(message,0)));
6365       }
6366       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6367     }
6368
6369   PerlException:
6370     InheritPerlException(exception,perl_exception);
6371     exception=DestroyExceptionInfo(exception);
6372     SvREFCNT_dec(perl_exception);
6373   }
6374 \f
6375 #
6376 ###############################################################################
6377 #                                                                             #
6378 #                                                                             #
6379 #                                                                             #
6380 #   G e t P i x e l                                                           #
6381 #                                                                             #
6382 #                                                                             #
6383 #                                                                             #
6384 ###############################################################################
6385 #
6386 #
6387 void
6388 GetPixel(ref,...)
6389   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6390   ALIAS:
6391     getpixel = 1
6392     getPixel = 2
6393   PPCODE:
6394   {
6395     AV
6396       *av;
6397
6398     char
6399       *attribute;
6400
6401     ExceptionInfo
6402       *exception;
6403
6404     Image
6405       *image;
6406
6407     MagickBooleanType
6408       normalize;
6409
6410     RectangleInfo
6411       region;
6412
6413     register const Quantum
6414       *p;
6415
6416     register ssize_t
6417       i;
6418
6419     ssize_t
6420       option;
6421
6422     struct PackageInfo
6423       *info;
6424
6425     SV
6426       *perl_exception,
6427       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6428
6429     PERL_UNUSED_VAR(ref);
6430     PERL_UNUSED_VAR(ix);
6431     exception=AcquireExceptionInfo();
6432     perl_exception=newSVpv("",0);
6433     reference=SvRV(ST(0));
6434     av=(AV *) reference;
6435     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6436       exception);
6437     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6438     if (image == (Image *) NULL)
6439       {
6440         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6441           PackageName);
6442         goto PerlException;
6443       }
6444     normalize=MagickTrue;
6445     region.x=0;
6446     region.y=0;
6447     region.width=image->columns;
6448     region.height=1;
6449     if (items == 1)
6450       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6451     for (i=2; i < items; i+=2)
6452     {
6453       attribute=(char *) SvPV(ST(i-1),na);
6454       switch (*attribute)
6455       {
6456         case 'C':
6457         case 'c':
6458         {
6459           if (LocaleCompare(attribute,"channel") == 0)
6460             {
6461               ssize_t
6462                 option;
6463
6464               option=ParseChannelOption(SvPV(ST(i),na));
6465               if (option < 0)
6466                 {
6467                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6468                     SvPV(ST(i),na));
6469                   return;
6470                 }
6471               (void) SetPixelChannelMask(image,(ChannelType) option);
6472               break;
6473             }
6474           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6475             attribute);
6476           break;
6477         }
6478         case 'g':
6479         case 'G':
6480         {
6481           if (LocaleCompare(attribute,"geometry") == 0)
6482             {
6483               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6484               break;
6485             }
6486           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6487             attribute);
6488           break;
6489         }
6490         case 'N':
6491         case 'n':
6492         {
6493           if (LocaleCompare(attribute,"normalize") == 0)
6494             {
6495               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6496                 SvPV(ST(i),na));
6497               if (option < 0)
6498                 {
6499                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6500                     SvPV(ST(i),na));
6501                   break;
6502                 }
6503              normalize=option != 0 ? MagickTrue : MagickFalse;
6504              break;
6505             }
6506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6507             attribute);
6508           break;
6509         }
6510         case 'x':
6511         case 'X':
6512         {
6513           if (LocaleCompare(attribute,"x") == 0)
6514             {
6515               region.x=SvIV(ST(i));
6516               break;
6517             }
6518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6519             attribute);
6520           break;
6521         }
6522         case 'y':
6523         case 'Y':
6524         {
6525           if (LocaleCompare(attribute,"y") == 0)
6526             {
6527               region.y=SvIV(ST(i));
6528               break;
6529             }
6530           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6531             attribute);
6532           break;
6533         }
6534         default:
6535         {
6536           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6537             attribute);
6538           break;
6539         }
6540       }
6541     }
6542     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6543     if (p == (const Quantum *) NULL)
6544       PUSHs(&sv_undef);
6545     else
6546       {
6547         double
6548           scale;
6549
6550         scale=1.0;
6551         if (normalize != MagickFalse)
6552           scale=1.0/QuantumRange;
6553         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6554           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6555         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6556           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6557         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6558           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6559         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6560             (image->colorspace == CMYKColorspace))
6561           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6562         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6563           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6564       }
6565
6566   PerlException:
6567     InheritPerlException(exception,perl_exception);
6568     exception=DestroyExceptionInfo(exception);
6569     SvREFCNT_dec(perl_exception);
6570   }
6571 \f
6572 #
6573 ###############################################################################
6574 #                                                                             #
6575 #                                                                             #
6576 #                                                                             #
6577 #   G e t P i x e l s                                                         #
6578 #                                                                             #
6579 #                                                                             #
6580 #                                                                             #
6581 ###############################################################################
6582 #
6583 #
6584 void
6585 GetPixels(ref,...)
6586   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6587   ALIAS:
6588     getpixels = 1
6589     getPixels = 2
6590   PPCODE:
6591   {
6592     AV
6593       *av;
6594
6595     char
6596       *attribute;
6597
6598     const char
6599       *map;
6600
6601     ExceptionInfo
6602       *exception;
6603
6604     Image
6605       *image;
6606
6607     MagickBooleanType
6608       normalize,
6609       status;
6610
6611     RectangleInfo
6612       region;
6613
6614     register ssize_t
6615       i;
6616
6617     ssize_t
6618       option;
6619
6620     struct PackageInfo
6621       *info;
6622
6623     SV
6624       *perl_exception,
6625       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6626
6627     PERL_UNUSED_VAR(ref);
6628     PERL_UNUSED_VAR(ix);
6629     exception=AcquireExceptionInfo();
6630     perl_exception=newSVpv("",0);
6631     reference=SvRV(ST(0));
6632     av=(AV *) reference;
6633     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6634       exception);
6635     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6636     if (image == (Image *) NULL)
6637       {
6638         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6639           PackageName);
6640         goto PerlException;
6641       }
6642     map="RGB";
6643     if (image->alpha_trait != UndefinedPixelTrait)
6644       map="RGBA";
6645     if (image->colorspace == CMYKColorspace)
6646       {
6647         map="CMYK";
6648         if (image->alpha_trait != UndefinedPixelTrait)
6649           map="CMYKA";
6650       }
6651     normalize=MagickFalse;
6652     region.x=0;
6653     region.y=0;
6654     region.width=image->columns;
6655     region.height=1;
6656     if (items == 1)
6657       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6658     for (i=2; i < items; i+=2)
6659     {
6660       attribute=(char *) SvPV(ST(i-1),na);
6661       switch (*attribute)
6662       {
6663         case 'g':
6664         case 'G':
6665         {
6666           if (LocaleCompare(attribute,"geometry") == 0)
6667             {
6668               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6669               break;
6670             }
6671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6672             attribute);
6673           break;
6674         }
6675         case 'H':
6676         case 'h':
6677         {
6678           if (LocaleCompare(attribute,"height") == 0)
6679             {
6680               region.height=SvIV(ST(i));
6681               break;
6682             }
6683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6684             attribute);
6685           break;
6686         }
6687         case 'M':
6688         case 'm':
6689         {
6690           if (LocaleCompare(attribute,"map") == 0)
6691             {
6692               map=SvPV(ST(i),na);
6693               break;
6694             }
6695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6696             attribute);
6697           break;
6698         }
6699         case 'N':
6700         case 'n':
6701         {
6702           if (LocaleCompare(attribute,"normalize") == 0)
6703             {
6704               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6705                 SvPV(ST(i),na));
6706               if (option < 0)
6707                 {
6708                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6709                     SvPV(ST(i),na));
6710                   break;
6711                 }
6712              normalize=option != 0 ? MagickTrue : MagickFalse;
6713              break;
6714             }
6715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6716             attribute);
6717           break;
6718         }
6719         case 'W':
6720         case 'w':
6721         {
6722           if (LocaleCompare(attribute,"width") == 0)
6723             {
6724               region.width=SvIV(ST(i));
6725               break;
6726             }
6727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6728             attribute);
6729           break;
6730         }
6731         case 'x':
6732         case 'X':
6733         {
6734           if (LocaleCompare(attribute,"x") == 0)
6735             {
6736               region.x=SvIV(ST(i));
6737               break;
6738             }
6739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6740             attribute);
6741           break;
6742         }
6743         case 'y':
6744         case 'Y':
6745         {
6746           if (LocaleCompare(attribute,"y") == 0)
6747             {
6748               region.y=SvIV(ST(i));
6749               break;
6750             }
6751           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6752             attribute);
6753           break;
6754         }
6755         default:
6756         {
6757           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6758             attribute);
6759           break;
6760         }
6761       }
6762     }
6763     if (normalize != MagickFalse)
6764       {
6765         float
6766           *pixels;
6767
6768         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6769           region.height*sizeof(*pixels));
6770         if (pixels == (float *) NULL)
6771           {
6772             ThrowPerlException(exception,ResourceLimitError,
6773               "MemoryAllocationFailed",PackageName);
6774             goto PerlException;
6775           }
6776         status=ExportImagePixels(image,region.x,region.y,region.width,
6777           region.height,map,FloatPixel,pixels,exception);
6778         if (status == MagickFalse)
6779           PUSHs(&sv_undef);
6780         else
6781           {
6782             EXTEND(sp,strlen(map)*region.width*region.height);
6783             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6784               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6785           }
6786         pixels=(float *) RelinquishMagickMemory(pixels);
6787       }
6788     else
6789       {
6790         Quantum
6791           *pixels;
6792
6793         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6794           region.height*sizeof(*pixels));
6795         if (pixels == (Quantum *) NULL)
6796           {
6797             ThrowPerlException(exception,ResourceLimitError,
6798               "MemoryAllocationFailed",PackageName);
6799             goto PerlException;
6800           }
6801         status=ExportImagePixels(image,region.x,region.y,region.width,
6802           region.height,map,QuantumPixel,pixels,exception);
6803         if (status == MagickFalse)
6804           PUSHs(&sv_undef);
6805         else
6806           {
6807             EXTEND(sp,strlen(map)*region.width*region.height);
6808             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6809               PUSHs(sv_2mortal(newSViv(pixels[i])));
6810           }
6811         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6812       }
6813
6814   PerlException:
6815     InheritPerlException(exception,perl_exception);
6816     exception=DestroyExceptionInfo(exception);
6817     SvREFCNT_dec(perl_exception);
6818   }
6819 \f
6820 #
6821 ###############################################################################
6822 #                                                                             #
6823 #                                                                             #
6824 #                                                                             #
6825 #   I m a g e T o B l o b                                                     #
6826 #                                                                             #
6827 #                                                                             #
6828 #                                                                             #
6829 ###############################################################################
6830 #
6831 #
6832 void
6833 ImageToBlob(ref,...)
6834   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6835   ALIAS:
6836     ImageToBlob  = 1
6837     imagetoblob  = 2
6838     toblob       = 3
6839     blob         = 4
6840   PPCODE:
6841   {
6842     char
6843       filename[MagickPathExtent];
6844
6845     ExceptionInfo
6846       *exception;
6847
6848     Image
6849       *image,
6850       *next;
6851
6852     register ssize_t
6853       i;
6854
6855     struct PackageInfo
6856       *info,
6857       *package_info;
6858
6859     size_t
6860       length;
6861
6862     ssize_t
6863       scene;
6864
6865     SV
6866       *perl_exception,
6867       *reference;
6868
6869     void
6870       *blob;
6871
6872     PERL_UNUSED_VAR(ref);
6873     PERL_UNUSED_VAR(ix);
6874     exception=AcquireExceptionInfo();
6875     perl_exception=newSVpv("",0);
6876     package_info=(struct PackageInfo *) NULL;
6877     if (sv_isobject(ST(0)) == 0)
6878       {
6879         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6880           PackageName);
6881         goto PerlException;
6882       }
6883     reference=SvRV(ST(0));
6884     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6885     if (image == (Image *) NULL)
6886       {
6887         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6888           PackageName);
6889         goto PerlException;
6890       }
6891     package_info=ClonePackageInfo(info,exception);
6892     for (i=2; i < items; i+=2)
6893       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6894     (void) CopyMagickString(filename,package_info->image_info->filename,
6895       MagickPathExtent);
6896     scene=0;
6897     for (next=image; next; next=next->next)
6898     {
6899       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6900       next->scene=scene++;
6901     }
6902     SetImageInfo(package_info->image_info,(unsigned int)
6903       GetImageListLength(image),exception);
6904     EXTEND(sp,(ssize_t) GetImageListLength(image));
6905     for ( ; image; image=image->next)
6906     {
6907       length=0;
6908       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6909       if (blob != (char *) NULL)
6910         {
6911           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6912           blob=(unsigned char *) RelinquishMagickMemory(blob);
6913         }
6914       if (package_info->image_info->adjoin)
6915         break;
6916     }
6917
6918   PerlException:
6919     if (package_info != (struct PackageInfo *) NULL)
6920       DestroyPackageInfo(package_info);
6921     InheritPerlException(exception,perl_exception);
6922     exception=DestroyExceptionInfo(exception);
6923     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6924   }
6925 \f
6926 #
6927 ###############################################################################
6928 #                                                                             #
6929 #                                                                             #
6930 #                                                                             #
6931 #   L a y e r s                                                               #
6932 #                                                                             #
6933 #                                                                             #
6934 #                                                                             #
6935 ###############################################################################
6936 #
6937 #
6938 void
6939 Layers(ref,...)
6940   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6941   ALIAS:
6942     Layers                = 1
6943     layers           = 2
6944     OptimizeImageLayers   = 3
6945     optimizelayers        = 4
6946     optimizeimagelayers   = 5
6947   PPCODE:
6948   {
6949     AV
6950       *av;
6951
6952     char
6953       *attribute;
6954
6955     CompositeOperator
6956       compose;
6957
6958     ExceptionInfo
6959       *exception;
6960
6961     HV
6962       *hv;
6963
6964     Image
6965       *image,
6966       *layers;
6967
6968     LayerMethod
6969       method;
6970
6971     register ssize_t
6972       i;
6973
6974     ssize_t
6975       option,
6976       sp;
6977
6978     struct PackageInfo
6979       *info;
6980
6981     SV
6982       *av_reference,
6983       *perl_exception,
6984       *reference,
6985       *rv,
6986       *sv;
6987
6988     PERL_UNUSED_VAR(ref);
6989     PERL_UNUSED_VAR(ix);
6990     exception=AcquireExceptionInfo();
6991     perl_exception=newSVpv("",0);
6992     sv=NULL;
6993     if (sv_isobject(ST(0)) == 0)
6994       {
6995         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6996           PackageName);
6997         goto PerlException;
6998       }
6999     reference=SvRV(ST(0));
7000     hv=SvSTASH(reference);
7001     av=newAV();
7002     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7003     SvREFCNT_dec(av);
7004     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7005     if (image == (Image *) NULL)
7006       {
7007         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7008           PackageName);
7009         goto PerlException;
7010       }
7011     compose=image->compose;
7012     method=OptimizeLayer;
7013     for (i=2; i < items; i+=2)
7014     {
7015       attribute=(char *) SvPV(ST(i-1),na);
7016       switch (*attribute)
7017       {
7018         case 'C':
7019         case 'c':
7020         {
7021           if (LocaleCompare(attribute,"compose") == 0)
7022             {
7023               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7024                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7025               if (sp < 0)
7026                 {
7027                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7028                     SvPV(ST(i),na));
7029                   break;
7030                 }
7031               compose=(CompositeOperator) sp;
7032               break;
7033             }
7034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7035             attribute);
7036           break;
7037         }
7038         case 'M':
7039         case 'm':
7040         {
7041           if (LocaleCompare(attribute,"method") == 0)
7042             {
7043               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7044                 SvPV(ST(i),na));
7045               if (option < 0)
7046                 {
7047                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7048                     SvPV(ST(i),na));
7049                   break;
7050                 }
7051               method=(LayerMethod) option;
7052               break;
7053             }
7054           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7055             attribute);
7056           break;
7057         }
7058         default:
7059         {
7060           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7061             attribute);
7062           break;
7063         }
7064       }
7065     }
7066     layers=(Image *) NULL;
7067     switch (method)
7068     {
7069       case CompareAnyLayer:
7070       case CompareClearLayer:
7071       case CompareOverlayLayer:
7072       default:
7073       {
7074         layers=CompareImagesLayers(image,method,exception);
7075         break;
7076       }
7077       case MergeLayer:
7078       case FlattenLayer:
7079       case MosaicLayer:
7080       {
7081         layers=MergeImageLayers(image,method,exception);
7082         break;
7083       }
7084       case DisposeLayer:
7085       {
7086         layers=DisposeImages(image,exception);
7087         break;
7088       }
7089       case OptimizeImageLayer:
7090       {
7091         layers=OptimizeImageLayers(image,exception);
7092         break;
7093       }
7094       case OptimizePlusLayer:
7095       {
7096         layers=OptimizePlusImageLayers(image,exception);
7097         break;
7098       }
7099       case OptimizeTransLayer:
7100       {
7101         OptimizeImageTransparency(image,exception);
7102         break;
7103       }
7104       case RemoveDupsLayer:
7105       {
7106         RemoveDuplicateLayers(&image,exception);
7107         break;
7108       }
7109       case RemoveZeroLayer:
7110       {
7111         RemoveZeroDelayLayers(&image,exception);
7112         break;
7113       }
7114       case OptimizeLayer:
7115       {
7116         QuantizeInfo
7117           *quantize_info;
7118
7119         /*
7120           General Purpose, GIF Animation Optimizer.
7121         */
7122         layers=CoalesceImages(image,exception);
7123         if (layers == (Image *) NULL)
7124           break;
7125         image=layers;
7126         layers=OptimizeImageLayers(image,exception);
7127         if (layers == (Image *) NULL)
7128           break;
7129         image=DestroyImageList(image);
7130         image=layers;
7131         layers=(Image *) NULL;
7132         OptimizeImageTransparency(image,exception);
7133         quantize_info=AcquireQuantizeInfo(info->image_info);
7134         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7135         quantize_info=DestroyQuantizeInfo(quantize_info);
7136         break;
7137       }
7138       case CompositeLayer:
7139       {
7140         Image
7141           *source;
7142
7143         RectangleInfo
7144           geometry;
7145
7146         /*
7147           Split image sequence at the first 'NULL:' image.
7148         */
7149         source=image;
7150         while (source != (Image *) NULL)
7151         {
7152           source=GetNextImageInList(source);
7153           if ((source != (Image *) NULL) &&
7154               (LocaleCompare(source->magick,"NULL") == 0))
7155             break;
7156         }
7157         if (source != (Image *) NULL)
7158           {
7159             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7160                 (GetNextImageInList(source) == (Image *) NULL))
7161               source=(Image *) NULL;
7162             else
7163               {
7164                 /*
7165                   Separate the two lists, junk the null: image.
7166                 */
7167                 source=SplitImageList(source->previous);
7168                 DeleteImageFromList(&source);
7169               }
7170           }
7171         if (source == (Image *) NULL)
7172           {
7173             (void) ThrowMagickException(exception,GetMagickModule(),
7174               OptionError,"MissingNullSeparator","layers Composite");
7175             break;
7176           }
7177         /*
7178           Adjust offset with gravity and virtual canvas.
7179         */
7180         SetGeometry(image,&geometry);
7181         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7182         geometry.width=source->page.width != 0 ? source->page.width :
7183           source->columns;
7184         geometry.height=source->page.height != 0 ? source->page.height :
7185           source->rows;
7186         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7187           image->columns,image->page.height != 0 ? image->page.height :
7188           image->rows,image->gravity,&geometry);
7189         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7190         source=DestroyImageList(source);
7191         break;
7192       }
7193     }
7194     if (layers != (Image *) NULL)
7195       image=layers;
7196     else
7197       image=CloneImage(image,0,0,MagickTrue,exception);
7198     if (image == (Image *) NULL)
7199       goto PerlException;
7200     for ( ; image; image=image->next)
7201     {
7202       AddImageToRegistry(sv,image);
7203       rv=newRV(sv);
7204       av_push(av,sv_bless(rv,hv));
7205       SvREFCNT_dec(sv);
7206     }
7207     exception=DestroyExceptionInfo(exception);
7208     ST(0)=av_reference;
7209     SvREFCNT_dec(perl_exception);
7210     XSRETURN(1);
7211
7212   PerlException:
7213     InheritPerlException(exception,perl_exception);
7214     exception=DestroyExceptionInfo(exception);
7215     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7216     SvPOK_on(perl_exception);
7217     ST(0)=sv_2mortal(perl_exception);
7218     XSRETURN(1);
7219   }
7220 \f
7221 #
7222 ###############################################################################
7223 #                                                                             #
7224 #                                                                             #
7225 #                                                                             #
7226 #   M a g i c k T o M i m e                                                   #
7227 #                                                                             #
7228 #                                                                             #
7229 #                                                                             #
7230 ###############################################################################
7231 #
7232 #
7233 SV *
7234 MagickToMime(ref,name)
7235   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7236   char *name
7237   ALIAS:
7238     magicktomime = 1
7239   CODE:
7240   {
7241     char
7242       *mime;
7243
7244     PERL_UNUSED_VAR(ref);
7245     PERL_UNUSED_VAR(ix);
7246     mime=MagickToMime(name);
7247     RETVAL=newSVpv(mime,0);
7248     mime=(char *) RelinquishMagickMemory(mime);
7249   }
7250   OUTPUT:
7251     RETVAL
7252 \f
7253 #
7254 ###############################################################################
7255 #                                                                             #
7256 #                                                                             #
7257 #                                                                             #
7258 #   M o g r i f y                                                             #
7259 #                                                                             #
7260 #                                                                             #
7261 #                                                                             #
7262 ###############################################################################
7263 #
7264 #
7265 void
7266 Mogrify(ref,...)
7267   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7268   ALIAS:
7269     Comment            =   1
7270     CommentImage       =   2
7271     Label              =   3
7272     LabelImage         =   4
7273     AddNoise           =   5
7274     AddNoiseImage      =   6
7275     Colorize           =   7
7276     ColorizeImage      =   8
7277     Border             =   9
7278     BorderImage        =  10
7279     Blur               =  11
7280     BlurImage          =  12
7281     Chop               =  13
7282     ChopImage          =  14
7283     Crop               =  15
7284     CropImage          =  16
7285     Despeckle          =  17
7286     DespeckleImage     =  18
7287     Edge               =  19
7288     EdgeImage          =  20
7289     Emboss             =  21
7290     EmbossImage        =  22
7291     Enhance            =  23
7292     EnhanceImage       =  24
7293     Flip               =  25
7294     FlipImage          =  26
7295     Flop               =  27
7296     FlopImage          =  28
7297     Frame              =  29
7298     FrameImage         =  30
7299     Implode            =  31
7300     ImplodeImage       =  32
7301     Magnify            =  33
7302     MagnifyImage       =  34
7303     MedianFilter       =  35
7304     MedianConvolveImage  =  36
7305     Minify             =  37
7306     MinifyImage        =  38
7307     OilPaint           =  39
7308     OilPaintImage      =  40
7309     ReduceNoise        =  41
7310     ReduceNoiseImage   =  42
7311     Roll               =  43
7312     RollImage          =  44
7313     Rotate             =  45
7314     RotateImage        =  46
7315     Sample             =  47
7316     SampleImage        =  48
7317     Scale              =  49
7318     ScaleImage         =  50
7319     Shade              =  51
7320     ShadeImage         =  52
7321     Sharpen            =  53
7322     SharpenImage       =  54
7323     Shear              =  55
7324     ShearImage         =  56
7325     Spread             =  57
7326     SpreadImage        =  58
7327     Swirl              =  59
7328     SwirlImage         =  60
7329     Resize             =  61
7330     ResizeImage        =  62
7331     Zoom               =  63
7332     ZoomImage          =  64
7333     Annotate           =  65
7334     AnnotateImage      =  66
7335     ColorFloodfill     =  67
7336     ColorFloodfillImage=  68
7337     Composite          =  69
7338     CompositeImage     =  70
7339     Contrast           =  71
7340     ContrastImage      =  72
7341     CycleColormap      =  73
7342     CycleColormapImage =  74
7343     Draw               =  75
7344     DrawImage          =  76
7345     Equalize           =  77
7346     EqualizeImage      =  78
7347     Gamma              =  79
7348     GammaImage         =  80
7349     Map                =  81
7350     MapImage           =  82
7351     MatteFloodfill     =  83
7352     MatteFloodfillImage=  84
7353     Modulate           =  85
7354     ModulateImage      =  86
7355     Negate             =  87
7356     NegateImage        =  88
7357     Normalize          =  89
7358     NormalizeImage     =  90
7359     NumberColors       =  91
7360     NumberColorsImage  =  92
7361     Opaque             =  93
7362     OpaqueImage        =  94
7363     Quantize           =  95
7364     QuantizeImage      =  96
7365     Raise              =  97
7366     RaiseImage         =  98
7367     Segment            =  99
7368     SegmentImage       = 100
7369     Signature          = 101
7370     SignatureImage     = 102
7371     Solarize           = 103
7372     SolarizeImage      = 104
7373     Sync               = 105
7374     SyncImage          = 106
7375     Texture            = 107
7376     TextureImage       = 108
7377     Evaluate           = 109
7378     EvaluateImage      = 110
7379     Transparent        = 111
7380     TransparentImage   = 112
7381     Threshold          = 113
7382     ThresholdImage     = 114
7383     Charcoal           = 115
7384     CharcoalImage      = 116
7385     Trim               = 117
7386     TrimImage          = 118
7387     Wave               = 119
7388     WaveImage          = 120
7389     Separate           = 121
7390     SeparateImage      = 122
7391     Stereo             = 125
7392     StereoImage        = 126
7393     Stegano            = 127
7394     SteganoImage       = 128
7395     Deconstruct        = 129
7396     DeconstructImage   = 130
7397     GaussianBlur       = 131
7398     GaussianBlurImage  = 132
7399     Convolve           = 133
7400     ConvolveImage      = 134
7401     Profile            = 135
7402     ProfileImage       = 136
7403     UnsharpMask        = 137
7404     UnsharpMaskImage   = 138
7405     MotionBlur         = 139
7406     MotionBlurImage    = 140
7407     OrderedDither      = 141
7408     OrderedDitherImage = 142
7409     Shave              = 143
7410     ShaveImage         = 144
7411     Level              = 145
7412     LevelImage         = 146
7413     Clip               = 147
7414     ClipImage          = 148
7415     AffineTransform    = 149
7416     AffineTransformImage = 150
7417     Difference         = 151
7418     DifferenceImage    = 152
7419     AdaptiveThreshold  = 153
7420     AdaptiveThresholdImage = 154
7421     Resample           = 155
7422     ResampleImage      = 156
7423     Describe           = 157
7424     DescribeImage      = 158
7425     BlackThreshold     = 159
7426     BlackThresholdImage= 160
7427     WhiteThreshold     = 161
7428     WhiteThresholdImage= 162
7429     RotationalBlur     = 163
7430     RotationalBlurImage= 164
7431     Thumbnail          = 165
7432     ThumbnailImage     = 166
7433     Strip              = 167
7434     StripImage         = 168
7435     Tint               = 169
7436     TintImage          = 170
7437     Channel            = 171
7438     ChannelImage       = 172
7439     Splice             = 173
7440     SpliceImage        = 174
7441     Posterize          = 175
7442     PosterizeImage     = 176
7443     Shadow             = 177
7444     ShadowImage        = 178
7445     Identify           = 179
7446     IdentifyImage      = 180
7447     SepiaTone          = 181
7448     SepiaToneImage     = 182
7449     SigmoidalContrast  = 183
7450     SigmoidalContrastImage = 184
7451     Extent             = 185
7452     ExtentImage        = 186
7453     Vignette           = 187
7454     VignetteImage      = 188
7455     ContrastStretch    = 189
7456     ContrastStretchImage = 190
7457     Sans0              = 191
7458     Sans0Image         = 192
7459     Sans1              = 193
7460     Sans1Image         = 194
7461     AdaptiveSharpen    = 195
7462     AdaptiveSharpenImage = 196
7463     Transpose          = 197
7464     TransposeImage     = 198
7465     Transverse         = 199
7466     TransverseImage    = 200
7467     AutoOrient         = 201
7468     AutoOrientImage    = 202
7469     AdaptiveBlur       = 203
7470     AdaptiveBlurImage  = 204
7471     Sketch             = 205
7472     SketchImage        = 206
7473     UniqueColors       = 207
7474     UniqueColorsImage  = 208
7475     AdaptiveResize     = 209
7476     AdaptiveResizeImage= 210
7477     ClipMask           = 211
7478     ClipMaskImage      = 212
7479     LinearStretch      = 213
7480     LinearStretchImage = 214
7481     ColorMatrix        = 215
7482     ColorMatrixImage   = 216
7483     Mask               = 217
7484     MaskImage          = 218
7485     Polaroid           = 219
7486     PolaroidImage      = 220
7487     FloodfillPaint     = 221
7488     FloodfillPaintImage= 222
7489     Distort            = 223
7490     DistortImage       = 224
7491     Clut               = 225
7492     ClutImage          = 226
7493     LiquidRescale      = 227
7494     LiquidRescaleImage = 228
7495     Encipher           = 229
7496     EncipherImage      = 230
7497     Decipher           = 231
7498     DecipherImage      = 232
7499     Deskew             = 233
7500     DeskewImage        = 234
7501     Remap              = 235
7502     RemapImage         = 236
7503     SparseColor        = 237
7504     SparseColorImage   = 238
7505     Function           = 239
7506     FunctionImage      = 240
7507     SelectiveBlur      = 241
7508     SelectiveBlurImage = 242
7509     HaldClut           = 243
7510     HaldClutImage      = 244
7511     BlueShift          = 245
7512     BlueShiftImage     = 246
7513     ForwardFourierTransform  = 247
7514     ForwardFourierTransformImage = 248
7515     InverseFourierTransform = 249
7516     InverseFourierTransformImage = 250
7517     ColorDecisionList  = 251
7518     ColorDecisionListImage = 252
7519     AutoGamma          = 253
7520     AutoGammaImage     = 254
7521     AutoLevel          = 255
7522     AutoLevelImage     = 256
7523     LevelColors        = 257
7524     LevelImageColors   = 258
7525     Clamp              = 259
7526     ClampImage         = 260
7527     BrightnessContrast = 261
7528     BrightnessContrastImage = 262
7529     Morphology         = 263
7530     MorphologyImage    = 264
7531     Color              = 265
7532     ColorImage         = 266
7533     Mode               = 267
7534     ModeImage          = 268
7535     Statistic          = 269
7536     StatisticImage     = 270
7537     Perceptible        = 271
7538     PerceptibleImage   = 272
7539     Poly               = 273
7540     PolyImage          = 274
7541     Grayscale          = 275
7542     GrayscaleImage     = 276
7543     CannyEdge          = 278
7544     CannyEdgeImage     = 279
7545     HoughLine          = 280
7546     HoughLineImage     = 281
7547     MeanShift          = 282
7548     MeanShiftImage     = 283
7549     Kuwahara           = 284
7550     KuwaharaImage      = 285
7551     ConnectedComponent = 286
7552     ConnectedComponentImage = 287
7553     MogrifyRegion      = 666
7554   PPCODE:
7555   {
7556     AffineMatrix
7557       affine,
7558       current;
7559
7560     char
7561       attribute_flag[MaxArguments],
7562       message[MagickPathExtent];
7563
7564     ChannelType
7565       channel,
7566       channel_mask;
7567
7568     CompositeOperator
7569       compose;
7570
7571     const char
7572       *attribute,
7573       *value;
7574
7575     double
7576       angle;
7577
7578     ExceptionInfo
7579       *exception;
7580
7581     GeometryInfo
7582       geometry_info;
7583
7584     Image
7585       *image,
7586       *next,
7587       *region_image;
7588
7589     MagickBooleanType
7590       status;
7591
7592     MagickStatusType
7593       flags;
7594
7595     PixelInfo
7596       fill_color;
7597
7598     RectangleInfo
7599       geometry,
7600       region_info;
7601
7602     register ssize_t
7603       i;
7604
7605     ssize_t
7606       base,
7607       j,
7608       number_images;
7609
7610     struct Methods
7611       *rp;
7612
7613     struct PackageInfo
7614       *info;
7615
7616     SV
7617       *perl_exception,
7618       **pv,
7619       *reference,
7620       **reference_vector;
7621
7622     struct ArgumentList
7623       argument_list[MaxArguments];
7624
7625     PERL_UNUSED_VAR(ref);
7626     PERL_UNUSED_VAR(ix);
7627     exception=AcquireExceptionInfo();
7628     perl_exception=newSVpv("",0);
7629     reference_vector=NULL;
7630     region_image=NULL;
7631     number_images=0;
7632     base=2;
7633     if (sv_isobject(ST(0)) == 0)
7634       {
7635         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7636           PackageName);
7637         goto PerlException;
7638       }
7639     reference=SvRV(ST(0));
7640     region_info.width=0;
7641     region_info.height=0;
7642     region_info.x=0;
7643     region_info.y=0;
7644     region_image=(Image *) NULL;
7645     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7646     if (ix && (ix != 666))
7647       {
7648         /*
7649           Called as Method(...)
7650         */
7651         ix=(ix+1)/2;
7652         rp=(&Methods[ix-1]);
7653         attribute=rp->name;
7654       }
7655     else
7656       {
7657         /*
7658           Called as Mogrify("Method",...)
7659         */
7660         attribute=(char *) SvPV(ST(1),na);
7661         if (ix)
7662           {
7663             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7664             attribute=(char *) SvPV(ST(2),na);
7665             base++;
7666           }
7667         for (rp=Methods; ; rp++)
7668         {
7669           if (rp >= EndOf(Methods))
7670             {
7671               ThrowPerlException(exception,OptionError,
7672                 "UnrecognizedPerlMagickMethod",attribute);
7673               goto PerlException;
7674             }
7675           if (strEQcase(attribute,rp->name))
7676             break;
7677         }
7678         ix=rp-Methods+1;
7679         base++;
7680       }
7681     if (image == (Image *) NULL)
7682       {
7683         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7684         goto PerlException;
7685       }
7686     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7687     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7688     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7689     {
7690       Arguments
7691         *pp,
7692         *qq;
7693
7694       ssize_t
7695         ssize_test;
7696
7697       struct ArgumentList
7698         *al;
7699
7700       SV
7701         *sv;
7702
7703       sv=NULL;
7704       ssize_test=0;
7705       pp=(Arguments *) NULL;
7706       qq=rp->arguments;
7707       if (i == items)
7708         {
7709           pp=rp->arguments,
7710           sv=ST(i-1);
7711         }
7712       else
7713         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7714         {
7715           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7716             break;
7717           if (strEQcase(attribute,qq->method) > ssize_test)
7718             {
7719               pp=qq;
7720               ssize_test=strEQcase(attribute,qq->method);
7721             }
7722         }
7723       if (pp == (Arguments *) NULL)
7724         {
7725           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7726             attribute);
7727           goto continue_outer_loop;
7728         }
7729       al=(&argument_list[pp-rp->arguments]);
7730       switch (pp->type)
7731       {
7732         case ArrayReference:
7733         {
7734           if (SvTYPE(sv) != SVt_RV)
7735             {
7736               (void) FormatLocaleString(message,MagickPathExtent,
7737                 "invalid %.60s value",pp->method);
7738               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7739               goto continue_outer_loop;
7740             }
7741           al->array_reference=SvRV(sv);
7742           break;
7743         }
7744         case RealReference:
7745         {
7746           al->real_reference=SvNV(sv);
7747           break;
7748         }
7749         case FileReference:
7750         {
7751           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7752           break;
7753         }
7754         case ImageReference:
7755         {
7756           if (!sv_isobject(sv) ||
7757               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7758                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7759             {
7760               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7761                 PackageName);
7762               goto PerlException;
7763             }
7764           break;
7765         }
7766         case IntegerReference:
7767         {
7768           al->integer_reference=SvIV(sv);
7769           break;
7770         }
7771         case StringReference:
7772         {
7773           al->string_reference=(char *) SvPV(sv,al->length);
7774           if (sv_isobject(sv))
7775             al->image_reference=SetupList(aTHX_ SvRV(sv),
7776               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7777           break;
7778         }
7779         default:
7780         {
7781           /*
7782             Is a string; look up name.
7783           */
7784           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7785             {
7786               al->string_reference=(char *) SvPV(sv,al->length);
7787               al->integer_reference=(-1);
7788               break;
7789             }
7790           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7791             MagickFalse,SvPV(sv,na));
7792           if (pp->type == MagickChannelOptions)
7793             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7794           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7795             {
7796               (void) FormatLocaleString(message,MagickPathExtent,
7797                 "invalid %.60s value",pp->method);
7798               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7799               goto continue_outer_loop;
7800             }
7801           break;
7802         }
7803       }
7804       attribute_flag[pp-rp->arguments]++;
7805       continue_outer_loop: ;
7806     }
7807     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7808     pv=reference_vector;
7809     SetGeometryInfo(&geometry_info);
7810     channel=DefaultChannels;
7811     for (next=image; next; next=next->next)
7812     {
7813       image=next;
7814       SetGeometry(image,&geometry);
7815       if ((region_info.width*region_info.height) != 0)
7816         {
7817           region_image=image;
7818           image=CropImage(image,&region_info,exception);
7819         }
7820       switch (ix)
7821       {
7822         default:
7823         {
7824           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7825           ThrowPerlException(exception,OptionError,
7826             "UnrecognizedPerlMagickMethod",message);
7827           goto PerlException;
7828         }
7829         case 1:  /* Comment */
7830         {
7831           if (attribute_flag[0] == 0)
7832             argument_list[0].string_reference=(char *) NULL;
7833           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7834             info ? info->image_info : (ImageInfo *) NULL,image,
7835             argument_list[0].string_reference,exception),exception);
7836           break;
7837         }
7838         case 2:  /* Label */
7839         {
7840           if (attribute_flag[0] == 0)
7841             argument_list[0].string_reference=(char *) NULL;
7842           (void) SetImageProperty(image,"label",InterpretImageProperties(
7843             info ? info->image_info : (ImageInfo *) NULL,image,
7844             argument_list[0].string_reference,exception),exception);
7845           break;
7846         }
7847         case 3:  /* AddNoise */
7848         {
7849           double
7850             attenuate;
7851
7852           if (attribute_flag[0] == 0)
7853             argument_list[0].integer_reference=UniformNoise;
7854           attenuate=1.0;
7855           if (attribute_flag[1] != 0)
7856             attenuate=argument_list[1].real_reference;
7857           if (attribute_flag[2] != 0)
7858             channel=(ChannelType) argument_list[2].integer_reference;
7859           channel_mask=SetImageChannelMask(image,channel);
7860           image=AddNoiseImage(image,(NoiseType)
7861             argument_list[0].integer_reference,attenuate,exception);
7862           if (image != (Image *) NULL)
7863             (void) SetImageChannelMask(image,channel_mask);
7864           break;
7865         }
7866         case 4:  /* Colorize */
7867         {
7868           PixelInfo
7869             target;
7870
7871           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7872             0,0,&target,exception);
7873           if (attribute_flag[0] != 0)
7874             (void) QueryColorCompliance(argument_list[0].string_reference,
7875               AllCompliance,&target,exception);
7876           if (attribute_flag[1] == 0)
7877             argument_list[1].string_reference="100%";
7878           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7879             exception);
7880           break;
7881         }
7882         case 5:  /* Border */
7883         {
7884           CompositeOperator
7885             compose;
7886
7887           geometry.width=0;
7888           geometry.height=0;
7889           if (attribute_flag[0] != 0)
7890             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7891               &geometry,exception);
7892           if (attribute_flag[1] != 0)
7893             geometry.width=argument_list[1].integer_reference;
7894           if (attribute_flag[2] != 0)
7895             geometry.height=argument_list[2].integer_reference;
7896           if (attribute_flag[3] != 0)
7897             QueryColorCompliance(argument_list[3].string_reference,
7898               AllCompliance,&image->border_color,exception);
7899           if (attribute_flag[4] != 0)
7900             QueryColorCompliance(argument_list[4].string_reference,
7901               AllCompliance,&image->border_color,exception);
7902           if (attribute_flag[5] != 0)
7903             QueryColorCompliance(argument_list[5].string_reference,
7904               AllCompliance,&image->border_color,exception);
7905           compose=image->compose;
7906           if (attribute_flag[6] != 0)
7907             compose=(CompositeOperator) argument_list[6].integer_reference;
7908           image=BorderImage(image,&geometry,compose,exception);
7909           break;
7910         }
7911         case 6:  /* Blur */
7912         {
7913           if (attribute_flag[0] != 0)
7914             {
7915               flags=ParseGeometry(argument_list[0].string_reference,
7916                 &geometry_info);
7917               if ((flags & SigmaValue) == 0)
7918                 geometry_info.sigma=1.0;
7919             }
7920           if (attribute_flag[1] != 0)
7921             geometry_info.rho=argument_list[1].real_reference;
7922           if (attribute_flag[2] != 0)
7923             geometry_info.sigma=argument_list[2].real_reference;
7924           if (attribute_flag[3] != 0)
7925             channel=(ChannelType) argument_list[3].integer_reference;
7926           channel_mask=SetImageChannelMask(image,channel);
7927           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7928             exception);
7929           if (image != (Image *) NULL)
7930             (void) SetImageChannelMask(image,channel_mask);
7931           break;
7932         }
7933         case 7:  /* Chop */
7934         {
7935           if (attribute_flag[5] != 0)
7936             image->gravity=(GravityType) argument_list[5].integer_reference;
7937           if (attribute_flag[0] != 0)
7938             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7939               &geometry,exception);
7940           if (attribute_flag[1] != 0)
7941             geometry.width=argument_list[1].integer_reference;
7942           if (attribute_flag[2] != 0)
7943             geometry.height=argument_list[2].integer_reference;
7944           if (attribute_flag[3] != 0)
7945             geometry.x=argument_list[3].integer_reference;
7946           if (attribute_flag[4] != 0)
7947             geometry.y=argument_list[4].integer_reference;
7948           image=ChopImage(image,&geometry,exception);
7949           break;
7950         }
7951         case 8:  /* Crop */
7952         {
7953           if (attribute_flag[6] != 0)
7954             image->gravity=(GravityType) argument_list[6].integer_reference;
7955           if (attribute_flag[0] != 0)
7956             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7957               &geometry,exception);
7958           if (attribute_flag[1] != 0)
7959             geometry.width=argument_list[1].integer_reference;
7960           if (attribute_flag[2] != 0)
7961             geometry.height=argument_list[2].integer_reference;
7962           if (attribute_flag[3] != 0)
7963             geometry.x=argument_list[3].integer_reference;
7964           if (attribute_flag[4] != 0)
7965             geometry.y=argument_list[4].integer_reference;
7966           if (attribute_flag[5] != 0)
7967             image->fuzz=StringToDoubleInterval(
7968               argument_list[5].string_reference,(double) QuantumRange+1.0);
7969           image=CropImage(image,&geometry,exception);
7970           break;
7971         }
7972         case 9:  /* Despeckle */
7973         {
7974           image=DespeckleImage(image,exception);
7975           break;
7976         }
7977         case 10:  /* Edge */
7978         {
7979           if (attribute_flag[0] != 0)
7980             geometry_info.rho=argument_list[0].real_reference;
7981           image=EdgeImage(image,geometry_info.rho,exception);
7982           break;
7983         }
7984         case 11:  /* Emboss */
7985         {
7986           if (attribute_flag[0] != 0)
7987             {
7988               flags=ParseGeometry(argument_list[0].string_reference,
7989                 &geometry_info);
7990               if ((flags & SigmaValue) == 0)
7991                 geometry_info.sigma=1.0;
7992             }
7993           if (attribute_flag[1] != 0)
7994             geometry_info.rho=argument_list[1].real_reference;
7995           if (attribute_flag[2] != 0)
7996             geometry_info.sigma=argument_list[2].real_reference;
7997           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7998             exception);
7999           break;
8000         }
8001         case 12:  /* Enhance */
8002         {
8003           image=EnhanceImage(image,exception);
8004           break;
8005         }
8006         case 13:  /* Flip */
8007         {
8008           image=FlipImage(image,exception);
8009           break;
8010         }
8011         case 14:  /* Flop */
8012         {
8013           image=FlopImage(image,exception);
8014           break;
8015         }
8016         case 15:  /* Frame */
8017         {
8018           CompositeOperator
8019             compose;
8020
8021           FrameInfo
8022             frame_info;
8023
8024           if (attribute_flag[0] != 0)
8025             {
8026               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8027                 &geometry,exception);
8028               frame_info.width=geometry.width;
8029               frame_info.height=geometry.height;
8030               frame_info.outer_bevel=geometry.x;
8031               frame_info.inner_bevel=geometry.y;
8032             }
8033           if (attribute_flag[1] != 0)
8034             frame_info.width=argument_list[1].integer_reference;
8035           if (attribute_flag[2] != 0)
8036             frame_info.height=argument_list[2].integer_reference;
8037           if (attribute_flag[3] != 0)
8038             frame_info.inner_bevel=argument_list[3].integer_reference;
8039           if (attribute_flag[4] != 0)
8040             frame_info.outer_bevel=argument_list[4].integer_reference;
8041           if (attribute_flag[5] != 0)
8042             QueryColorCompliance(argument_list[5].string_reference,
8043               AllCompliance,&fill_color,exception);
8044           if (attribute_flag[6] != 0)
8045             QueryColorCompliance(argument_list[6].string_reference,
8046               AllCompliance,&fill_color,exception);
8047           frame_info.x=(ssize_t) frame_info.width;
8048           frame_info.y=(ssize_t) frame_info.height;
8049           frame_info.width=image->columns+2*frame_info.x;
8050           frame_info.height=image->rows+2*frame_info.y;
8051           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8052             image->matte_color=fill_color;
8053           compose=image->compose;
8054           if (attribute_flag[7] != 0)
8055             compose=(CompositeOperator) argument_list[7].integer_reference;
8056           image=FrameImage(image,&frame_info,compose,exception);
8057           break;
8058         }
8059         case 16:  /* Implode */
8060         {
8061           PixelInterpolateMethod
8062             method;
8063
8064           if (attribute_flag[0] == 0)
8065             argument_list[0].real_reference=0.5;
8066           method=UndefinedInterpolatePixel;
8067           if (attribute_flag[1] != 0)
8068             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8069           image=ImplodeImage(image,argument_list[0].real_reference,
8070             method,exception);
8071           break;
8072         }
8073         case 17:  /* Magnify */
8074         {
8075           image=MagnifyImage(image,exception);
8076           break;
8077         }
8078         case 18:  /* MedianFilter */
8079         {
8080           if (attribute_flag[0] != 0)
8081             {
8082               flags=ParseGeometry(argument_list[0].string_reference,
8083                 &geometry_info);
8084               if ((flags & SigmaValue) == 0)
8085                 geometry_info.sigma=geometry_info.rho;
8086             }
8087           if (attribute_flag[1] != 0)
8088             geometry_info.rho=argument_list[1].real_reference;
8089           if (attribute_flag[2] != 0)
8090             geometry_info.sigma=argument_list[2].real_reference;
8091           if (attribute_flag[3] != 0)
8092             channel=(ChannelType) argument_list[3].integer_reference;
8093           channel_mask=SetImageChannelMask(image,channel);
8094           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8095             (size_t) geometry_info.sigma,exception);
8096           if (image != (Image *) NULL)
8097             (void) SetImageChannelMask(image,channel_mask);
8098           break;
8099         }
8100         case 19:  /* Minify */
8101         {
8102           image=MinifyImage(image,exception);
8103           break;
8104         }
8105         case 20:  /* OilPaint */
8106         {
8107           if (attribute_flag[0] == 0)
8108             argument_list[0].real_reference=0.0;
8109           if (attribute_flag[1] == 0)
8110             argument_list[1].real_reference=1.0;
8111           image=OilPaintImage(image,argument_list[0].real_reference,
8112             argument_list[1].real_reference,exception);
8113           break;
8114         }
8115         case 21:  /* ReduceNoise */
8116         {
8117           if (attribute_flag[0] != 0)
8118             {
8119               flags=ParseGeometry(argument_list[0].string_reference,
8120                 &geometry_info);
8121               if ((flags & SigmaValue) == 0)
8122                 geometry_info.sigma=1.0;
8123             }
8124           if (attribute_flag[1] != 0)
8125             geometry_info.rho=argument_list[1].real_reference;
8126           if (attribute_flag[2] != 0)
8127             geometry_info.sigma=argument_list[2].real_reference;
8128           if (attribute_flag[3] != 0)
8129             channel=(ChannelType) argument_list[3].integer_reference;
8130           channel_mask=SetImageChannelMask(image,channel);
8131           image=StatisticImage(image,NonpeakStatistic,(size_t)
8132             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8133           if (image != (Image *) NULL)
8134             (void) SetImageChannelMask(image,channel_mask);
8135           break;
8136         }
8137         case 22:  /* Roll */
8138         {
8139           if (attribute_flag[0] != 0)
8140             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8141               &geometry,exception);
8142           if (attribute_flag[1] != 0)
8143             geometry.x=argument_list[1].integer_reference;
8144           if (attribute_flag[2] != 0)
8145             geometry.y=argument_list[2].integer_reference;
8146           image=RollImage(image,geometry.x,geometry.y,exception);
8147           break;
8148         }
8149         case 23:  /* Rotate */
8150         {
8151           if (attribute_flag[0] == 0)
8152             argument_list[0].real_reference=90.0;
8153           if (attribute_flag[1] != 0)
8154             {
8155               QueryColorCompliance(argument_list[1].string_reference,
8156                 AllCompliance,&image->background_color,exception);
8157               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8158                   (image->alpha_trait == UndefinedPixelTrait))
8159                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8160             }
8161           image=RotateImage(image,argument_list[0].real_reference,exception);
8162           break;
8163         }
8164         case 24:  /* Sample */
8165         {
8166           if (attribute_flag[0] != 0)
8167             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8168               &geometry,exception);
8169           if (attribute_flag[1] != 0)
8170             geometry.width=argument_list[1].integer_reference;
8171           if (attribute_flag[2] != 0)
8172             geometry.height=argument_list[2].integer_reference;
8173           image=SampleImage(image,geometry.width,geometry.height,exception);
8174           break;
8175         }
8176         case 25:  /* Scale */
8177         {
8178           if (attribute_flag[0] != 0)
8179             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8180               &geometry,exception);
8181           if (attribute_flag[1] != 0)
8182             geometry.width=argument_list[1].integer_reference;
8183           if (attribute_flag[2] != 0)
8184             geometry.height=argument_list[2].integer_reference;
8185           image=ScaleImage(image,geometry.width,geometry.height,exception);
8186           break;
8187         }
8188         case 26:  /* Shade */
8189         {
8190           if (attribute_flag[0] != 0)
8191             {
8192               flags=ParseGeometry(argument_list[0].string_reference,
8193                 &geometry_info);
8194               if ((flags & SigmaValue) == 0)
8195                 geometry_info.sigma=0.0;
8196             }
8197           if (attribute_flag[1] != 0)
8198             geometry_info.rho=argument_list[1].real_reference;
8199           if (attribute_flag[2] != 0)
8200             geometry_info.sigma=argument_list[2].real_reference;
8201           image=ShadeImage(image,
8202             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8203             geometry_info.rho,geometry_info.sigma,exception);
8204           break;
8205         }
8206         case 27:  /* Sharpen */
8207         {
8208           if (attribute_flag[0] != 0)
8209             {
8210               flags=ParseGeometry(argument_list[0].string_reference,
8211                 &geometry_info);
8212               if ((flags & SigmaValue) == 0)
8213                 geometry_info.sigma=1.0;
8214             }
8215           if (attribute_flag[1] != 0)
8216             geometry_info.rho=argument_list[1].real_reference;
8217           if (attribute_flag[2] != 0)
8218             geometry_info.sigma=argument_list[2].real_reference;
8219           if (attribute_flag[3] != 0)
8220             channel=(ChannelType) argument_list[3].integer_reference;
8221           channel_mask=SetImageChannelMask(image,channel);
8222           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8223             exception);
8224           if (image != (Image *) NULL)
8225             (void) SetImageChannelMask(image,channel_mask);
8226           break;
8227         }
8228         case 28:  /* Shear */
8229         {
8230           if (attribute_flag[0] != 0)
8231             {
8232               flags=ParseGeometry(argument_list[0].string_reference,
8233                 &geometry_info);
8234               if ((flags & SigmaValue) == 0)
8235                 geometry_info.sigma=geometry_info.rho;
8236             }
8237           if (attribute_flag[1] != 0)
8238             geometry_info.rho=argument_list[1].real_reference;
8239           if (attribute_flag[2] != 0)
8240             geometry_info.sigma=argument_list[2].real_reference;
8241           if (attribute_flag[3] != 0)
8242             QueryColorCompliance(argument_list[3].string_reference,
8243               AllCompliance,&image->background_color,exception);
8244           if (attribute_flag[4] != 0)
8245             QueryColorCompliance(argument_list[4].string_reference,
8246               AllCompliance,&image->background_color,exception);
8247           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8248             exception);
8249           break;
8250         }
8251         case 29:  /* Spread */
8252         {
8253           PixelInterpolateMethod
8254             method;
8255
8256           if (attribute_flag[0] == 0)
8257             argument_list[0].real_reference=1.0;
8258           method=UndefinedInterpolatePixel;
8259           if (attribute_flag[1] != 0)
8260             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8261           image=SpreadImage(image,argument_list[0].real_reference,method,
8262             exception);
8263           break;
8264         }
8265         case 30:  /* Swirl */
8266         {
8267           PixelInterpolateMethod
8268             method;
8269
8270           if (attribute_flag[0] == 0)
8271             argument_list[0].real_reference=50.0;
8272           method=UndefinedInterpolatePixel;
8273           if (attribute_flag[1] != 0)
8274             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8275           image=SwirlImage(image,argument_list[0].real_reference,
8276             method,exception);
8277           break;
8278         }
8279         case 31:  /* Resize */
8280         case 32:  /* Zoom */
8281         {
8282           if (attribute_flag[0] != 0)
8283             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8284               &geometry,exception);
8285           if (attribute_flag[1] != 0)
8286             geometry.width=argument_list[1].integer_reference;
8287           if (attribute_flag[2] != 0)
8288             geometry.height=argument_list[2].integer_reference;
8289           if (attribute_flag[3] == 0)
8290             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8291           if (attribute_flag[4] != 0)
8292             SetImageArtifact(image,"filter:support",
8293               argument_list[4].string_reference);
8294           image=ResizeImage(image,geometry.width,geometry.height,
8295             (FilterTypes) argument_list[3].integer_reference,
8296             exception);
8297           break;
8298         }
8299         case 33:  /* Annotate */
8300         {
8301           DrawInfo
8302             *draw_info;
8303
8304           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8305             (DrawInfo *) NULL);
8306           if (attribute_flag[0] != 0)
8307             {
8308               char
8309                 *text;
8310
8311               text=InterpretImageProperties(info ? info->image_info :
8312                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8313                 exception);
8314               (void) CloneString(&draw_info->text,text);
8315               text=DestroyString(text);
8316             }
8317           if (attribute_flag[1] != 0)
8318             (void) CloneString(&draw_info->font,
8319               argument_list[1].string_reference);
8320           if (attribute_flag[2] != 0)
8321             draw_info->pointsize=argument_list[2].real_reference;
8322           if (attribute_flag[3] != 0)
8323             (void) CloneString(&draw_info->density,
8324               argument_list[3].string_reference);
8325           if (attribute_flag[4] != 0)
8326             (void) QueryColorCompliance(argument_list[4].string_reference,
8327               AllCompliance,&draw_info->undercolor,exception);
8328           if (attribute_flag[5] != 0)
8329             {
8330               (void) QueryColorCompliance(argument_list[5].string_reference,
8331                 AllCompliance,&draw_info->stroke,exception);
8332               if (argument_list[5].image_reference != (Image *) NULL)
8333                 draw_info->stroke_pattern=CloneImage(
8334                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8335             }
8336           if (attribute_flag[6] != 0)
8337             {
8338               (void) QueryColorCompliance(argument_list[6].string_reference,
8339                 AllCompliance,&draw_info->fill,exception);
8340               if (argument_list[6].image_reference != (Image *) NULL)
8341                 draw_info->fill_pattern=CloneImage(
8342                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8343             }
8344           if (attribute_flag[7] != 0)
8345             {
8346               (void) CloneString(&draw_info->geometry,
8347                 argument_list[7].string_reference);
8348               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8349                 &geometry,exception);
8350               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8351                 geometry_info.sigma=geometry_info.xi;
8352             }
8353           if (attribute_flag[8] != 0)
8354             (void) QueryColorCompliance(argument_list[8].string_reference,
8355               AllCompliance,&draw_info->fill,exception);
8356           if (attribute_flag[11] != 0)
8357             draw_info->gravity=(GravityType)
8358               argument_list[11].integer_reference;
8359           if (attribute_flag[25] != 0)
8360             {
8361               AV
8362                 *av;
8363
8364               av=(AV *) argument_list[25].array_reference;
8365               if ((av_len(av) != 3) && (av_len(av) != 5))
8366                 {
8367                   ThrowPerlException(exception,OptionError,
8368                     "affine matrix must have 4 or 6 elements",PackageName);
8369                   goto PerlException;
8370                 }
8371               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8372               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8373               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8374               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8375               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8376                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8377                 {
8378                   ThrowPerlException(exception,OptionError,
8379                     "affine matrix is singular",PackageName);
8380                    goto PerlException;
8381                 }
8382               if (av_len(av) == 5)
8383                 {
8384                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8385                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8386                 }
8387             }
8388           for (j=12; j < 17; j++)
8389           {
8390             if (attribute_flag[j] == 0)
8391               continue;
8392             value=argument_list[j].string_reference;
8393             angle=argument_list[j].real_reference;
8394             current=draw_info->affine;
8395             GetAffineMatrix(&affine);
8396             switch (j)
8397             {
8398               case 12:
8399               {
8400                 /*
8401                   Translate.
8402                 */
8403                 flags=ParseGeometry(value,&geometry_info);
8404                 affine.tx=geometry_info.xi;
8405                 affine.ty=geometry_info.psi;
8406                 if ((flags & PsiValue) == 0)
8407                   affine.ty=affine.tx;
8408                 break;
8409               }
8410               case 13:
8411               {
8412                 /*
8413                   Scale.
8414                 */
8415                 flags=ParseGeometry(value,&geometry_info);
8416                 affine.sx=geometry_info.rho;
8417                 affine.sy=geometry_info.sigma;
8418                 if ((flags & SigmaValue) == 0)
8419                   affine.sy=affine.sx;
8420                 break;
8421               }
8422               case 14:
8423               {
8424                 /*
8425                   Rotate.
8426                 */
8427                 if (angle == 0.0)
8428                   break;
8429                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8430                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8431                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8432                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8433                 break;
8434               }
8435               case 15:
8436               {
8437                 /*
8438                   SkewX.
8439                 */
8440                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8441                 break;
8442               }
8443               case 16:
8444               {
8445                 /*
8446                   SkewY.
8447                 */
8448                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8449                 break;
8450               }
8451             }
8452             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8453             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8454             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8455             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8456             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8457               current.tx;
8458             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8459               current.ty;
8460           }
8461           if (attribute_flag[9] == 0)
8462             argument_list[9].real_reference=0.0;
8463           if (attribute_flag[10] == 0)
8464             argument_list[10].real_reference=0.0;
8465           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8466             {
8467               char
8468                 geometry[MagickPathExtent];
8469
8470               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8471                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8472                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8473               (void) CloneString(&draw_info->geometry,geometry);
8474             }
8475           if (attribute_flag[17] != 0)
8476             draw_info->stroke_width=argument_list[17].real_reference;
8477           if (attribute_flag[18] != 0)
8478             {
8479               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8480                 MagickTrue : MagickFalse;
8481               draw_info->stroke_antialias=draw_info->text_antialias;
8482             }
8483           if (attribute_flag[19] != 0)
8484             (void) CloneString(&draw_info->family,
8485               argument_list[19].string_reference);
8486           if (attribute_flag[20] != 0)
8487             draw_info->style=(StyleType) argument_list[20].integer_reference;
8488           if (attribute_flag[21] != 0)
8489             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8490           if (attribute_flag[22] != 0)
8491             draw_info->weight=argument_list[22].integer_reference;
8492           if (attribute_flag[23] != 0)
8493             draw_info->align=(AlignType) argument_list[23].integer_reference;
8494           if (attribute_flag[24] != 0)
8495             (void) CloneString(&draw_info->encoding,
8496               argument_list[24].string_reference);
8497           if (attribute_flag[25] != 0)
8498             draw_info->fill_pattern=CloneImage(
8499               argument_list[25].image_reference,0,0,MagickTrue,exception);
8500           if (attribute_flag[26] != 0)
8501             draw_info->fill_pattern=CloneImage(
8502               argument_list[26].image_reference,0,0,MagickTrue,exception);
8503           if (attribute_flag[27] != 0)
8504             draw_info->stroke_pattern=CloneImage(
8505               argument_list[27].image_reference,0,0,MagickTrue,exception);
8506           if (attribute_flag[29] != 0)
8507             draw_info->kerning=argument_list[29].real_reference;
8508           if (attribute_flag[30] != 0)
8509             draw_info->interline_spacing=argument_list[30].real_reference;
8510           if (attribute_flag[31] != 0)
8511             draw_info->interword_spacing=argument_list[31].real_reference;
8512           if (attribute_flag[32] != 0)
8513             draw_info->direction=(DirectionType)
8514               argument_list[32].integer_reference;
8515           (void) AnnotateImage(image,draw_info,exception);
8516           draw_info=DestroyDrawInfo(draw_info);
8517           break;
8518         }
8519         case 34:  /* ColorFloodfill */
8520         {
8521           DrawInfo
8522             *draw_info;
8523
8524           MagickBooleanType
8525             invert;
8526
8527           PixelInfo
8528             target;
8529
8530           draw_info=CloneDrawInfo(info ? info->image_info :
8531             (ImageInfo *) NULL,(DrawInfo *) NULL);
8532           if (attribute_flag[0] != 0)
8533             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8534               &geometry,exception);
8535           if (attribute_flag[1] != 0)
8536             geometry.x=argument_list[1].integer_reference;
8537           if (attribute_flag[2] != 0)
8538             geometry.y=argument_list[2].integer_reference;
8539           if (attribute_flag[3] != 0)
8540             (void) QueryColorCompliance(argument_list[3].string_reference,
8541               AllCompliance,&draw_info->fill,exception);
8542           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8543             geometry.x,geometry.y,&target,exception);
8544           invert=MagickFalse;
8545           if (attribute_flag[4] != 0)
8546             {
8547               QueryColorCompliance(argument_list[4].string_reference,
8548                 AllCompliance,&target,exception);
8549               invert=MagickTrue;
8550             }
8551           if (attribute_flag[5] != 0)
8552             image->fuzz=StringToDoubleInterval(
8553               argument_list[5].string_reference,(double) QuantumRange+1.0);
8554           if (attribute_flag[6] != 0)
8555             invert=(MagickBooleanType) argument_list[6].integer_reference;
8556           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8557             geometry.y,invert,exception);
8558           draw_info=DestroyDrawInfo(draw_info);
8559           break;
8560         }
8561         case 35:  /* Composite */
8562         {
8563           char
8564             composite_geometry[MagickPathExtent];
8565
8566           Image
8567             *composite_image,
8568             *rotate_image;
8569
8570           MagickBooleanType
8571             clip_to_self;
8572
8573           compose=OverCompositeOp;
8574           if (attribute_flag[0] != 0)
8575             composite_image=argument_list[0].image_reference;
8576           else
8577             {
8578               ThrowPerlException(exception,OptionError,
8579                 "CompositeImageRequired",PackageName);
8580               goto PerlException;
8581             }
8582           /*
8583             Parameter Handling used for BOTH normal and tiled composition.
8584           */
8585           if (attribute_flag[1] != 0) /* compose */
8586             compose=(CompositeOperator) argument_list[1].integer_reference;
8587           if (attribute_flag[6] != 0) /* opacity  */
8588             {
8589               if (compose != DissolveCompositeOp)
8590                 (void) SetImageAlpha(composite_image,(Quantum)
8591                   StringToDoubleInterval(argument_list[6].string_reference,
8592                   (double) QuantumRange+1.0),exception);
8593               else
8594                 {
8595                   CacheView
8596                     *composite_view;
8597
8598                   double
8599                     opacity;
8600
8601                   MagickBooleanType
8602                     sync;
8603
8604                   register ssize_t
8605                     x;
8606
8607                   register Quantum
8608                     *q;
8609
8610                   ssize_t
8611                     y;
8612
8613                   /*
8614                     Handle dissolve composite operator (patch by
8615                     Kevin A. McGrail).
8616                   */
8617                   (void) CloneString(&image->geometry,
8618                     argument_list[6].string_reference);
8619                   opacity=(Quantum) StringToDoubleInterval(
8620                     argument_list[6].string_reference,(double) QuantumRange+
8621                     1.0);
8622                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8623                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8624                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8625                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8626                   {
8627                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8628                       composite_image->columns,1,exception);
8629                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8630                     {
8631                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8632                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8633                           q);
8634                       q+=GetPixelChannels(composite_image);
8635                     }
8636                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8637                     if (sync == MagickFalse)
8638                       break;
8639                   }
8640                   composite_view=DestroyCacheView(composite_view);
8641                 }
8642             }
8643           if (attribute_flag[9] != 0)    /* "color=>" */
8644             QueryColorCompliance(argument_list[9].string_reference,
8645               AllCompliance,&composite_image->background_color,exception);
8646           if (attribute_flag[12] != 0) /* "interpolate=>" */
8647             image->interpolate=(PixelInterpolateMethod)
8648               argument_list[12].integer_reference;
8649           if (attribute_flag[13] != 0)   /* "args=>" */
8650             (void) SetImageArtifact(composite_image,"compose:args",
8651               argument_list[13].string_reference);
8652           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8653             (void) SetImageArtifact(composite_image,"compose:args",
8654               argument_list[14].string_reference);
8655           clip_to_self=MagickTrue;
8656           if (attribute_flag[15] != 0)
8657             clip_to_self=(MagickBooleanType)
8658               argument_list[15].integer_reference;
8659           /*
8660             Tiling Composition (with orthogonal rotate).
8661           */
8662           rotate_image=(Image *) NULL;
8663           if (attribute_flag[8] != 0)   /* "rotate=>" */
8664             {
8665                /*
8666                  Rotate image.
8667                */
8668                rotate_image=RotateImage(composite_image,
8669                  argument_list[8].real_reference,exception);
8670                if (rotate_image == (Image *) NULL)
8671                  break;
8672             }
8673           if ((attribute_flag[7] != 0) &&
8674               (argument_list[7].integer_reference != 0)) /* tile */
8675             {
8676               ssize_t
8677                 x,
8678                 y;
8679
8680               /*
8681                 Tile the composite image.
8682               */
8683              if (attribute_flag[8] != 0)   /* "tile=>" */
8684                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8685                  "false");
8686              else
8687                (void) SetImageArtifact(composite_image,
8688                  "compose:outside-overlay","false");
8689              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8690                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8691                 {
8692                   if (attribute_flag[8] != 0) /* rotate */
8693                     (void) CompositeImage(image,rotate_image,compose,
8694                       MagickTrue,x,y,exception);
8695                   else
8696                     (void) CompositeImage(image,composite_image,compose,
8697                       MagickTrue,x,y,exception);
8698                 }
8699               if (attribute_flag[8] != 0) /* rotate */
8700                 rotate_image=DestroyImage(rotate_image);
8701               break;
8702             }
8703           /*
8704             Parameter Handling used used ONLY for normal composition.
8705           */
8706           if (attribute_flag[5] != 0) /* gravity */
8707             image->gravity=(GravityType) argument_list[5].integer_reference;
8708           if (attribute_flag[2] != 0) /* geometry offset */
8709             {
8710               SetGeometry(image,&geometry);
8711               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8712                 &geometry);
8713               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8714                 &geometry);
8715             }
8716           if (attribute_flag[3] != 0) /* x offset */
8717             geometry.x=argument_list[3].integer_reference;
8718           if (attribute_flag[4] != 0) /* y offset */
8719             geometry.y=argument_list[4].integer_reference;
8720           if (attribute_flag[10] != 0) /* mask */
8721             {
8722               if ((image->compose == DisplaceCompositeOp) ||
8723                   (image->compose == DistortCompositeOp))
8724                 {
8725                   /*
8726                     Merge Y displacement into X displacement image.
8727                   */
8728                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8729                     exception);
8730                   (void) CompositeImage(composite_image,
8731                     argument_list[10].image_reference,CopyGreenCompositeOp,
8732                     MagickTrue,0,0,exception);
8733                 }
8734               else
8735                 {
8736                   Image
8737                     *mask_image;
8738
8739                   /*
8740                     Set a blending mask for the composition.
8741                   */
8742                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8743                     MagickTrue,exception);
8744                   (void) SetImageMask(composite_image,mask_image,exception);
8745                   mask_image=DestroyImage(mask_image);
8746                 }
8747             }
8748           if (attribute_flag[11] != 0) /* channel */
8749             channel=(ChannelType) argument_list[11].integer_reference;
8750           /*
8751             Composite two images (normal composition).
8752           */
8753           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8754             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8755             (double) composite_image->rows,(double) geometry.x,(double)
8756             geometry.y);
8757           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8758             exception);
8759           channel_mask=SetImageChannelMask(image,channel);
8760           if (attribute_flag[8] == 0) /* no rotate */
8761             CompositeImage(image,composite_image,compose,clip_to_self,
8762               geometry.x,geometry.y,exception);
8763           else
8764             {
8765               /*
8766                 Position adjust rotated image then composite.
8767               */
8768               geometry.x-=(ssize_t) (rotate_image->columns-
8769                 composite_image->columns)/2;
8770               geometry.y-=(ssize_t) (rotate_image->rows-
8771                 composite_image->rows)/2;
8772               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8773                 geometry.y,exception);
8774               rotate_image=DestroyImage(rotate_image);
8775             }
8776           if (attribute_flag[10] != 0) /* mask */
8777             {
8778               if ((image->compose == DisplaceCompositeOp) ||
8779                   (image->compose == DistortCompositeOp))
8780                 composite_image=DestroyImage(composite_image);
8781               else
8782                 (void) SetImageMask(image,(Image *) NULL,exception);
8783             }
8784           (void) SetImageChannelMask(image,channel_mask);
8785           break;
8786         }
8787         case 36:  /* Contrast */
8788         {
8789           if (attribute_flag[0] == 0)
8790             argument_list[0].integer_reference=0;
8791           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8792             MagickTrue : MagickFalse,exception);
8793           break;
8794         }
8795         case 37:  /* CycleColormap */
8796         {
8797           if (attribute_flag[0] == 0)
8798             argument_list[0].integer_reference=6;
8799           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8800             exception);
8801           break;
8802         }
8803         case 38:  /* Draw */
8804         {
8805           DrawInfo
8806             *draw_info;
8807
8808           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8809             (DrawInfo *) NULL);
8810           (void) CloneString(&draw_info->primitive,"point");
8811           if (attribute_flag[0] != 0)
8812             {
8813               if (argument_list[0].integer_reference < 0)
8814                 (void) CloneString(&draw_info->primitive,
8815                   argument_list[0].string_reference);
8816               else
8817                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8818                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8819             }
8820           if (attribute_flag[1] != 0)
8821             {
8822               if (LocaleCompare(draw_info->primitive,"path") == 0)
8823                 {
8824                   (void) ConcatenateString(&draw_info->primitive," '");
8825                   ConcatenateString(&draw_info->primitive,
8826                     argument_list[1].string_reference);
8827                   (void) ConcatenateString(&draw_info->primitive,"'");
8828                 }
8829               else
8830                 {
8831                   (void) ConcatenateString(&draw_info->primitive," ");
8832                   ConcatenateString(&draw_info->primitive,
8833                     argument_list[1].string_reference);
8834                 }
8835             }
8836           if (attribute_flag[2] != 0)
8837             {
8838               (void) ConcatenateString(&draw_info->primitive," ");
8839               (void) ConcatenateString(&draw_info->primitive,
8840                 CommandOptionToMnemonic(MagickMethodOptions,
8841                 argument_list[2].integer_reference));
8842             }
8843           if (attribute_flag[3] != 0)
8844             {
8845               (void) QueryColorCompliance(argument_list[3].string_reference,
8846                 AllCompliance,&draw_info->stroke,exception);
8847               if (argument_list[3].image_reference != (Image *) NULL)
8848                 draw_info->stroke_pattern=CloneImage(
8849                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8850             }
8851           if (attribute_flag[4] != 0)
8852             {
8853               (void) QueryColorCompliance(argument_list[4].string_reference,
8854                 AllCompliance,&draw_info->fill,exception);
8855               if (argument_list[4].image_reference != (Image *) NULL)
8856                 draw_info->fill_pattern=CloneImage(
8857                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8858             }
8859           if (attribute_flag[5] != 0)
8860             draw_info->stroke_width=argument_list[5].real_reference;
8861           if (attribute_flag[6] != 0)
8862             (void) CloneString(&draw_info->font,
8863               argument_list[6].string_reference);
8864           if (attribute_flag[7] != 0)
8865             (void) QueryColorCompliance(argument_list[7].string_reference,
8866               AllCompliance,&draw_info->border_color,exception);
8867           if (attribute_flag[8] != 0)
8868             draw_info->affine.tx=argument_list[8].real_reference;
8869           if (attribute_flag[9] != 0)
8870             draw_info->affine.ty=argument_list[9].real_reference;
8871           if (attribute_flag[20] != 0)
8872             {
8873               AV
8874                 *av;
8875
8876               av=(AV *) argument_list[20].array_reference;
8877               if ((av_len(av) != 3) && (av_len(av) != 5))
8878                 {
8879                   ThrowPerlException(exception,OptionError,
8880                     "affine matrix must have 4 or 6 elements",PackageName);
8881                   goto PerlException;
8882                 }
8883               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8884               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8885               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8886               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8887               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8888                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8889                 {
8890                   ThrowPerlException(exception,OptionError,
8891                     "affine matrix is singular",PackageName);
8892                    goto PerlException;
8893                 }
8894               if (av_len(av) == 5)
8895                 {
8896                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8897                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8898                 }
8899             }
8900           for (j=10; j < 15; j++)
8901           {
8902             if (attribute_flag[j] == 0)
8903               continue;
8904             value=argument_list[j].string_reference;
8905             angle=argument_list[j].real_reference;
8906             current=draw_info->affine;
8907             GetAffineMatrix(&affine);
8908             switch (j)
8909             {
8910               case 10:
8911               {
8912                 /*
8913                   Translate.
8914                 */
8915                 flags=ParseGeometry(value,&geometry_info);
8916                 affine.tx=geometry_info.xi;
8917                 affine.ty=geometry_info.psi;
8918                 if ((flags & PsiValue) == 0)
8919                   affine.ty=affine.tx;
8920                 break;
8921               }
8922               case 11:
8923               {
8924                 /*
8925                   Scale.
8926                 */
8927                 flags=ParseGeometry(value,&geometry_info);
8928                 affine.sx=geometry_info.rho;
8929                 affine.sy=geometry_info.sigma;
8930                 if ((flags & SigmaValue) == 0)
8931                   affine.sy=affine.sx;
8932                 break;
8933               }
8934               case 12:
8935               {
8936                 /*
8937                   Rotate.
8938                 */
8939                 if (angle == 0.0)
8940                   break;
8941                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8942                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8943                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8944                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8945                 break;
8946               }
8947               case 13:
8948               {
8949                 /*
8950                   SkewX.
8951                 */
8952                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8953                 break;
8954               }
8955               case 14:
8956               {
8957                 /*
8958                   SkewY.
8959                 */
8960                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8961                 break;
8962               }
8963             }
8964             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8965             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8966             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8967             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8968             draw_info->affine.tx=
8969               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8970             draw_info->affine.ty=
8971               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8972           }
8973           if (attribute_flag[15] != 0)
8974             draw_info->fill_pattern=CloneImage(
8975               argument_list[15].image_reference,0,0,MagickTrue,exception);
8976           if (attribute_flag[16] != 0)
8977             draw_info->pointsize=argument_list[16].real_reference;
8978           if (attribute_flag[17] != 0)
8979             {
8980               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8981                 ? MagickTrue : MagickFalse;
8982               draw_info->text_antialias=draw_info->stroke_antialias;
8983             }
8984           if (attribute_flag[18] != 0)
8985             (void) CloneString(&draw_info->density,
8986               argument_list[18].string_reference);
8987           if (attribute_flag[19] != 0)
8988             draw_info->stroke_width=argument_list[19].real_reference;
8989           if (attribute_flag[21] != 0)
8990             draw_info->dash_offset=argument_list[21].real_reference;
8991           if (attribute_flag[22] != 0)
8992             {
8993               AV
8994                 *av;
8995
8996               av=(AV *) argument_list[22].array_reference;
8997               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8998                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8999               if (draw_info->dash_pattern != (double *) NULL)
9000                 {
9001                   for (i=0; i <= av_len(av); i++)
9002                     draw_info->dash_pattern[i]=(double)
9003                       SvNV(*(av_fetch(av,i,0)));
9004                   draw_info->dash_pattern[i]=0.0;
9005                 }
9006             }
9007           if (attribute_flag[23] != 0)
9008             image->interpolate=(PixelInterpolateMethod)
9009               argument_list[23].integer_reference;
9010           if ((attribute_flag[24] != 0) &&
9011               (draw_info->fill_pattern != (Image *) NULL))
9012             flags=ParsePageGeometry(draw_info->fill_pattern,
9013               argument_list[24].string_reference,
9014               &draw_info->fill_pattern->tile_offset,exception);
9015           if (attribute_flag[25] != 0)
9016             {
9017               (void) ConcatenateString(&draw_info->primitive," '");
9018               (void) ConcatenateString(&draw_info->primitive,
9019                 argument_list[25].string_reference);
9020               (void) ConcatenateString(&draw_info->primitive,"'");
9021             }
9022           if (attribute_flag[26] != 0)
9023             draw_info->fill_pattern=CloneImage(
9024               argument_list[26].image_reference,0,0,MagickTrue,exception);
9025           if (attribute_flag[27] != 0)
9026             draw_info->stroke_pattern=CloneImage(
9027               argument_list[27].image_reference,0,0,MagickTrue,exception);
9028           if (attribute_flag[28] != 0)
9029             (void) CloneString(&draw_info->primitive,
9030               argument_list[28].string_reference);
9031           if (attribute_flag[29] != 0)
9032             draw_info->kerning=argument_list[29].real_reference;
9033           if (attribute_flag[30] != 0)
9034             draw_info->interline_spacing=argument_list[30].real_reference;
9035           if (attribute_flag[31] != 0)
9036             draw_info->interword_spacing=argument_list[31].real_reference;
9037           if (attribute_flag[32] != 0)
9038             draw_info->direction=(DirectionType)
9039               argument_list[32].integer_reference;
9040           DrawImage(image,draw_info,exception);
9041           draw_info=DestroyDrawInfo(draw_info);
9042           break;
9043         }
9044         case 39:  /* Equalize */
9045         {
9046           if (attribute_flag[0] != 0)
9047             channel=(ChannelType) argument_list[0].integer_reference;
9048           channel_mask=SetImageChannelMask(image,channel);
9049           EqualizeImage(image,exception);
9050           (void) SetImageChannelMask(image,channel_mask);
9051           break;
9052         }
9053         case 40:  /* Gamma */
9054         {
9055           if (attribute_flag[1] != 0)
9056             channel=(ChannelType) argument_list[1].integer_reference;
9057           if (attribute_flag[2] == 0)
9058             argument_list[2].real_reference=1.0;
9059           if (attribute_flag[3] == 0)
9060             argument_list[3].real_reference=1.0;
9061           if (attribute_flag[4] == 0)
9062             argument_list[4].real_reference=1.0;
9063           if (attribute_flag[0] == 0)
9064             {
9065               (void) FormatLocaleString(message,MagickPathExtent,
9066                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9067                 (double) argument_list[3].real_reference,
9068                 (double) argument_list[4].real_reference);
9069               argument_list[0].string_reference=message;
9070             }
9071           (void) GammaImage(image,StringToDouble(
9072             argument_list[0].string_reference,(char **) NULL),exception);
9073           break;
9074         }
9075         case 41:  /* Map */
9076         {
9077           QuantizeInfo
9078             *quantize_info;
9079
9080           if (attribute_flag[0] == 0)
9081             {
9082               ThrowPerlException(exception,OptionError,"MapImageRequired",
9083                 PackageName);
9084               goto PerlException;
9085             }
9086           quantize_info=AcquireQuantizeInfo(info->image_info);
9087           if (attribute_flag[1] != 0)
9088             quantize_info->dither_method=(DitherMethod)
9089               argument_list[1].integer_reference;
9090           (void) RemapImages(quantize_info,image,
9091             argument_list[0].image_reference,exception);
9092           quantize_info=DestroyQuantizeInfo(quantize_info);
9093           break;
9094         }
9095         case 42:  /* MatteFloodfill */
9096         {
9097           DrawInfo
9098             *draw_info;
9099
9100           MagickBooleanType
9101             invert;
9102
9103           PixelInfo
9104             target;
9105
9106           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9107             (DrawInfo *) NULL);
9108           if (attribute_flag[0] != 0)
9109             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9110               &geometry,exception);
9111           if (attribute_flag[1] != 0)
9112             geometry.x=argument_list[1].integer_reference;
9113           if (attribute_flag[2] != 0)
9114             geometry.y=argument_list[2].integer_reference;
9115           if (image->alpha_trait == UndefinedPixelTrait)
9116             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9117           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9118             geometry.x,geometry.y,&target,exception);
9119           if (attribute_flag[4] != 0)
9120             QueryColorCompliance(argument_list[4].string_reference,
9121               AllCompliance,&target,exception);
9122           if (attribute_flag[3] != 0)
9123             target.alpha=StringToDoubleInterval(
9124               argument_list[3].string_reference,(double) (double) QuantumRange+
9125               1.0);
9126           if (attribute_flag[5] != 0)
9127             image->fuzz=StringToDoubleInterval(
9128               argument_list[5].string_reference,(double) QuantumRange+1.0);
9129           invert=MagickFalse;
9130           if (attribute_flag[6] != 0)
9131             invert=(MagickBooleanType) argument_list[6].integer_reference;
9132           channel_mask=SetImageChannelMask(image,AlphaChannel);
9133           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9134             geometry.y,invert,exception);
9135           (void) SetImageChannelMask(image,channel_mask);
9136           draw_info=DestroyDrawInfo(draw_info);
9137           break;
9138         }
9139         case 43:  /* Modulate */
9140         {
9141           char
9142             modulate[MagickPathExtent];
9143
9144           geometry_info.rho=100.0;
9145           geometry_info.sigma=100.0;
9146           geometry_info.xi=100.0;
9147           if (attribute_flag[0] != 0)
9148             (void)ParseGeometry(argument_list[0].string_reference,
9149               &geometry_info);
9150           if (attribute_flag[1] != 0)
9151             geometry_info.xi=argument_list[1].real_reference;
9152           if (attribute_flag[2] != 0)
9153             geometry_info.sigma=argument_list[2].real_reference;
9154           if (attribute_flag[3] != 0)
9155             {
9156               geometry_info.sigma=argument_list[3].real_reference;
9157               SetImageArtifact(image,"modulate:colorspace","HWB");
9158             }
9159           if (attribute_flag[4] != 0)
9160             {
9161               geometry_info.rho=argument_list[4].real_reference;
9162               SetImageArtifact(image,"modulate:colorspace","HSB");
9163             }
9164           if (attribute_flag[5] != 0)
9165             {
9166               geometry_info.sigma=argument_list[5].real_reference;
9167               SetImageArtifact(image,"modulate:colorspace","HSL");
9168             }
9169           if (attribute_flag[6] != 0)
9170             {
9171               geometry_info.rho=argument_list[6].real_reference;
9172               SetImageArtifact(image,"modulate:colorspace","HWB");
9173             }
9174           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9175             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9176           (void) ModulateImage(image,modulate,exception);
9177           break;
9178         }
9179         case 44:  /* Negate */
9180         {
9181           if (attribute_flag[0] == 0)
9182             argument_list[0].integer_reference=0;
9183           if (attribute_flag[1] != 0)
9184             channel=(ChannelType) argument_list[1].integer_reference;
9185           channel_mask=SetImageChannelMask(image,channel);
9186           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9187             MagickTrue : MagickFalse,exception);
9188           (void) SetImageChannelMask(image,channel_mask);
9189           break;
9190         }
9191         case 45:  /* Normalize */
9192         {
9193           if (attribute_flag[0] != 0)
9194             channel=(ChannelType) argument_list[0].integer_reference;
9195           channel_mask=SetImageChannelMask(image,channel);
9196           NormalizeImage(image,exception);
9197           (void) SetImageChannelMask(image,channel_mask);
9198           break;
9199         }
9200         case 46:  /* NumberColors */
9201           break;
9202         case 47:  /* Opaque */
9203         {
9204           MagickBooleanType
9205             invert;
9206
9207           PixelInfo
9208             fill_color,
9209             target;
9210
9211           (void) QueryColorCompliance("none",AllCompliance,&target,
9212              exception);
9213           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9214             exception);
9215           if (attribute_flag[0] != 0)
9216             (void) QueryColorCompliance(argument_list[0].string_reference,
9217               AllCompliance,&target,exception);
9218           if (attribute_flag[1] != 0)
9219             (void) QueryColorCompliance(argument_list[1].string_reference,
9220               AllCompliance,&fill_color,exception);
9221           if (attribute_flag[2] != 0)
9222             image->fuzz=StringToDoubleInterval(
9223               argument_list[2].string_reference,(double) QuantumRange+1.0);
9224           if (attribute_flag[3] != 0)
9225             channel=(ChannelType) argument_list[3].integer_reference;
9226           invert=MagickFalse;
9227           if (attribute_flag[4] != 0)
9228             invert=(MagickBooleanType) argument_list[4].integer_reference;
9229           channel_mask=SetImageChannelMask(image,channel);
9230           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9231           (void) SetImageChannelMask(image,channel_mask);
9232           break;
9233         }
9234         case 48:  /* Quantize */
9235         {
9236           QuantizeInfo
9237             *quantize_info;
9238
9239           quantize_info=AcquireQuantizeInfo(info->image_info);
9240           if (attribute_flag[0] != 0)
9241             quantize_info->number_colors=(size_t)
9242               argument_list[0].integer_reference;
9243           if (attribute_flag[1] != 0)
9244             quantize_info->tree_depth=(size_t)
9245               argument_list[1].integer_reference;
9246           if (attribute_flag[2] != 0)
9247             quantize_info->colorspace=(ColorspaceType)
9248               argument_list[2].integer_reference;
9249           if (attribute_flag[3] != 0)
9250             quantize_info->dither_method=(DitherMethod)
9251               argument_list[3].integer_reference;
9252           if (attribute_flag[4] != 0)
9253             quantize_info->measure_error=
9254               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9255           if (attribute_flag[6] != 0)
9256             (void) QueryColorCompliance(argument_list[6].string_reference,
9257               AllCompliance,&image->transparent_color,exception);
9258           if (attribute_flag[7] != 0)
9259             quantize_info->dither_method=(DitherMethod)
9260               argument_list[7].integer_reference;
9261           if (attribute_flag[5] && argument_list[5].integer_reference)
9262             (void) QuantizeImages(quantize_info,image,exception);
9263           else
9264             if ((image->storage_class == DirectClass) ||
9265                (image->colors > quantize_info->number_colors) ||
9266                (quantize_info->colorspace == GRAYColorspace))
9267              (void) QuantizeImage(quantize_info,image,exception);
9268            else
9269              CompressImageColormap(image,exception);
9270           quantize_info=DestroyQuantizeInfo(quantize_info);
9271           break;
9272         }
9273         case 49:  /* Raise */
9274         {
9275           if (attribute_flag[0] != 0)
9276             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9277               &geometry,exception);
9278           if (attribute_flag[1] != 0)
9279             geometry.width=argument_list[1].integer_reference;
9280           if (attribute_flag[2] != 0)
9281             geometry.height=argument_list[2].integer_reference;
9282           if (attribute_flag[3] == 0)
9283             argument_list[3].integer_reference=1;
9284           (void) RaiseImage(image,&geometry,
9285             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9286             exception);
9287           break;
9288         }
9289         case 50:  /* Segment */
9290         {
9291           ColorspaceType
9292             colorspace;
9293
9294           double
9295             cluster_threshold,
9296             smoothing_threshold;
9297
9298           MagickBooleanType
9299             verbose;
9300
9301           cluster_threshold=1.0;
9302           smoothing_threshold=1.5;
9303           colorspace=sRGBColorspace;
9304           verbose=MagickFalse;
9305           if (attribute_flag[0] != 0)
9306             {
9307               flags=ParseGeometry(argument_list[0].string_reference,
9308                 &geometry_info);
9309               cluster_threshold=geometry_info.rho;
9310               if (flags & SigmaValue)
9311                 smoothing_threshold=geometry_info.sigma;
9312             }
9313           if (attribute_flag[1] != 0)
9314             cluster_threshold=argument_list[1].real_reference;
9315           if (attribute_flag[2] != 0)
9316             smoothing_threshold=argument_list[2].real_reference;
9317           if (attribute_flag[3] != 0)
9318             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9319           if (attribute_flag[4] != 0)
9320             verbose=argument_list[4].integer_reference != 0 ?
9321               MagickTrue : MagickFalse;
9322           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9323             smoothing_threshold,exception);
9324           break;
9325         }
9326         case 51:  /* Signature */
9327         {
9328           (void) SignatureImage(image,exception);
9329           break;
9330         }
9331         case 52:  /* Solarize */
9332         {
9333           geometry_info.rho=QuantumRange/2.0;
9334           if (attribute_flag[0] != 0)
9335             flags=ParseGeometry(argument_list[0].string_reference,
9336               &geometry_info);
9337           if (attribute_flag[1] != 0)
9338             geometry_info.rho=StringToDoubleInterval(
9339               argument_list[1].string_reference,(double) QuantumRange+1.0);
9340           (void) SolarizeImage(image,geometry_info.rho,exception);
9341           break;
9342         }
9343         case 53:  /* Sync */
9344         {
9345           (void) SyncImage(image,exception);
9346           break;
9347         }
9348         case 54:  /* Texture */
9349         {
9350           if (attribute_flag[0] == 0)
9351             break;
9352           TextureImage(image,argument_list[0].image_reference,exception);
9353           break;
9354         }
9355         case 55:  /* Evalute */
9356         {
9357           MagickEvaluateOperator
9358             op;
9359
9360           op=SetEvaluateOperator;
9361           if (attribute_flag[0] == MagickFalse)
9362             argument_list[0].real_reference=0.0;
9363           if (attribute_flag[1] != MagickFalse)
9364             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9365           if (attribute_flag[2] != MagickFalse)
9366             channel=(ChannelType) argument_list[2].integer_reference;
9367           channel_mask=SetImageChannelMask(image,channel);
9368           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9369             exception);
9370           (void) SetImageChannelMask(image,channel_mask);
9371           break;
9372         }
9373         case 56:  /* Transparent */
9374         {
9375           double
9376             opacity;
9377
9378           MagickBooleanType
9379             invert;
9380
9381           PixelInfo
9382             target;
9383
9384           (void) QueryColorCompliance("none",AllCompliance,&target,
9385             exception);
9386           if (attribute_flag[0] != 0)
9387             (void) QueryColorCompliance(argument_list[0].string_reference,
9388               AllCompliance,&target,exception);
9389           opacity=TransparentAlpha;
9390           if (attribute_flag[1] != 0)
9391             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9392               (double) QuantumRange+1.0);
9393           if (attribute_flag[2] != 0)
9394             image->fuzz=StringToDoubleInterval(
9395               argument_list[2].string_reference,(double) QuantumRange+1.0);
9396           if (attribute_flag[3] == 0)
9397             argument_list[3].integer_reference=0;
9398           invert=MagickFalse;
9399           if (attribute_flag[3] != 0)
9400             invert=(MagickBooleanType) argument_list[3].integer_reference;
9401           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9402             invert,exception);
9403           break;
9404         }
9405         case 57:  /* Threshold */
9406         {
9407           double
9408             threshold;
9409
9410           if (attribute_flag[0] == 0)
9411             argument_list[0].string_reference="50%";
9412           if (attribute_flag[1] != 0)
9413             channel=(ChannelType) argument_list[1].integer_reference;
9414           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9415             (double) QuantumRange+1.0);
9416           channel_mask=SetImageChannelMask(image,channel);
9417           (void) BilevelImage(image,threshold,exception);
9418           (void) SetImageChannelMask(image,channel_mask);
9419           break;
9420         }
9421         case 58:  /* Charcoal */
9422         {
9423           if (attribute_flag[0] != 0)
9424             {
9425               flags=ParseGeometry(argument_list[0].string_reference,
9426                 &geometry_info);
9427               if ((flags & SigmaValue) == 0)
9428                 geometry_info.sigma=1.0;
9429             }
9430           if (attribute_flag[1] != 0)
9431             geometry_info.rho=argument_list[1].real_reference;
9432           if (attribute_flag[2] != 0)
9433             geometry_info.sigma=argument_list[2].real_reference;
9434           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9435             exception);
9436           break;
9437         }
9438         case 59:  /* Trim */
9439         {
9440           if (attribute_flag[0] != 0)
9441             image->fuzz=StringToDoubleInterval(
9442               argument_list[0].string_reference,(double) QuantumRange+1.0);
9443           image=TrimImage(image,exception);
9444           break;
9445         }
9446         case 60:  /* Wave */
9447         {
9448           PixelInterpolateMethod
9449             method;
9450
9451           if (attribute_flag[0] != 0)
9452             {
9453               flags=ParseGeometry(argument_list[0].string_reference,
9454                 &geometry_info);
9455               if ((flags & SigmaValue) == 0)
9456                 geometry_info.sigma=1.0;
9457             }
9458           if (attribute_flag[1] != 0)
9459             geometry_info.rho=argument_list[1].real_reference;
9460           if (attribute_flag[2] != 0)
9461             geometry_info.sigma=argument_list[2].real_reference;
9462           method=UndefinedInterpolatePixel;
9463           if (attribute_flag[3] != 0)
9464             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9465           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9466             method,exception);
9467           break;
9468         }
9469         case 61:  /* Separate */
9470         {
9471           if (attribute_flag[0] != 0)
9472             channel=(ChannelType) argument_list[0].integer_reference;
9473           image=SeparateImage(image,channel,exception);
9474           break;
9475         }
9476         case 63:  /* Stereo */
9477         {
9478           if (attribute_flag[0] == 0)
9479             {
9480               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9481                 PackageName);
9482               goto PerlException;
9483             }
9484           if (attribute_flag[1] != 0)
9485             geometry.x=argument_list[1].integer_reference;
9486           if (attribute_flag[2] != 0)
9487             geometry.y=argument_list[2].integer_reference;
9488           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9489             geometry.x,geometry.y,exception);
9490           break;
9491         }
9492         case 64:  /* Stegano */
9493         {
9494           if (attribute_flag[0] == 0)
9495             {
9496               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9497                 PackageName);
9498               goto PerlException;
9499             }
9500           if (attribute_flag[1] == 0)
9501             argument_list[1].integer_reference=0;
9502           image->offset=argument_list[1].integer_reference;
9503           image=SteganoImage(image,argument_list[0].image_reference,exception);
9504           break;
9505         }
9506         case 65:  /* Deconstruct */
9507         {
9508           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9509           break;
9510         }
9511         case 66:  /* GaussianBlur */
9512         {
9513           if (attribute_flag[0] != 0)
9514             {
9515               flags=ParseGeometry(argument_list[0].string_reference,
9516                 &geometry_info);
9517               if ((flags & SigmaValue) == 0)
9518                 geometry_info.sigma=1.0;
9519             }
9520           if (attribute_flag[1] != 0)
9521             geometry_info.rho=argument_list[1].real_reference;
9522           if (attribute_flag[2] != 0)
9523             geometry_info.sigma=argument_list[2].real_reference;
9524           if (attribute_flag[3] != 0)
9525             channel=(ChannelType) argument_list[3].integer_reference;
9526           channel_mask=SetImageChannelMask(image,channel);
9527           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9528             exception);
9529           if (image != (Image *) NULL)
9530             (void) SetImageChannelMask(image,channel_mask);
9531           break;
9532         }
9533         case 67:  /* Convolve */
9534         {
9535           KernelInfo
9536             *kernel;
9537
9538           kernel=(KernelInfo *) NULL;
9539           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9540             break;
9541           if (attribute_flag[0] != 0)
9542             {
9543               AV
9544                 *av;
9545
9546               size_t
9547                 order;
9548
9549               kernel=AcquireKernelInfo((const char *) NULL,exception);
9550               if (kernel == (KernelInfo *) NULL)
9551                 break;
9552               av=(AV *) argument_list[0].array_reference;
9553               order=(size_t) sqrt(av_len(av)+1);
9554               kernel->width=order;
9555               kernel->height=order;
9556               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9557                 order*sizeof(*kernel->values));
9558               if (kernel->values == (MagickRealType *) NULL)
9559                 {
9560                   kernel=DestroyKernelInfo(kernel);
9561                   ThrowPerlException(exception,ResourceLimitFatalError,
9562                     "MemoryAllocationFailed",PackageName);
9563                   goto PerlException;
9564                 }
9565               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9566                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9567               for ( ; j < (ssize_t) (order*order); j++)
9568                 kernel->values[j]=0.0;
9569             }
9570           if (attribute_flag[1] != 0)
9571             channel=(ChannelType) argument_list[1].integer_reference;
9572           if (attribute_flag[2] != 0)
9573             SetImageArtifact(image,"filter:blur",
9574               argument_list[2].string_reference);
9575           if (attribute_flag[3] != 0)
9576             {
9577               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9578                 exception);
9579               if (kernel == (KernelInfo *) NULL)
9580                 break;
9581             }
9582           channel_mask=SetImageChannelMask(image,channel);
9583           image=ConvolveImage(image,kernel,exception);
9584           if (image != (Image *) NULL)
9585             (void) SetImageChannelMask(image,channel_mask);
9586           kernel=DestroyKernelInfo(kernel);
9587           break;
9588         }
9589         case 68:  /* Profile */
9590         {
9591           const char
9592             *name;
9593
9594           Image
9595             *profile_image;
9596
9597           ImageInfo
9598             *profile_info;
9599
9600           StringInfo
9601             *profile;
9602
9603           name="*";
9604           if (attribute_flag[0] != 0)
9605             name=argument_list[0].string_reference;
9606           if (attribute_flag[2] != 0)
9607             image->rendering_intent=(RenderingIntent)
9608               argument_list[2].integer_reference;
9609           if (attribute_flag[3] != 0)
9610             image->black_point_compensation=
9611               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9612           if (attribute_flag[1] != 0)
9613             {
9614               if (argument_list[1].length == 0)
9615                 {
9616                   /*
9617                     Remove a profile from the image.
9618                   */
9619                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9620                     exception);
9621                   break;
9622                 }
9623               /*
9624                 Associate user supplied profile with the image.
9625               */
9626               profile=AcquireStringInfo(argument_list[1].length);
9627               SetStringInfoDatum(profile,(const unsigned char *)
9628                 argument_list[1].string_reference);
9629               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9630                 (size_t) GetStringInfoLength(profile),exception);
9631               profile=DestroyStringInfo(profile);
9632               break;
9633             }
9634           /*
9635             Associate a profile with the image.
9636           */
9637           profile_info=CloneImageInfo(info ? info->image_info :
9638             (ImageInfo *) NULL);
9639           profile_image=ReadImages(profile_info,name,exception);
9640           if (profile_image == (Image *) NULL)
9641             break;
9642           ResetImageProfileIterator(profile_image);
9643           name=GetNextImageProfile(profile_image);
9644           while (name != (const char *) NULL)
9645           {
9646             const StringInfo
9647               *profile;
9648
9649             profile=GetImageProfile(profile_image,name);
9650             if (profile != (const StringInfo *) NULL)
9651               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9652                 (size_t) GetStringInfoLength(profile),exception);
9653             name=GetNextImageProfile(profile_image);
9654           }
9655           profile_image=DestroyImage(profile_image);
9656           profile_info=DestroyImageInfo(profile_info);
9657           break;
9658         }
9659         case 69:  /* UnsharpMask */
9660         {
9661           if (attribute_flag[0] != 0)
9662             {
9663               flags=ParseGeometry(argument_list[0].string_reference,
9664                 &geometry_info);
9665               if ((flags & SigmaValue) == 0)
9666                 geometry_info.sigma=1.0;
9667               if ((flags & XiValue) == 0)
9668                 geometry_info.xi=1.0;
9669               if ((flags & PsiValue) == 0)
9670                 geometry_info.psi=0.5;
9671             }
9672           if (attribute_flag[1] != 0)
9673             geometry_info.rho=argument_list[1].real_reference;
9674           if (attribute_flag[2] != 0)
9675             geometry_info.sigma=argument_list[2].real_reference;
9676           if (attribute_flag[3] != 0)
9677             geometry_info.xi=argument_list[3].real_reference;
9678           if (attribute_flag[4] != 0)
9679             geometry_info.psi=argument_list[4].real_reference;
9680           if (attribute_flag[5] != 0)
9681             channel=(ChannelType) argument_list[5].integer_reference;
9682           channel_mask=SetImageChannelMask(image,channel);
9683           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9684             geometry_info.xi,geometry_info.psi,exception);
9685           if (image != (Image *) NULL)
9686             (void) SetImageChannelMask(image,channel_mask);
9687           break;
9688         }
9689         case 70:  /* MotionBlur */
9690         {
9691           if (attribute_flag[0] != 0)
9692             {
9693               flags=ParseGeometry(argument_list[0].string_reference,
9694                 &geometry_info);
9695               if ((flags & SigmaValue) == 0)
9696                 geometry_info.sigma=1.0;
9697               if ((flags & XiValue) == 0)
9698                 geometry_info.xi=1.0;
9699             }
9700           if (attribute_flag[1] != 0)
9701             geometry_info.rho=argument_list[1].real_reference;
9702           if (attribute_flag[2] != 0)
9703             geometry_info.sigma=argument_list[2].real_reference;
9704           if (attribute_flag[3] != 0)
9705             geometry_info.xi=argument_list[3].real_reference;
9706           if (attribute_flag[4] != 0)
9707             channel=(ChannelType) argument_list[4].integer_reference;
9708           channel_mask=SetImageChannelMask(image,channel);
9709           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9710             geometry_info.xi,exception);
9711           if (image != (Image *) NULL)
9712             (void) SetImageChannelMask(image,channel_mask);
9713           break;
9714         }
9715         case 71:  /* OrderedDither */
9716         {
9717           if (attribute_flag[0] == 0)
9718             argument_list[0].string_reference="o8x8";
9719           if (attribute_flag[1] != 0)
9720             channel=(ChannelType) argument_list[1].integer_reference;
9721           channel_mask=SetImageChannelMask(image,channel);
9722           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9723             exception);
9724           (void) SetImageChannelMask(image,channel_mask);
9725           break;
9726         }
9727         case 72:  /* Shave */
9728         {
9729           if (attribute_flag[0] != 0)
9730             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9731               &geometry,exception);
9732           if (attribute_flag[1] != 0)
9733             geometry.width=argument_list[1].integer_reference;
9734           if (attribute_flag[2] != 0)
9735             geometry.height=argument_list[2].integer_reference;
9736           image=ShaveImage(image,&geometry,exception);
9737           break;
9738         }
9739         case 73:  /* Level */
9740         {
9741           double
9742             black_point,
9743             gamma,
9744             white_point;
9745
9746           black_point=0.0;
9747           white_point=(double) image->columns*image->rows;
9748           gamma=1.0;
9749           if (attribute_flag[0] != 0)
9750             {
9751               flags=ParseGeometry(argument_list[0].string_reference,
9752                 &geometry_info);
9753               black_point=geometry_info.rho;
9754               if ((flags & SigmaValue) != 0)
9755                 white_point=geometry_info.sigma;
9756               if ((flags & XiValue) != 0)
9757                 gamma=geometry_info.xi;
9758               if ((flags & PercentValue) != 0)
9759                 {
9760                   black_point*=(double) (QuantumRange/100.0);
9761                   white_point*=(double) (QuantumRange/100.0);
9762                 }
9763               if ((flags & SigmaValue) == 0)
9764                 white_point=(double) QuantumRange-black_point;
9765             }
9766           if (attribute_flag[1] != 0)
9767             black_point=argument_list[1].real_reference;
9768           if (attribute_flag[2] != 0)
9769             white_point=argument_list[2].real_reference;
9770           if (attribute_flag[3] != 0)
9771             gamma=argument_list[3].real_reference;
9772           if (attribute_flag[4] != 0)
9773             channel=(ChannelType) argument_list[4].integer_reference;
9774           if (attribute_flag[5] != 0)
9775             {
9776               argument_list[0].real_reference=argument_list[5].real_reference;
9777               attribute_flag[0]=attribute_flag[5];
9778             }
9779           channel_mask=SetImageChannelMask(image,channel);
9780           (void) LevelImage(image,black_point,white_point,gamma,exception);
9781           (void) SetImageChannelMask(image,channel_mask);
9782           break;
9783         }
9784         case 74:  /* Clip */
9785         {
9786           if (attribute_flag[0] == 0)
9787             argument_list[0].string_reference="#1";
9788           if (attribute_flag[1] == 0)
9789             argument_list[1].integer_reference=MagickTrue;
9790           (void) ClipImagePath(image,argument_list[0].string_reference,
9791             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9792             exception);
9793           break;
9794         }
9795         case 75:  /* AffineTransform */
9796         {
9797           DrawInfo
9798             *draw_info;
9799
9800           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9801             (DrawInfo *) NULL);
9802           if (attribute_flag[0] != 0)
9803             {
9804               AV
9805                 *av;
9806
9807               av=(AV *) argument_list[0].array_reference;
9808               if ((av_len(av) != 3) && (av_len(av) != 5))
9809                 {
9810                   ThrowPerlException(exception,OptionError,
9811                     "affine matrix must have 4 or 6 elements",PackageName);
9812                   goto PerlException;
9813                 }
9814               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9815               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9816               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9817               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9818               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9819                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9820                 {
9821                   ThrowPerlException(exception,OptionError,
9822                     "affine matrix is singular",PackageName);
9823                    goto PerlException;
9824                 }
9825               if (av_len(av) == 5)
9826                 {
9827                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9828                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9829                 }
9830             }
9831           for (j=1; j < 6; j++)
9832           {
9833             if (attribute_flag[j] == 0)
9834               continue;
9835             value=argument_list[j].string_reference;
9836             angle=argument_list[j].real_reference;
9837             current=draw_info->affine;
9838             GetAffineMatrix(&affine);
9839             switch (j)
9840             {
9841               case 1:
9842               {
9843                 /*
9844                   Translate.
9845                 */
9846                 flags=ParseGeometry(value,&geometry_info);
9847                 affine.tx=geometry_info.xi;
9848                 affine.ty=geometry_info.psi;
9849                 if ((flags & PsiValue) == 0)
9850                   affine.ty=affine.tx;
9851                 break;
9852               }
9853               case 2:
9854               {
9855                 /*
9856                   Scale.
9857                 */
9858                 flags=ParseGeometry(value,&geometry_info);
9859                 affine.sx=geometry_info.rho;
9860                 affine.sy=geometry_info.sigma;
9861                 if ((flags & SigmaValue) == 0)
9862                   affine.sy=affine.sx;
9863                 break;
9864               }
9865               case 3:
9866               {
9867                 /*
9868                   Rotate.
9869                 */
9870                 if (angle == 0.0)
9871                   break;
9872                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9873                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9874                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9875                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9876                 break;
9877               }
9878               case 4:
9879               {
9880                 /*
9881                   SkewX.
9882                 */
9883                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9884                 break;
9885               }
9886               case 5:
9887               {
9888                 /*
9889                   SkewY.
9890                 */
9891                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9892                 break;
9893               }
9894             }
9895             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9896             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9897             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9898             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9899             draw_info->affine.tx=
9900               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9901             draw_info->affine.ty=
9902               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9903           }
9904           if (attribute_flag[6] != 0)
9905             image->interpolate=(PixelInterpolateMethod)
9906               argument_list[6].integer_reference;
9907           if (attribute_flag[7] != 0)
9908             QueryColorCompliance(argument_list[7].string_reference,
9909               AllCompliance,&image->background_color,exception);
9910           image=AffineTransformImage(image,&draw_info->affine,exception);
9911           draw_info=DestroyDrawInfo(draw_info);
9912           break;
9913         }
9914         case 76:  /* Difference */
9915         {
9916           if (attribute_flag[0] == 0)
9917             {
9918               ThrowPerlException(exception,OptionError,
9919                 "ReferenceImageRequired",PackageName);
9920               goto PerlException;
9921             }
9922           if (attribute_flag[1] != 0)
9923             image->fuzz=StringToDoubleInterval(
9924               argument_list[1].string_reference,(double) QuantumRange+1.0);
9925           (void) IsImagesEqual(image,argument_list[0].image_reference,
9926             exception);
9927           break;
9928         }
9929         case 77:  /* AdaptiveThreshold */
9930         {
9931           if (attribute_flag[0] != 0)
9932             {
9933               flags=ParseGeometry(argument_list[0].string_reference,
9934                 &geometry_info);
9935               if ((flags & PercentValue) != 0)
9936                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9937             }
9938           if (attribute_flag[1] != 0)
9939             geometry_info.rho=argument_list[1].integer_reference;
9940           if (attribute_flag[2] != 0)
9941             geometry_info.sigma=argument_list[2].integer_reference;
9942           if (attribute_flag[3] != 0)
9943             geometry_info.xi=argument_list[3].integer_reference;;
9944           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9945             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9946           break;
9947         }
9948         case 78:  /* Resample */
9949         {
9950           size_t
9951             height,
9952             width;
9953
9954           if (attribute_flag[0] != 0)
9955             {
9956               flags=ParseGeometry(argument_list[0].string_reference,
9957                 &geometry_info);
9958               if ((flags & SigmaValue) == 0)
9959                 geometry_info.sigma=geometry_info.rho;
9960             }
9961           if (attribute_flag[1] != 0)
9962             geometry_info.rho=argument_list[1].real_reference;
9963           if (attribute_flag[2] != 0)
9964             geometry_info.sigma=argument_list[2].real_reference;
9965           if (attribute_flag[3] == 0)
9966             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9967           if (attribute_flag[4] == 0)
9968             SetImageArtifact(image,"filter:support",
9969               argument_list[4].string_reference);
9970           width=(size_t) (geometry_info.rho*image->columns/
9971             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9972           height=(size_t) (geometry_info.sigma*image->rows/
9973             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9974           image=ResizeImage(image,width,height,(FilterTypes)
9975             argument_list[3].integer_reference,exception);
9976           if (image != (Image *) NULL)
9977             {
9978               image->resolution.x=geometry_info.rho;
9979               image->resolution.y=geometry_info.sigma;
9980             }
9981           break;
9982         }
9983         case 79:  /* Describe */
9984         {
9985           if (attribute_flag[0] == 0)
9986             argument_list[0].file_reference=(FILE *) NULL;
9987           if (attribute_flag[1] != 0)
9988             (void) SetImageArtifact(image,"identify:features",
9989               argument_list[1].string_reference);
9990           (void) IdentifyImage(image,argument_list[0].file_reference,
9991             MagickTrue,exception);
9992           break;
9993         }
9994         case 80:  /* BlackThreshold */
9995         {
9996           if (attribute_flag[0] == 0)
9997             argument_list[0].string_reference="50%";
9998           if (attribute_flag[2] != 0)
9999             channel=(ChannelType) argument_list[2].integer_reference;
10000           channel_mask=SetImageChannelMask(image,channel);
10001           BlackThresholdImage(image,argument_list[0].string_reference,
10002             exception);
10003           (void) SetImageChannelMask(image,channel_mask);
10004           break;
10005         }
10006         case 81:  /* WhiteThreshold */
10007         {
10008           if (attribute_flag[0] == 0)
10009             argument_list[0].string_reference="50%";
10010           if (attribute_flag[2] != 0)
10011             channel=(ChannelType) argument_list[2].integer_reference;
10012           channel_mask=SetImageChannelMask(image,channel);
10013           WhiteThresholdImage(image,argument_list[0].string_reference,
10014             exception);
10015           (void) SetImageChannelMask(image,channel_mask);
10016           break;
10017         }
10018         case 82:  /* RotationalBlur */
10019         {
10020           if (attribute_flag[0] != 0)
10021             {
10022               flags=ParseGeometry(argument_list[0].string_reference,
10023                 &geometry_info);
10024             }
10025           if (attribute_flag[1] != 0)
10026             geometry_info.rho=argument_list[1].real_reference;
10027           if (attribute_flag[2] != 0)
10028             channel=(ChannelType) argument_list[2].integer_reference;
10029           channel_mask=SetImageChannelMask(image,channel);
10030           image=RotationalBlurImage(image,geometry_info.rho,exception);
10031           if (image != (Image *) NULL)
10032             (void) SetImageChannelMask(image,channel_mask);
10033           break;
10034         }
10035         case 83:  /* Thumbnail */
10036         {
10037           if (attribute_flag[0] != 0)
10038             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10039               &geometry,exception);
10040           if (attribute_flag[1] != 0)
10041             geometry.width=argument_list[1].integer_reference;
10042           if (attribute_flag[2] != 0)
10043             geometry.height=argument_list[2].integer_reference;
10044           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10045           break;
10046         }
10047         case 84:  /* Strip */
10048         {
10049           (void) StripImage(image,exception);
10050           break;
10051         }
10052         case 85:  /* Tint */
10053         {
10054           PixelInfo
10055             tint;
10056
10057           GetPixelInfo(image,&tint);
10058           if (attribute_flag[0] != 0)
10059             (void) QueryColorCompliance(argument_list[0].string_reference,
10060               AllCompliance,&tint,exception);
10061           if (attribute_flag[1] == 0)
10062             argument_list[1].string_reference="100";
10063           image=TintImage(image,argument_list[1].string_reference,&tint,
10064             exception);
10065           break;
10066         }
10067         case 86:  /* Channel */
10068         {
10069           if (attribute_flag[0] != 0)
10070             channel=(ChannelType) argument_list[0].integer_reference;
10071           image=SeparateImage(image,channel,exception);
10072           break;
10073         }
10074         case 87:  /* Splice */
10075         {
10076           if (attribute_flag[7] != 0)
10077             image->gravity=(GravityType) argument_list[7].integer_reference;
10078           if (attribute_flag[0] != 0)
10079             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10080               &geometry,exception);
10081           if (attribute_flag[1] != 0)
10082             geometry.width=argument_list[1].integer_reference;
10083           if (attribute_flag[2] != 0)
10084             geometry.height=argument_list[2].integer_reference;
10085           if (attribute_flag[3] != 0)
10086             geometry.x=argument_list[3].integer_reference;
10087           if (attribute_flag[4] != 0)
10088             geometry.y=argument_list[4].integer_reference;
10089           if (attribute_flag[5] != 0)
10090             image->fuzz=StringToDoubleInterval(
10091               argument_list[5].string_reference,(double) QuantumRange+1.0);
10092           if (attribute_flag[6] != 0)
10093             (void) QueryColorCompliance(argument_list[6].string_reference,
10094               AllCompliance,&image->background_color,exception);
10095           image=SpliceImage(image,&geometry,exception);
10096           break;
10097         }
10098         case 88:  /* Posterize */
10099         {
10100           if (attribute_flag[0] == 0)
10101             argument_list[0].integer_reference=3;
10102           if (attribute_flag[1] == 0)
10103             argument_list[1].integer_reference=0;
10104           (void) PosterizeImage(image,argument_list[0].integer_reference,
10105             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10106             NoDitherMethod,exception);
10107           break;
10108         }
10109         case 89:  /* Shadow */
10110         {
10111           if (attribute_flag[0] != 0)
10112             {
10113               flags=ParseGeometry(argument_list[0].string_reference,
10114                 &geometry_info);
10115               if ((flags & SigmaValue) == 0)
10116                 geometry_info.sigma=1.0;
10117               if ((flags & XiValue) == 0)
10118                 geometry_info.xi=4.0;
10119               if ((flags & PsiValue) == 0)
10120                 geometry_info.psi=4.0;
10121             }
10122           if (attribute_flag[1] != 0)
10123             geometry_info.rho=argument_list[1].real_reference;
10124           if (attribute_flag[2] != 0)
10125             geometry_info.sigma=argument_list[2].real_reference;
10126           if (attribute_flag[3] != 0)
10127             geometry_info.xi=argument_list[3].integer_reference;
10128           if (attribute_flag[4] != 0)
10129             geometry_info.psi=argument_list[4].integer_reference;
10130           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10131             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10132             ceil(geometry_info.psi-0.5),exception);
10133           break;
10134         }
10135         case 90:  /* Identify */
10136         {
10137           if (attribute_flag[0] == 0)
10138             argument_list[0].file_reference=(FILE *) NULL;
10139           if (attribute_flag[1] != 0)
10140             (void) SetImageArtifact(image,"identify:features",
10141               argument_list[1].string_reference);
10142           if ((attribute_flag[2] != 0) &&
10143               (argument_list[2].integer_reference != 0))
10144             (void) SetImageArtifact(image,"identify:unique","true");
10145           (void) IdentifyImage(image,argument_list[0].file_reference,
10146             MagickTrue,exception);
10147           break;
10148         }
10149         case 91:  /* SepiaTone */
10150         {
10151           if (attribute_flag[0] == 0)
10152             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10153           image=SepiaToneImage(image,argument_list[0].real_reference,
10154             exception);
10155           break;
10156         }
10157         case 92:  /* SigmoidalContrast */
10158         {
10159           MagickBooleanType
10160             sharpen;
10161
10162           if (attribute_flag[0] != 0)
10163             {
10164               flags=ParseGeometry(argument_list[0].string_reference,
10165                 &geometry_info);
10166               if ((flags & SigmaValue) == 0)
10167                 geometry_info.sigma=QuantumRange/2.0;
10168               if ((flags & PercentValue) != 0)
10169                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10170             }
10171           if (attribute_flag[1] != 0)
10172             geometry_info.rho=argument_list[1].real_reference;
10173           if (attribute_flag[2] != 0)
10174             geometry_info.sigma=argument_list[2].real_reference;
10175           if (attribute_flag[3] != 0)
10176             channel=(ChannelType) argument_list[3].integer_reference;
10177           sharpen=MagickTrue;
10178           if (attribute_flag[4] != 0)
10179             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10180               MagickFalse;
10181           channel_mask=SetImageChannelMask(image,channel);
10182           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10183             geometry_info.sigma,exception);
10184           (void) SetImageChannelMask(image,channel_mask);
10185           break;
10186         }
10187         case 93:  /* Extent */
10188         {
10189           if (attribute_flag[7] != 0)
10190             image->gravity=(GravityType) argument_list[7].integer_reference;
10191           if (attribute_flag[0] != 0)
10192             {
10193               int
10194                 flags;
10195
10196               flags=ParseGravityGeometry(image,
10197                 argument_list[0].string_reference,&geometry,exception);
10198               (void) flags;
10199               if (geometry.width == 0)
10200                 geometry.width=image->columns;
10201               if (geometry.height == 0)
10202                 geometry.height=image->rows;
10203             }
10204           if (attribute_flag[1] != 0)
10205             geometry.width=argument_list[1].integer_reference;
10206           if (attribute_flag[2] != 0)
10207             geometry.height=argument_list[2].integer_reference;
10208           if (attribute_flag[3] != 0)
10209             geometry.x=argument_list[3].integer_reference;
10210           if (attribute_flag[4] != 0)
10211             geometry.y=argument_list[4].integer_reference;
10212           if (attribute_flag[5] != 0)
10213             image->fuzz=StringToDoubleInterval(
10214               argument_list[5].string_reference,(double) QuantumRange+1.0);
10215           if (attribute_flag[6] != 0)
10216             (void) QueryColorCompliance(argument_list[6].string_reference,
10217               AllCompliance,&image->background_color,exception);
10218           image=ExtentImage(image,&geometry,exception);
10219           break;
10220         }
10221         case 94:  /* Vignette */
10222         {
10223           if (attribute_flag[0] != 0)
10224             {
10225               flags=ParseGeometry(argument_list[0].string_reference,
10226                 &geometry_info);
10227               if ((flags & SigmaValue) == 0)
10228                 geometry_info.sigma=1.0;
10229               if ((flags & XiValue) == 0)
10230                 geometry_info.xi=0.1*image->columns;
10231               if ((flags & PsiValue) == 0)
10232                 geometry_info.psi=0.1*image->rows;
10233             }
10234           if (attribute_flag[1] != 0)
10235             geometry_info.rho=argument_list[1].real_reference;
10236           if (attribute_flag[2] != 0)
10237             geometry_info.sigma=argument_list[2].real_reference;
10238           if (attribute_flag[3] != 0)
10239             geometry_info.xi=argument_list[3].integer_reference;
10240           if (attribute_flag[4] != 0)
10241             geometry_info.psi=argument_list[4].integer_reference;
10242           if (attribute_flag[5] != 0)
10243             (void) QueryColorCompliance(argument_list[5].string_reference,
10244               AllCompliance,&image->background_color,exception);
10245           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10246             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10247             ceil(geometry_info.psi-0.5),exception);
10248           break;
10249         }
10250         case 95:  /* ContrastStretch */
10251         {
10252           double
10253             black_point,
10254             white_point;
10255
10256           black_point=0.0;
10257           white_point=(double) image->columns*image->rows;
10258           if (attribute_flag[0] != 0)
10259             {
10260               flags=ParseGeometry(argument_list[0].string_reference,
10261                 &geometry_info);
10262               black_point=geometry_info.rho;
10263               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10264                 black_point;
10265               if ((flags & PercentValue) != 0)
10266                 {
10267                   black_point*=(double) image->columns*image->rows/100.0;
10268                   white_point*=(double) image->columns*image->rows/100.0;
10269                 }
10270               white_point=(double) image->columns*image->rows-
10271                 white_point;
10272             }
10273           if (attribute_flag[1] != 0)
10274             black_point=argument_list[1].real_reference;
10275           if (attribute_flag[2] != 0)
10276             white_point=argument_list[2].real_reference;
10277           if (attribute_flag[4] != 0)
10278             channel=(ChannelType) argument_list[4].integer_reference;
10279           channel_mask=SetImageChannelMask(image,channel);
10280           (void) ContrastStretchImage(image,black_point,white_point,exception);
10281           (void) SetImageChannelMask(image,channel_mask);
10282           break;
10283         }
10284         case 96:  /* Sans0 */
10285         {
10286           break;
10287         }
10288         case 97:  /* Sans1 */
10289         {
10290           break;
10291         }
10292         case 98:  /* AdaptiveSharpen */
10293         {
10294           if (attribute_flag[0] != 0)
10295             {
10296               flags=ParseGeometry(argument_list[0].string_reference,
10297                 &geometry_info);
10298               if ((flags & SigmaValue) == 0)
10299                 geometry_info.sigma=1.0;
10300               if ((flags & XiValue) == 0)
10301                 geometry_info.xi=0.0;
10302             }
10303           if (attribute_flag[1] != 0)
10304             geometry_info.rho=argument_list[1].real_reference;
10305           if (attribute_flag[2] != 0)
10306             geometry_info.sigma=argument_list[2].real_reference;
10307           if (attribute_flag[3] != 0)
10308             geometry_info.xi=argument_list[3].real_reference;
10309           if (attribute_flag[4] != 0)
10310             channel=(ChannelType) argument_list[4].integer_reference;
10311           channel_mask=SetImageChannelMask(image,channel);
10312           image=AdaptiveSharpenImage(image,geometry_info.rho,
10313             geometry_info.sigma,exception);
10314           if (image != (Image *) NULL)
10315             (void) SetImageChannelMask(image,channel_mask);
10316           break;
10317         }
10318         case 99:  /* Transpose */
10319         {
10320           image=TransposeImage(image,exception);
10321           break;
10322         }
10323         case 100:  /* Tranverse */
10324         {
10325           image=TransverseImage(image,exception);
10326           break;
10327         }
10328         case 101:  /* AutoOrient */
10329         {
10330           image=AutoOrientImage(image,image->orientation,exception);
10331           break;
10332         }
10333         case 102:  /* AdaptiveBlur */
10334         {
10335           if (attribute_flag[0] != 0)
10336             {
10337               flags=ParseGeometry(argument_list[0].string_reference,
10338                 &geometry_info);
10339               if ((flags & SigmaValue) == 0)
10340                 geometry_info.sigma=1.0;
10341               if ((flags & XiValue) == 0)
10342                 geometry_info.xi=0.0;
10343             }
10344           if (attribute_flag[1] != 0)
10345             geometry_info.rho=argument_list[1].real_reference;
10346           if (attribute_flag[2] != 0)
10347             geometry_info.sigma=argument_list[2].real_reference;
10348           if (attribute_flag[3] != 0)
10349             channel=(ChannelType) argument_list[3].integer_reference;
10350           channel_mask=SetImageChannelMask(image,channel);
10351           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10352             exception);
10353           if (image != (Image *) NULL)
10354             (void) SetImageChannelMask(image,channel_mask);
10355           break;
10356         }
10357         case 103:  /* Sketch */
10358         {
10359           if (attribute_flag[0] != 0)
10360             {
10361               flags=ParseGeometry(argument_list[0].string_reference,
10362                 &geometry_info);
10363               if ((flags & SigmaValue) == 0)
10364                 geometry_info.sigma=1.0;
10365               if ((flags & XiValue) == 0)
10366                 geometry_info.xi=1.0;
10367             }
10368           if (attribute_flag[1] != 0)
10369             geometry_info.rho=argument_list[1].real_reference;
10370           if (attribute_flag[2] != 0)
10371             geometry_info.sigma=argument_list[2].real_reference;
10372           if (attribute_flag[3] != 0)
10373             geometry_info.xi=argument_list[3].real_reference;
10374           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10375             geometry_info.xi,exception);
10376           break;
10377         }
10378         case 104:  /* UniqueColors */
10379         {
10380           image=UniqueImageColors(image,exception);
10381           break;
10382         }
10383         case 105:  /* AdaptiveResize */
10384         {
10385           if (attribute_flag[0] != 0)
10386             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10387               &geometry,exception);
10388           if (attribute_flag[1] != 0)
10389             geometry.width=argument_list[1].integer_reference;
10390           if (attribute_flag[2] != 0)
10391             geometry.height=argument_list[2].integer_reference;
10392           if (attribute_flag[3] != 0)
10393             image->filter=(FilterTypes) argument_list[4].integer_reference;
10394           if (attribute_flag[4] != 0)
10395             SetImageArtifact(image,"filter:support",
10396               argument_list[4].string_reference);
10397           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10398             exception);
10399           break;
10400         }
10401         case 106:  /* ClipMask */
10402         {
10403           Image
10404             *mask_image;
10405
10406           if (attribute_flag[0] == 0)
10407             {
10408               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10409                 PackageName);
10410               goto PerlException;
10411             }
10412           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10413             exception);
10414           (void) SetImageMask(image,mask_image,exception);
10415           mask_image=DestroyImage(mask_image);
10416           break;
10417         }
10418         case 107:  /* LinearStretch */
10419         {
10420            double
10421              black_point,
10422              white_point;
10423
10424            black_point=0.0;
10425            white_point=(double) image->columns*image->rows;
10426            if (attribute_flag[0] != 0)
10427              {
10428                flags=ParseGeometry(argument_list[0].string_reference,
10429                  &geometry_info);
10430                if ((flags & SigmaValue) != 0)
10431                   white_point=geometry_info.sigma;
10432                if ((flags & PercentValue) != 0)
10433                  {
10434                    black_point*=(double) image->columns*image->rows/100.0;
10435                    white_point*=(double) image->columns*image->rows/100.0;
10436                  }
10437                if ((flags & SigmaValue) == 0)
10438                  white_point=(double) image->columns*image->rows-black_point;
10439              }
10440           if (attribute_flag[1] != 0)
10441             black_point=argument_list[1].real_reference;
10442           if (attribute_flag[2] != 0)
10443             white_point=argument_list[2].real_reference;
10444           (void) LinearStretchImage(image,black_point,white_point,exception);
10445           break;
10446         }
10447         case 108:  /* ColorMatrix */
10448         {
10449           AV
10450             *av;
10451
10452           double
10453             *color_matrix;
10454
10455           KernelInfo
10456             *kernel_info;
10457
10458           size_t
10459             order;
10460
10461           if (attribute_flag[0] == 0)
10462             break;
10463           av=(AV *) argument_list[0].array_reference;
10464           order=(size_t) sqrt(av_len(av)+1);
10465           color_matrix=(double *) AcquireQuantumMemory(order,order*
10466             sizeof(*color_matrix));
10467           if (color_matrix == (double *) NULL)
10468             {
10469               ThrowPerlException(exception,ResourceLimitFatalError,
10470                 "MemoryAllocationFailed",PackageName);
10471               goto PerlException;
10472            }
10473           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10474             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10475           for ( ; j < (ssize_t) (order*order); j++)
10476             color_matrix[j]=0.0;
10477           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10478           if (kernel_info == (KernelInfo *) NULL)
10479             break;
10480           kernel_info->width=order;
10481           kernel_info->height=order;
10482           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10483             order*sizeof(*kernel_info->values));
10484           if (kernel_info->values != (MagickRealType *) NULL)
10485             {
10486               for (i=0; i < (ssize_t) (order*order); i++)
10487                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10488               image=ColorMatrixImage(image,kernel_info,exception);
10489             }
10490           kernel_info=DestroyKernelInfo(kernel_info);
10491           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10492           break;
10493         }
10494         case 109:  /* Mask */
10495         {
10496           Image
10497             *mask_image;
10498
10499           if (attribute_flag[0] == 0)
10500             {
10501               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10502                 PackageName);
10503               goto PerlException;
10504             }
10505           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10506             MagickTrue,exception);
10507           (void) SetImageMask(image,mask_image,exception);
10508           mask_image=DestroyImage(mask_image);
10509           break;
10510         }
10511         case 110:  /* Polaroid */
10512         {
10513           char
10514             *caption;
10515
10516           DrawInfo
10517             *draw_info;
10518
10519           double
10520             angle;
10521
10522           PixelInterpolateMethod
10523             method;
10524
10525           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10526             (DrawInfo *) NULL);
10527           caption=(char *) NULL;
10528           if (attribute_flag[0] != 0)
10529             caption=InterpretImageProperties(info ? info->image_info :
10530               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10531               exception);
10532           angle=0.0;
10533           if (attribute_flag[1] != 0)
10534             angle=argument_list[1].real_reference;
10535           if (attribute_flag[2] != 0)
10536             (void) CloneString(&draw_info->font,
10537               argument_list[2].string_reference);
10538           if (attribute_flag[3] != 0)
10539             (void) QueryColorCompliance(argument_list[3].string_reference,
10540               AllCompliance,&draw_info->stroke,exception);
10541           if (attribute_flag[4] != 0)
10542             (void) QueryColorCompliance(argument_list[4].string_reference,
10543               AllCompliance,&draw_info->fill,exception);
10544           if (attribute_flag[5] != 0)
10545             draw_info->stroke_width=argument_list[5].real_reference;
10546           if (attribute_flag[6] != 0)
10547             draw_info->pointsize=argument_list[6].real_reference;
10548           if (attribute_flag[7] != 0)
10549             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10550           if (attribute_flag[8] != 0)
10551             (void) QueryColorCompliance(argument_list[8].string_reference,
10552               AllCompliance,&image->background_color,exception);
10553           method=UndefinedInterpolatePixel;
10554           if (attribute_flag[9] != 0)
10555             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10556           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10557           draw_info=DestroyDrawInfo(draw_info);
10558           if (caption != (char *) NULL)
10559             caption=DestroyString(caption);
10560           break;
10561         }
10562         case 111:  /* FloodfillPaint */
10563         {
10564           DrawInfo
10565             *draw_info;
10566
10567           MagickBooleanType
10568             invert;
10569
10570           PixelInfo
10571             target;
10572
10573           draw_info=CloneDrawInfo(info ? info->image_info :
10574             (ImageInfo *) NULL,(DrawInfo *) NULL);
10575           if (attribute_flag[0] != 0)
10576             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10577               &geometry,exception);
10578           if (attribute_flag[1] != 0)
10579             geometry.x=argument_list[1].integer_reference;
10580           if (attribute_flag[2] != 0)
10581             geometry.y=argument_list[2].integer_reference;
10582           if (attribute_flag[3] != 0)
10583             (void) QueryColorCompliance(argument_list[3].string_reference,
10584               AllCompliance,&draw_info->fill,exception);
10585           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10586             geometry.x,geometry.y,&target,exception);
10587           if (attribute_flag[4] != 0)
10588             QueryColorCompliance(argument_list[4].string_reference,
10589               AllCompliance,&target,exception);
10590           if (attribute_flag[5] != 0)
10591             image->fuzz=StringToDoubleInterval(
10592               argument_list[5].string_reference,(double) QuantumRange+1.0);
10593           if (attribute_flag[6] != 0)
10594             channel=(ChannelType) argument_list[6].integer_reference;
10595           invert=MagickFalse;
10596           if (attribute_flag[7] != 0)
10597             invert=(MagickBooleanType) argument_list[7].integer_reference;
10598           channel_mask=SetImageChannelMask(image,channel);
10599           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10600             geometry.y,invert,exception);
10601           (void) SetImageChannelMask(image,channel_mask);
10602           draw_info=DestroyDrawInfo(draw_info);
10603           break;
10604         }
10605         case 112:  /* Distort */
10606         {
10607           AV
10608             *av;
10609
10610           double
10611             *coordinates;
10612
10613           DistortImageMethod
10614             method;
10615
10616           size_t
10617             number_coordinates;
10618
10619           VirtualPixelMethod
10620             virtual_pixel;
10621
10622           if (attribute_flag[0] == 0)
10623             break;
10624           method=UndefinedDistortion;
10625           if (attribute_flag[1] != 0)
10626             method=(DistortImageMethod) argument_list[1].integer_reference;
10627           av=(AV *) argument_list[0].array_reference;
10628           number_coordinates=(size_t) av_len(av)+1;
10629           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10630             sizeof(*coordinates));
10631           if (coordinates == (double *) NULL)
10632             {
10633               ThrowPerlException(exception,ResourceLimitFatalError,
10634                 "MemoryAllocationFailed",PackageName);
10635               goto PerlException;
10636             }
10637           for (j=0; j < (ssize_t) number_coordinates; j++)
10638             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10639           virtual_pixel=UndefinedVirtualPixelMethod;
10640           if (attribute_flag[2] != 0)
10641             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10642               argument_list[2].integer_reference,exception);
10643           image=DistortImage(image,method,number_coordinates,coordinates,
10644             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10645             exception);
10646           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10647             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10648               exception);
10649           coordinates=(double *) RelinquishMagickMemory(coordinates);
10650           break;
10651         }
10652         case 113:  /* Clut */
10653         {
10654           PixelInterpolateMethod
10655             method;
10656
10657           if (attribute_flag[0] == 0)
10658             {
10659               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10660                 PackageName);
10661               goto PerlException;
10662             }
10663           method=UndefinedInterpolatePixel;
10664           if (attribute_flag[1] != 0)
10665             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10666           if (attribute_flag[2] != 0)
10667             channel=(ChannelType) argument_list[2].integer_reference;
10668           channel_mask=SetImageChannelMask(image,channel);
10669           (void) ClutImage(image,argument_list[0].image_reference,method,
10670             exception);
10671           (void) SetImageChannelMask(image,channel_mask);
10672           break;
10673         }
10674         case 114:  /* LiquidRescale */
10675         {
10676           if (attribute_flag[0] != 0)
10677             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10678               &geometry,exception);
10679           if (attribute_flag[1] != 0)
10680             geometry.width=argument_list[1].integer_reference;
10681           if (attribute_flag[2] != 0)
10682             geometry.height=argument_list[2].integer_reference;
10683           if (attribute_flag[3] == 0)
10684             argument_list[3].real_reference=1.0;
10685           if (attribute_flag[4] == 0)
10686             argument_list[4].real_reference=0.0;
10687           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10688             argument_list[3].real_reference,argument_list[4].real_reference,
10689             exception);
10690           break;
10691         }
10692         case 115:  /* EncipherImage */
10693         {
10694           (void) EncipherImage(image,argument_list[0].string_reference,
10695             exception);
10696           break;
10697         }
10698         case 116:  /* DecipherImage */
10699         {
10700           (void) DecipherImage(image,argument_list[0].string_reference,
10701             exception);
10702           break;
10703         }
10704         case 117:  /* Deskew */
10705         {
10706           geometry_info.rho=QuantumRange/2.0;
10707           if (attribute_flag[0] != 0)
10708             flags=ParseGeometry(argument_list[0].string_reference,
10709               &geometry_info);
10710           if (attribute_flag[1] != 0)
10711             geometry_info.rho=StringToDoubleInterval(
10712               argument_list[1].string_reference,(double) QuantumRange+1.0);
10713           image=DeskewImage(image,geometry_info.rho,exception);
10714           break;
10715         }
10716         case 118:  /* Remap */
10717         {
10718           QuantizeInfo
10719             *quantize_info;
10720
10721           if (attribute_flag[0] == 0)
10722             {
10723               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10724                 PackageName);
10725               goto PerlException;
10726             }
10727           quantize_info=AcquireQuantizeInfo(info->image_info);
10728           if (attribute_flag[1] != 0)
10729             quantize_info->dither_method=(DitherMethod)
10730               argument_list[1].integer_reference;
10731           (void) RemapImages(quantize_info,image,
10732             argument_list[0].image_reference,exception);
10733           quantize_info=DestroyQuantizeInfo(quantize_info);
10734           break;
10735         }
10736         case 119:  /* SparseColor */
10737         {
10738           AV
10739             *av;
10740
10741           double
10742             *coordinates;
10743
10744           SparseColorMethod
10745             method;
10746
10747           size_t
10748             number_coordinates;
10749
10750           VirtualPixelMethod
10751             virtual_pixel;
10752
10753           if (attribute_flag[0] == 0)
10754             break;
10755           method=UndefinedColorInterpolate;
10756           if (attribute_flag[1] != 0)
10757             method=(SparseColorMethod) argument_list[1].integer_reference;
10758           av=(AV *) argument_list[0].array_reference;
10759           number_coordinates=(size_t) av_len(av)+1;
10760           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10761             sizeof(*coordinates));
10762           if (coordinates == (double *) NULL)
10763             {
10764               ThrowPerlException(exception,ResourceLimitFatalError,
10765                 "MemoryAllocationFailed",PackageName);
10766               goto PerlException;
10767             }
10768           for (j=0; j < (ssize_t) number_coordinates; j++)
10769             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10770           virtual_pixel=UndefinedVirtualPixelMethod;
10771           if (attribute_flag[2] != 0)
10772             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10773               argument_list[2].integer_reference,exception);
10774           if (attribute_flag[3] != 0)
10775             channel=(ChannelType) argument_list[3].integer_reference;
10776           channel_mask=SetImageChannelMask(image,channel);
10777           image=SparseColorImage(image,method,number_coordinates,coordinates,
10778             exception);
10779           if (image != (Image *) NULL)
10780             (void) SetImageChannelMask(image,channel_mask);
10781           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10782             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10783               exception);
10784           coordinates=(double *) RelinquishMagickMemory(coordinates);
10785           break;
10786         }
10787         case 120:  /* Function */
10788         {
10789           AV
10790             *av;
10791
10792           double
10793             *parameters;
10794
10795           MagickFunction
10796             function;
10797
10798           size_t
10799             number_parameters;
10800
10801           VirtualPixelMethod
10802             virtual_pixel;
10803
10804           if (attribute_flag[0] == 0)
10805             break;
10806           function=UndefinedFunction;
10807           if (attribute_flag[1] != 0)
10808             function=(MagickFunction) argument_list[1].integer_reference;
10809           av=(AV *) argument_list[0].array_reference;
10810           number_parameters=(size_t) av_len(av)+1;
10811           parameters=(double *) AcquireQuantumMemory(number_parameters,
10812             sizeof(*parameters));
10813           if (parameters == (double *) NULL)
10814             {
10815               ThrowPerlException(exception,ResourceLimitFatalError,
10816                 "MemoryAllocationFailed",PackageName);
10817               goto PerlException;
10818             }
10819           for (j=0; j < (ssize_t) number_parameters; j++)
10820             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10821           virtual_pixel=UndefinedVirtualPixelMethod;
10822           if (attribute_flag[2] != 0)
10823             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10824               argument_list[2].integer_reference,exception);
10825           (void) FunctionImage(image,function,number_parameters,parameters,
10826             exception);
10827           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10828             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10829               exception);
10830           parameters=(double *) RelinquishMagickMemory(parameters);
10831           break;
10832         }
10833         case 121:  /* SelectiveBlur */
10834         {
10835           if (attribute_flag[0] != 0)
10836             {
10837               flags=ParseGeometry(argument_list[0].string_reference,
10838                 &geometry_info);
10839               if ((flags & SigmaValue) == 0)
10840                 geometry_info.sigma=1.0;
10841               if ((flags & PercentValue) != 0)
10842                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10843             }
10844           if (attribute_flag[1] != 0)
10845             geometry_info.rho=argument_list[1].real_reference;
10846           if (attribute_flag[2] != 0)
10847             geometry_info.sigma=argument_list[2].real_reference;
10848           if (attribute_flag[3] != 0)
10849             geometry_info.xi=argument_list[3].integer_reference;;
10850           if (attribute_flag[5] != 0)
10851             channel=(ChannelType) argument_list[5].integer_reference;
10852           channel_mask=SetImageChannelMask(image,channel);
10853           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10854             geometry_info.xi,exception);
10855           if (image != (Image *) NULL)
10856             (void) SetImageChannelMask(image,channel_mask);
10857           break;
10858         }
10859         case 122:  /* HaldClut */
10860         {
10861           if (attribute_flag[0] == 0)
10862             {
10863               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10864                 PackageName);
10865               goto PerlException;
10866             }
10867           if (attribute_flag[1] != 0)
10868             channel=(ChannelType) argument_list[1].integer_reference;
10869           channel_mask=SetImageChannelMask(image,channel);
10870           (void) HaldClutImage(image,argument_list[0].image_reference,
10871             exception);
10872           (void) SetImageChannelMask(image,channel_mask);
10873           break;
10874         }
10875         case 123:  /* BlueShift */
10876         {
10877           if (attribute_flag[0] != 0)
10878             (void) ParseGeometry(argument_list[0].string_reference,
10879               &geometry_info);
10880           image=BlueShiftImage(image,geometry_info.rho,exception);
10881           break;
10882         }
10883         case 124:  /* ForwardFourierTransformImage */
10884         {
10885           image=ForwardFourierTransformImage(image,
10886             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10887             exception);
10888           break;
10889         }
10890         case 125:  /* InverseFourierTransformImage */
10891         {
10892           image=InverseFourierTransformImage(image,image->next,
10893             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10894             exception);
10895           break;
10896         }
10897         case 126:  /* ColorDecisionList */
10898         {
10899           if (attribute_flag[0] == 0)
10900             argument_list[0].string_reference=(char *) NULL;
10901           (void) ColorDecisionListImage(image,
10902             argument_list[0].string_reference,exception);
10903           break;
10904         }
10905         case 127:  /* AutoGamma */
10906         {
10907           if (attribute_flag[0] != 0)
10908             channel=(ChannelType) argument_list[0].integer_reference;
10909           channel_mask=SetImageChannelMask(image,channel);
10910           (void) AutoGammaImage(image,exception);
10911           (void) SetImageChannelMask(image,channel_mask);
10912           break;
10913         }
10914         case 128:  /* AutoLevel */
10915         {
10916           if (attribute_flag[0] != 0)
10917             channel=(ChannelType) argument_list[0].integer_reference;
10918           channel_mask=SetImageChannelMask(image,channel);
10919           (void) AutoLevelImage(image,exception);
10920           (void) SetImageChannelMask(image,channel_mask);
10921           break;
10922         }
10923         case 129:  /* LevelColors */
10924         {
10925           PixelInfo
10926             black_point,
10927             white_point;
10928
10929           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10930             exception);
10931           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10932             exception);
10933           if (attribute_flag[1] != 0)
10934              (void) QueryColorCompliance(
10935                argument_list[1].string_reference,AllCompliance,&black_point,
10936                exception);
10937           if (attribute_flag[2] != 0)
10938              (void) QueryColorCompliance(
10939                argument_list[2].string_reference,AllCompliance,&white_point,
10940                exception);
10941           if (attribute_flag[3] != 0)
10942             channel=(ChannelType) argument_list[3].integer_reference;
10943           channel_mask=SetImageChannelMask(image,channel);
10944           (void) LevelImageColors(image,&black_point,&white_point,
10945             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10946             exception);
10947           (void) SetImageChannelMask(image,channel_mask);
10948           break;
10949         }
10950         case 130:  /* Clamp */
10951         {
10952           if (attribute_flag[0] != 0)
10953             channel=(ChannelType) argument_list[0].integer_reference;
10954           channel_mask=SetImageChannelMask(image,channel);
10955           (void) ClampImage(image,exception);
10956           (void) SetImageChannelMask(image,channel_mask);
10957           break;
10958         }
10959         case 131:  /* BrightnessContrast */
10960         {
10961           double
10962             brightness,
10963             contrast;
10964
10965           brightness=0.0;
10966           contrast=0.0;
10967           if (attribute_flag[0] != 0)
10968             {
10969               flags=ParseGeometry(argument_list[0].string_reference,
10970                 &geometry_info);
10971               brightness=geometry_info.rho;
10972               if ((flags & SigmaValue) == 0)
10973                 contrast=geometry_info.sigma;
10974             }
10975           if (attribute_flag[1] != 0)
10976             brightness=argument_list[1].real_reference;
10977           if (attribute_flag[2] != 0)
10978             contrast=argument_list[2].real_reference;
10979           if (attribute_flag[4] != 0)
10980             channel=(ChannelType) argument_list[4].integer_reference;
10981           channel_mask=SetImageChannelMask(image,channel);
10982           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10983           (void) SetImageChannelMask(image,channel_mask);
10984           break;
10985         }
10986         case 132:  /* Morphology */
10987         {
10988           KernelInfo
10989             *kernel;
10990
10991           MorphologyMethod
10992             method;
10993
10994           ssize_t
10995             iterations;
10996
10997           if (attribute_flag[0] == 0)
10998             break;
10999           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11000           if (kernel == (KernelInfo *) NULL)
11001             break;
11002           if (attribute_flag[1] != 0)
11003             channel=(ChannelType) argument_list[1].integer_reference;
11004           method=UndefinedMorphology;
11005           if (attribute_flag[2] != 0)
11006             method=argument_list[2].integer_reference;
11007           iterations=1;
11008           if (attribute_flag[3] != 0)
11009             iterations=argument_list[3].integer_reference;
11010           channel_mask=SetImageChannelMask(image,channel);
11011           image=MorphologyImage(image,method,iterations,kernel,exception);
11012           if (image != (Image *) NULL)
11013             (void) SetImageChannelMask(image,channel_mask);
11014           kernel=DestroyKernelInfo(kernel);
11015           break;
11016         }
11017         case 133:  /* Mode */
11018         {
11019           if (attribute_flag[0] != 0)
11020             {
11021               flags=ParseGeometry(argument_list[0].string_reference,
11022                 &geometry_info);
11023               if ((flags & SigmaValue) == 0)
11024                 geometry_info.sigma=1.0;
11025             }
11026           if (attribute_flag[1] != 0)
11027             geometry_info.rho=argument_list[1].real_reference;
11028           if (attribute_flag[2] != 0)
11029             geometry_info.sigma=argument_list[2].real_reference;
11030           if (attribute_flag[3] != 0)
11031             channel=(ChannelType) argument_list[3].integer_reference;
11032           channel_mask=SetImageChannelMask(image,channel);
11033           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11034             (size_t) geometry_info.sigma,exception);
11035           if (image != (Image *) NULL)
11036             (void) SetImageChannelMask(image,channel_mask);
11037           break;
11038         }
11039         case 134:  /* Statistic */
11040         {
11041           StatisticType
11042             statistic;
11043
11044           statistic=UndefinedStatistic;
11045           if (attribute_flag[0] != 0)
11046             {
11047               flags=ParseGeometry(argument_list[0].string_reference,
11048                 &geometry_info);
11049               if ((flags & SigmaValue) == 0)
11050                 geometry_info.sigma=1.0;
11051             }
11052           if (attribute_flag[1] != 0)
11053             geometry_info.rho=argument_list[1].real_reference;
11054           if (attribute_flag[2] != 0)
11055             geometry_info.sigma=argument_list[2].real_reference;
11056           if (attribute_flag[3] != 0)
11057             channel=(ChannelType) argument_list[3].integer_reference;
11058           if (attribute_flag[4] != 0)
11059             statistic=(StatisticType) argument_list[4].integer_reference;
11060           channel_mask=SetImageChannelMask(image,channel);
11061           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11062             (size_t) geometry_info.sigma,exception);
11063           if (image != (Image *) NULL)
11064             (void) SetImageChannelMask(image,channel_mask);
11065           break;
11066         }
11067         case 135:  /* Perceptible */
11068         {
11069           double
11070             epsilon;
11071
11072           epsilon=MagickEpsilon;
11073           if (attribute_flag[0] != 0)
11074             epsilon=argument_list[0].real_reference;
11075           if (attribute_flag[1] != 0)
11076             channel=(ChannelType) argument_list[1].integer_reference;
11077           channel_mask=SetImageChannelMask(image,channel);
11078           (void) PerceptibleImage(image,epsilon,exception);
11079           (void) SetImageChannelMask(image,channel_mask);
11080           break;
11081         }
11082         case 136:  /* Poly */
11083         {
11084           AV
11085             *av;
11086
11087           double
11088             *terms;
11089
11090           size_t
11091             number_terms;
11092
11093           if (attribute_flag[0] == 0)
11094             break;
11095           if (attribute_flag[1] != 0)
11096             channel=(ChannelType) argument_list[1].integer_reference;
11097           av=(AV *) argument_list[0].array_reference;
11098           number_terms=(size_t) av_len(av);
11099           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11100           if (terms == (double *) NULL)
11101             {
11102               ThrowPerlException(exception,ResourceLimitFatalError,
11103                 "MemoryAllocationFailed",PackageName);
11104               goto PerlException;
11105             }
11106           for (j=0; j < av_len(av); j++)
11107             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11108           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11109           terms=(double *) RelinquishMagickMemory(terms);
11110           break;
11111         }
11112         case 137:  /* Grayscale */
11113         {
11114           PixelIntensityMethod
11115             method;
11116
11117           method=UndefinedPixelIntensityMethod;
11118           if (attribute_flag[0] != 0)
11119             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11120           (void) GrayscaleImage(image,method,exception);
11121           break;
11122         }
11123         case 138:  /* Canny */
11124         {
11125           if (attribute_flag[0] != 0)
11126             {
11127               flags=ParseGeometry(argument_list[0].string_reference,
11128                 &geometry_info);
11129               if ((flags & SigmaValue) == 0)
11130                 geometry_info.sigma=1.0;
11131               if ((flags & XiValue) == 0)
11132                 geometry_info.xi=0.10;
11133               if ((flags & PsiValue) == 0)
11134                 geometry_info.psi=0.30;
11135               if ((flags & PercentValue) != 0)
11136                 {
11137                   geometry_info.xi/=100.0;
11138                   geometry_info.psi/=100.0;
11139                 }
11140             }
11141           if (attribute_flag[1] != 0)
11142             geometry_info.rho=argument_list[1].real_reference;
11143           if (attribute_flag[2] != 0)
11144             geometry_info.sigma=argument_list[2].real_reference;
11145           if (attribute_flag[3] != 0)
11146             geometry_info.xi=argument_list[3].real_reference;
11147           if (attribute_flag[4] != 0)
11148             geometry_info.psi=argument_list[4].real_reference;
11149           if (attribute_flag[5] != 0)
11150             channel=(ChannelType) argument_list[5].integer_reference;
11151           channel_mask=SetImageChannelMask(image,channel);
11152           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11153             geometry_info.xi,geometry_info.psi,exception);
11154           if (image != (Image *) NULL)
11155             (void) SetImageChannelMask(image,channel_mask);
11156           break;
11157         }
11158         case 139:  /* HoughLine */
11159         {
11160           if (attribute_flag[0] != 0)
11161             {
11162               flags=ParseGeometry(argument_list[0].string_reference,
11163                 &geometry_info);
11164               if ((flags & SigmaValue) == 0)
11165                 geometry_info.sigma=geometry_info.rho;
11166               if ((flags & XiValue) == 0)
11167                 geometry_info.xi=40;
11168             }
11169           if (attribute_flag[1] != 0)
11170             geometry_info.rho=(double) argument_list[1].integer_reference;
11171           if (attribute_flag[2] != 0)
11172             geometry_info.sigma=(double) argument_list[2].integer_reference;
11173           if (attribute_flag[3] != 0)
11174             geometry_info.xi=(double) argument_list[3].integer_reference;
11175           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11176             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11177           break;
11178         }
11179         case 140:  /* MeanShift */
11180         {
11181           if (attribute_flag[0] != 0)
11182             {
11183               flags=ParseGeometry(argument_list[0].string_reference,
11184                 &geometry_info);
11185               if ((flags & SigmaValue) == 0)
11186                 geometry_info.sigma=geometry_info.rho;
11187               if ((flags & PercentValue) != 0)
11188                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11189             }
11190           if (attribute_flag[1] != 0)
11191             geometry_info.rho=(double) argument_list[1].integer_reference;
11192           if (attribute_flag[2] != 0)
11193             geometry_info.sigma=(double) argument_list[2].integer_reference;
11194           if (attribute_flag[3] != 0)
11195             geometry_info.xi=(double) argument_list[3].integer_reference;
11196           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11197             geometry_info.sigma,geometry_info.xi,exception);
11198           break;
11199         }
11200         case 141:  /* Kuwahara */
11201         {
11202           if (attribute_flag[0] != 0)
11203             {
11204               flags=ParseGeometry(argument_list[0].string_reference,
11205                 &geometry_info);
11206               if ((flags & SigmaValue) == 0)
11207                 geometry_info.sigma=geometry_info.rho-0.5;
11208             }
11209           if (attribute_flag[1] != 0)
11210             geometry_info.rho=argument_list[1].real_reference;
11211           if (attribute_flag[2] != 0)
11212             geometry_info.sigma=argument_list[2].real_reference;
11213           if (attribute_flag[3] != 0)
11214             channel=(ChannelType) argument_list[3].integer_reference;
11215           channel_mask=SetImageChannelMask(image,channel);
11216           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11217             exception);
11218           if (image != (Image *) NULL)
11219             (void) SetImageChannelMask(image,channel_mask);
11220           break;
11221         }
11222         case 142:  /* ConnectedComponent */
11223         {
11224           size_t
11225             connectivity;
11226
11227           connectivity=4;
11228           if (attribute_flag[0] != 0)
11229             connectivity=argument_list[0].integer_reference;
11230           image=ConnectedComponentsImage(image,connectivity,exception);
11231           break;
11232         }
11233       }
11234       if (next != (Image *) NULL)
11235         (void) CatchImageException(next);
11236       if (region_image != (Image *) NULL)
11237         {
11238           /*
11239             Composite region.
11240           */
11241           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11242             region_info.x,region_info.y,exception);
11243           (void) status;
11244           (void) CatchImageException(region_image);
11245           image=DestroyImage(image);
11246           image=region_image;
11247         }
11248       if (image != (Image *) NULL)
11249         {
11250           number_images++;
11251           if (next && (next != image))
11252             {
11253               image->next=next->next;
11254               if (image->next != (Image *) NULL)
11255                 image->next->previous=image;
11256               DeleteImageFromRegistry(*pv,next);
11257             }
11258           sv_setiv(*pv,PTR2IV(image));
11259           next=image;
11260         }
11261       if (*pv)
11262         pv++;
11263     }
11264
11265   PerlException:
11266     if (reference_vector)
11267       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11268     InheritPerlException(exception,perl_exception);
11269     exception=DestroyExceptionInfo(exception);
11270     sv_setiv(perl_exception,(IV) number_images);
11271     SvPOK_on(perl_exception);
11272     ST(0)=sv_2mortal(perl_exception);
11273     XSRETURN(1);
11274   }
11275 \f
11276 #
11277 ###############################################################################
11278 #                                                                             #
11279 #                                                                             #
11280 #                                                                             #
11281 #   M o n t a g e                                                             #
11282 #                                                                             #
11283 #                                                                             #
11284 #                                                                             #
11285 ###############################################################################
11286 #
11287 #
11288 void
11289 Montage(ref,...)
11290   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11291   ALIAS:
11292     MontageImage  = 1
11293     montage       = 2
11294     montageimage  = 3
11295   PPCODE:
11296   {
11297     AV
11298       *av;
11299
11300     char
11301       *attribute;
11302
11303     ExceptionInfo
11304       *exception;
11305
11306     HV
11307       *hv;
11308
11309     Image
11310       *image,
11311       *next;
11312
11313     PixelInfo
11314       transparent_color;
11315
11316     MontageInfo
11317       *montage_info;
11318
11319     register ssize_t
11320       i;
11321
11322     ssize_t
11323       sp;
11324
11325     struct PackageInfo
11326       *info;
11327
11328     SV
11329       *av_reference,
11330       *perl_exception,
11331       *reference,
11332       *rv,
11333       *sv;
11334
11335     PERL_UNUSED_VAR(ref);
11336     PERL_UNUSED_VAR(ix);
11337     exception=AcquireExceptionInfo();
11338     perl_exception=newSVpv("",0);
11339     sv=NULL;
11340     attribute=NULL;
11341     if (sv_isobject(ST(0)) == 0)
11342       {
11343         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11344           PackageName);
11345         goto PerlException;
11346       }
11347     reference=SvRV(ST(0));
11348     hv=SvSTASH(reference);
11349     av=newAV();
11350     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11351     SvREFCNT_dec(av);
11352     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11353     if (image == (Image *) NULL)
11354       {
11355         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11356           PackageName);
11357         goto PerlException;
11358       }
11359     /*
11360       Get options.
11361     */
11362     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11363     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11364     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11365       exception);
11366     for (i=2; i < items; i+=2)
11367     {
11368       attribute=(char *) SvPV(ST(i-1),na);
11369       switch (*attribute)
11370       {
11371         case 'B':
11372         case 'b':
11373         {
11374           if (LocaleCompare(attribute,"background") == 0)
11375             {
11376               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11377                 &montage_info->background_color,exception);
11378               for (next=image; next; next=next->next)
11379                 next->background_color=montage_info->background_color;
11380               break;
11381             }
11382           if (LocaleCompare(attribute,"border") == 0)
11383             {
11384               montage_info->border_width=SvIV(ST(i));
11385               break;
11386             }
11387           if (LocaleCompare(attribute,"bordercolor") == 0)
11388             {
11389               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11390                 &montage_info->border_color,exception);
11391               for (next=image; next; next=next->next)
11392                 next->border_color=montage_info->border_color;
11393               break;
11394             }
11395           if (LocaleCompare(attribute,"borderwidth") == 0)
11396             {
11397               montage_info->border_width=SvIV(ST(i));
11398               break;
11399             }
11400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11401             attribute);
11402           break;
11403         }
11404         case 'C':
11405         case 'c':
11406         {
11407           if (LocaleCompare(attribute,"compose") == 0)
11408             {
11409               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11410                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11411               if (sp < 0)
11412                 {
11413                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11414                     SvPV(ST(i),na));
11415                   break;
11416                 }
11417               for (next=image; next; next=next->next)
11418                 next->compose=(CompositeOperator) sp;
11419               break;
11420             }
11421           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11422             attribute);
11423           break;
11424         }
11425         case 'F':
11426         case 'f':
11427         {
11428           if (LocaleCompare(attribute,"fill") == 0)
11429             {
11430               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11431                 &montage_info->fill,exception);
11432               break;
11433             }
11434           if (LocaleCompare(attribute,"font") == 0)
11435             {
11436               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11437               break;
11438             }
11439           if (LocaleCompare(attribute,"frame") == 0)
11440             {
11441               char
11442                 *p;
11443
11444               p=SvPV(ST(i),na);
11445               if (IsGeometry(p) == MagickFalse)
11446                 {
11447                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11448                     p);
11449                   break;
11450                 }
11451               (void) CloneString(&montage_info->frame,p);
11452               if (*p == '\0')
11453                 montage_info->frame=(char *) NULL;
11454               break;
11455             }
11456           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11457             attribute);
11458           break;
11459         }
11460         case 'G':
11461         case 'g':
11462         {
11463           if (LocaleCompare(attribute,"geometry") == 0)
11464             {
11465               char
11466                 *p;
11467
11468               p=SvPV(ST(i),na);
11469               if (IsGeometry(p) == MagickFalse)
11470                 {
11471                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11472                     p);
11473                   break;
11474                 }
11475              (void) CloneString(&montage_info->geometry,p);
11476              if (*p == '\0')
11477                montage_info->geometry=(char *) NULL;
11478              break;
11479            }
11480          if (LocaleCompare(attribute,"gravity") == 0)
11481            {
11482              ssize_t
11483                in;
11484
11485              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11486                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11487              if (in < 0)
11488                {
11489                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11490                    SvPV(ST(i),na));
11491                  return;
11492                }
11493              montage_info->gravity=(GravityType) in;
11494              for (next=image; next; next=next->next)
11495                next->gravity=(GravityType) in;
11496              break;
11497            }
11498           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11499             attribute);
11500           break;
11501         }
11502         case 'L':
11503         case 'l':
11504         {
11505           if (LocaleCompare(attribute,"label") == 0)
11506             {
11507               for (next=image; next; next=next->next)
11508                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11509                   info ? info->image_info : (ImageInfo *) NULL,next,
11510                   SvPV(ST(i),na),exception),exception);
11511               break;
11512             }
11513           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11514             attribute);
11515           break;
11516         }
11517         case 'M':
11518         case 'm':
11519         {
11520           if (LocaleCompare(attribute,"mattecolor") == 0)
11521             {
11522               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11523                 &montage_info->matte_color,exception);
11524               for (next=image; next; next=next->next)
11525                 next->matte_color=montage_info->matte_color;
11526               break;
11527             }
11528           if (LocaleCompare(attribute,"mode") == 0)
11529             {
11530               ssize_t
11531                 in;
11532
11533               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11534                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11535               switch (in)
11536               {
11537                 default:
11538                 {
11539                   ThrowPerlException(exception,OptionError,
11540                     "UnrecognizedModeType",SvPV(ST(i),na));
11541                   break;
11542                 }
11543                 case FrameMode:
11544                 {
11545                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11546                   montage_info->shadow=MagickTrue;
11547                   break;
11548                 }
11549                 case UnframeMode:
11550                 {
11551                   montage_info->frame=(char *) NULL;
11552                   montage_info->shadow=MagickFalse;
11553                   montage_info->border_width=0;
11554                   break;
11555                 }
11556                 case ConcatenateMode:
11557                 {
11558                   montage_info->frame=(char *) NULL;
11559                   montage_info->shadow=MagickFalse;
11560                   (void) CloneString(&montage_info->geometry,"+0+0");
11561                   montage_info->border_width=0;
11562                 }
11563               }
11564               break;
11565             }
11566           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11567             attribute);
11568           break;
11569         }
11570         case 'P':
11571         case 'p':
11572         {
11573           if (LocaleCompare(attribute,"pointsize") == 0)
11574             {
11575               montage_info->pointsize=SvIV(ST(i));
11576               break;
11577             }
11578           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11579             attribute);
11580           break;
11581         }
11582         case 'S':
11583         case 's':
11584         {
11585           if (LocaleCompare(attribute,"shadow") == 0)
11586             {
11587               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11588                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11589               if (sp < 0)
11590                 {
11591                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11592                     SvPV(ST(i),na));
11593                   break;
11594                 }
11595              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11596              break;
11597             }
11598           if (LocaleCompare(attribute,"stroke") == 0)
11599             {
11600               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11601                 &montage_info->stroke,exception);
11602               break;
11603             }
11604           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11605             attribute);
11606           break;
11607         }
11608         case 'T':
11609         case 't':
11610         {
11611           if (LocaleCompare(attribute,"texture") == 0)
11612             {
11613               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11614               break;
11615             }
11616           if (LocaleCompare(attribute,"tile") == 0)
11617             {
11618               char *p=SvPV(ST(i),na);
11619               if (IsGeometry(p) == MagickFalse)
11620                 {
11621                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11622                     p);
11623                   break;
11624                 }
11625               (void) CloneString(&montage_info->tile,p);
11626               if (*p == '\0')
11627                 montage_info->tile=(char *) NULL;
11628               break;
11629             }
11630           if (LocaleCompare(attribute,"title") == 0)
11631             {
11632               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11633               break;
11634             }
11635           if (LocaleCompare(attribute,"transparent") == 0)
11636             {
11637               PixelInfo
11638                 transparent_color;
11639
11640               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11641                 &transparent_color,exception);
11642               for (next=image; next; next=next->next)
11643                 (void) TransparentPaintImage(next,&transparent_color,
11644                   TransparentAlpha,MagickFalse,exception);
11645               break;
11646             }
11647           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11648             attribute);
11649           break;
11650         }
11651         default:
11652         {
11653           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11654             attribute);
11655           break;
11656         }
11657       }
11658     }
11659     image=MontageImageList(info->image_info,montage_info,image,exception);
11660     montage_info=DestroyMontageInfo(montage_info);
11661     if (image == (Image *) NULL)
11662       goto PerlException;
11663     if (transparent_color.alpha != TransparentAlpha)
11664       for (next=image; next; next=next->next)
11665         (void) TransparentPaintImage(next,&transparent_color,
11666           TransparentAlpha,MagickFalse,exception);
11667     for (  ; image; image=image->next)
11668     {
11669       AddImageToRegistry(sv,image);
11670       rv=newRV(sv);
11671       av_push(av,sv_bless(rv,hv));
11672       SvREFCNT_dec(sv);
11673     }
11674     exception=DestroyExceptionInfo(exception);
11675     ST(0)=av_reference;
11676     SvREFCNT_dec(perl_exception);
11677     XSRETURN(1);
11678
11679   PerlException:
11680     InheritPerlException(exception,perl_exception);
11681     exception=DestroyExceptionInfo(exception);
11682     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11683     SvPOK_on(perl_exception);
11684     ST(0)=sv_2mortal(perl_exception);
11685     XSRETURN(1);
11686   }
11687 \f
11688 #
11689 ###############################################################################
11690 #                                                                             #
11691 #                                                                             #
11692 #                                                                             #
11693 #   M o r p h                                                                 #
11694 #                                                                             #
11695 #                                                                             #
11696 #                                                                             #
11697 ###############################################################################
11698 #
11699 #
11700 void
11701 Morph(ref,...)
11702   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11703   ALIAS:
11704     MorphImage  = 1
11705     morph       = 2
11706     morphimage  = 3
11707   PPCODE:
11708   {
11709     AV
11710       *av;
11711
11712     char
11713       *attribute;
11714
11715     ExceptionInfo
11716       *exception;
11717
11718     HV
11719       *hv;
11720
11721     Image
11722       *image;
11723
11724     register ssize_t
11725       i;
11726
11727     ssize_t
11728       number_frames;
11729
11730     struct PackageInfo
11731       *info;
11732
11733     SV
11734       *av_reference,
11735       *perl_exception,
11736       *reference,
11737       *rv,
11738       *sv;
11739
11740     PERL_UNUSED_VAR(ref);
11741     PERL_UNUSED_VAR(ix);
11742     exception=AcquireExceptionInfo();
11743     perl_exception=newSVpv("",0);
11744     sv=NULL;
11745     av=NULL;
11746     attribute=NULL;
11747     if (sv_isobject(ST(0)) == 0)
11748       {
11749         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11750           PackageName);
11751         goto PerlException;
11752       }
11753     reference=SvRV(ST(0));
11754     hv=SvSTASH(reference);
11755     av=newAV();
11756     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11757     SvREFCNT_dec(av);
11758     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11759     if (image == (Image *) NULL)
11760       {
11761         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11762           PackageName);
11763         goto PerlException;
11764       }
11765     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11766     /*
11767       Get attribute.
11768     */
11769     number_frames=30;
11770     for (i=2; i < items; i+=2)
11771     {
11772       attribute=(char *) SvPV(ST(i-1),na);
11773       switch (*attribute)
11774       {
11775         case 'F':
11776         case 'f':
11777         {
11778           if (LocaleCompare(attribute,"frames") == 0)
11779             {
11780               number_frames=SvIV(ST(i));
11781               break;
11782             }
11783           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11784             attribute);
11785           break;
11786         }
11787         default:
11788         {
11789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11790             attribute);
11791           break;
11792         }
11793       }
11794     }
11795     image=MorphImages(image,number_frames,exception);
11796     if (image == (Image *) NULL)
11797       goto PerlException;
11798     for ( ; image; image=image->next)
11799     {
11800       AddImageToRegistry(sv,image);
11801       rv=newRV(sv);
11802       av_push(av,sv_bless(rv,hv));
11803       SvREFCNT_dec(sv);
11804     }
11805     exception=DestroyExceptionInfo(exception);
11806     ST(0)=av_reference;
11807     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11808     XSRETURN(1);
11809
11810   PerlException:
11811     InheritPerlException(exception,perl_exception);
11812     exception=DestroyExceptionInfo(exception);
11813     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11814     SvPOK_on(perl_exception);
11815     ST(0)=sv_2mortal(perl_exception);
11816     XSRETURN(1);
11817   }
11818 \f
11819 #
11820 ###############################################################################
11821 #                                                                             #
11822 #                                                                             #
11823 #                                                                             #
11824 #   M o s a i c                                                               #
11825 #                                                                             #
11826 #                                                                             #
11827 #                                                                             #
11828 ###############################################################################
11829 #
11830 #
11831 void
11832 Mosaic(ref)
11833   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11834   ALIAS:
11835     MosaicImage   = 1
11836     mosaic        = 2
11837     mosaicimage   = 3
11838   PPCODE:
11839   {
11840     AV
11841       *av;
11842
11843     ExceptionInfo
11844       *exception;
11845
11846     HV
11847       *hv;
11848
11849     Image
11850       *image;
11851
11852     struct PackageInfo
11853       *info;
11854
11855     SV
11856       *perl_exception,
11857       *reference,
11858       *rv,
11859       *sv;
11860
11861     PERL_UNUSED_VAR(ref);
11862     PERL_UNUSED_VAR(ix);
11863     exception=AcquireExceptionInfo();
11864     perl_exception=newSVpv("",0);
11865     sv=NULL;
11866     if (sv_isobject(ST(0)) == 0)
11867       {
11868         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11869           PackageName);
11870         goto PerlException;
11871       }
11872     reference=SvRV(ST(0));
11873     hv=SvSTASH(reference);
11874     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11875     if (image == (Image *) NULL)
11876       {
11877         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11878           PackageName);
11879         goto PerlException;
11880       }
11881     image=MergeImageLayers(image,MosaicLayer,exception);
11882     /*
11883       Create blessed Perl array for the returned image.
11884     */
11885     av=newAV();
11886     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11887     SvREFCNT_dec(av);
11888     AddImageToRegistry(sv,image);
11889     rv=newRV(sv);
11890     av_push(av,sv_bless(rv,hv));
11891     SvREFCNT_dec(sv);
11892     (void) CopyMagickString(info->image_info->filename,image->filename,
11893       MagickPathExtent);
11894     SetImageInfo(info->image_info,0,exception);
11895     exception=DestroyExceptionInfo(exception);
11896     SvREFCNT_dec(perl_exception);
11897     XSRETURN(1);
11898
11899   PerlException:
11900     InheritPerlException(exception,perl_exception);
11901     exception=DestroyExceptionInfo(exception);
11902     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11903     SvPOK_on(perl_exception);  /* return messages in string context */
11904     ST(0)=sv_2mortal(perl_exception);
11905     XSRETURN(1);
11906   }
11907 \f
11908 #
11909 ###############################################################################
11910 #                                                                             #
11911 #                                                                             #
11912 #                                                                             #
11913 #   P i n g                                                                   #
11914 #                                                                             #
11915 #                                                                             #
11916 #                                                                             #
11917 ###############################################################################
11918 #
11919 #
11920 void
11921 Ping(ref,...)
11922   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11923   ALIAS:
11924     PingImage  = 1
11925     ping       = 2
11926     pingimage  = 3
11927   PPCODE:
11928   {
11929     AV
11930       *av;
11931
11932     char
11933       **keep,
11934       **list;
11935
11936     ExceptionInfo
11937       *exception;
11938
11939     Image
11940       *image,
11941       *next;
11942
11943     int
11944       n;
11945
11946     MagickBooleanType
11947       status;
11948
11949     register char
11950       **p;
11951
11952     register ssize_t
11953       i;
11954
11955     ssize_t
11956       ac;
11957
11958     STRLEN
11959       *length;
11960
11961     struct PackageInfo
11962       *info,
11963       *package_info;
11964
11965     SV
11966       *perl_exception,
11967       *reference;
11968
11969     size_t
11970       count;
11971
11972     PERL_UNUSED_VAR(ref);
11973     PERL_UNUSED_VAR(ix);
11974     exception=AcquireExceptionInfo();
11975     perl_exception=newSVpv("",0);
11976     package_info=(struct PackageInfo *) NULL;
11977     ac=(items < 2) ? 1 : items-1;
11978     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11979     keep=list;
11980     length=(STRLEN *) NULL;
11981     if (list == (char **) NULL)
11982       {
11983         ThrowPerlException(exception,ResourceLimitError,
11984           "MemoryAllocationFailed",PackageName);
11985         goto PerlException;
11986       }
11987     keep=list;
11988     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11989     if (length == (STRLEN *) NULL)
11990       {
11991         ThrowPerlException(exception,ResourceLimitError,
11992           "MemoryAllocationFailed",PackageName);
11993         goto PerlException;
11994       }
11995     if (sv_isobject(ST(0)) == 0)
11996       {
11997         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11998           PackageName);
11999         goto PerlException;
12000       }
12001     reference=SvRV(ST(0));
12002     if (SvTYPE(reference) != SVt_PVAV)
12003       {
12004         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12005           PackageName);
12006         goto PerlException;
12007       }
12008     av=(AV *) reference;
12009     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12010       exception);
12011     package_info=ClonePackageInfo(info,exception);
12012     n=1;
12013     if (items <= 1)
12014       *list=(char *) (*package_info->image_info->filename ?
12015         package_info->image_info->filename : "XC:black");
12016     else
12017       for (n=0, i=0; i < ac; i++)
12018       {
12019         list[n]=(char *) SvPV(ST(i+1),length[n]);
12020         if ((items >= 3) && strEQcase(list[n],"blob"))
12021           {
12022             void
12023               *blob;
12024
12025             i++;
12026             blob=(void *) (SvPV(ST(i+1),length[n]));
12027             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12028           }
12029         if ((items >= 3) && strEQcase(list[n],"filename"))
12030           continue;
12031         if ((items >= 3) && strEQcase(list[n],"file"))
12032           {
12033             FILE
12034               *file;
12035
12036             PerlIO
12037               *io_info;
12038
12039             i++;
12040             io_info=IoIFP(sv_2io(ST(i+1)));
12041             if (io_info == (PerlIO *) NULL)
12042               {
12043                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12044                   PackageName);
12045                 continue;
12046               }
12047             file=PerlIO_findFILE(io_info);
12048             if (file == (FILE *) NULL)
12049               {
12050                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12051                   PackageName);
12052                 continue;
12053               }
12054             SetImageInfoFile(package_info->image_info,file);
12055           }
12056         if ((items >= 3) && strEQcase(list[n],"magick"))
12057           continue;
12058         n++;
12059       }
12060     list[n]=(char *) NULL;
12061     keep=list;
12062     status=ExpandFilenames(&n,&list);
12063     if (status == MagickFalse)
12064       {
12065         ThrowPerlException(exception,ResourceLimitError,
12066           "MemoryAllocationFailed",PackageName);
12067         goto PerlException;
12068       }
12069     count=0;
12070     for (i=0; i < n; i++)
12071     {
12072       (void) CopyMagickString(package_info->image_info->filename,list[i],
12073         MagickPathExtent);
12074       image=PingImage(package_info->image_info,exception);
12075       if (image == (Image *) NULL)
12076         break;
12077       if ((package_info->image_info->file != (FILE *) NULL) ||
12078           (package_info->image_info->blob != (void *) NULL))
12079         DisassociateImageStream(image);
12080       count+=GetImageListLength(image);
12081       EXTEND(sp,4*count);
12082       for (next=image; next; next=next->next)
12083       {
12084         PUSHs(sv_2mortal(newSViv(next->columns)));
12085         PUSHs(sv_2mortal(newSViv(next->rows)));
12086         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12087         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12088       }
12089       image=DestroyImageList(image);
12090     }
12091     /*
12092       Free resources.
12093     */
12094     for (i=0; i < n; i++)
12095       if (list[i] != (char *) NULL)
12096         for (p=keep; list[i] != *p++; )
12097           if (*p == NULL)
12098             {
12099               list[i]=(char *) RelinquishMagickMemory(list[i]);
12100               break;
12101             }
12102
12103   PerlException:
12104     if (package_info != (struct PackageInfo *) NULL)
12105       DestroyPackageInfo(package_info);
12106     if (list && (list != keep))
12107       list=(char **) RelinquishMagickMemory(list);
12108     if (keep)
12109       keep=(char **) RelinquishMagickMemory(keep);
12110     if (length)
12111       length=(STRLEN *) RelinquishMagickMemory(length);
12112     InheritPerlException(exception,perl_exception);
12113     exception=DestroyExceptionInfo(exception);
12114     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12115   }
12116 \f
12117 #
12118 ###############################################################################
12119 #                                                                             #
12120 #                                                                             #
12121 #                                                                             #
12122 #   P r e v i e w                                                             #
12123 #                                                                             #
12124 #                                                                             #
12125 #                                                                             #
12126 ###############################################################################
12127 #
12128 #
12129 void
12130 Preview(ref,...)
12131   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12132   ALIAS:
12133     PreviewImage = 1
12134     preview      = 2
12135     previewimage = 3
12136   PPCODE:
12137   {
12138     AV
12139       *av;
12140
12141     ExceptionInfo
12142       *exception;
12143
12144     HV
12145       *hv;
12146
12147     Image
12148       *image,
12149       *preview_image;
12150
12151     PreviewType
12152       preview_type;
12153
12154     struct PackageInfo
12155       *info;
12156
12157     SV
12158       *av_reference,
12159       *perl_exception,
12160       *reference,
12161       *rv,
12162       *sv;
12163
12164     PERL_UNUSED_VAR(ref);
12165     PERL_UNUSED_VAR(ix);
12166     exception=AcquireExceptionInfo();
12167     perl_exception=newSVpv("",0);
12168     sv=NULL;
12169     av=NULL;
12170     if (sv_isobject(ST(0)) == 0)
12171       {
12172         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12173           PackageName);
12174         goto PerlException;
12175       }
12176     reference=SvRV(ST(0));
12177     hv=SvSTASH(reference);
12178     av=newAV();
12179     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12180     SvREFCNT_dec(av);
12181     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12182     if (image == (Image *) NULL)
12183       {
12184         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12185           PackageName);
12186         goto PerlException;
12187       }
12188     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12189     preview_type=GammaPreview;
12190     if (items > 1)
12191       preview_type=(PreviewType)
12192         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12193     for ( ; image; image=image->next)
12194     {
12195       preview_image=PreviewImage(image,preview_type,exception);
12196       if (preview_image == (Image *) NULL)
12197         goto PerlException;
12198       AddImageToRegistry(sv,preview_image);
12199       rv=newRV(sv);
12200       av_push(av,sv_bless(rv,hv));
12201       SvREFCNT_dec(sv);
12202     }
12203     exception=DestroyExceptionInfo(exception);
12204     ST(0)=av_reference;
12205     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12206     XSRETURN(1);
12207
12208   PerlException:
12209     InheritPerlException(exception,perl_exception);
12210     exception=DestroyExceptionInfo(exception);
12211     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12212     SvPOK_on(perl_exception);
12213     ST(0)=sv_2mortal(perl_exception);
12214     XSRETURN(1);
12215   }
12216 \f
12217 #
12218 ###############################################################################
12219 #                                                                             #
12220 #                                                                             #
12221 #                                                                             #
12222 #   Q u e r y C o l o r                                                       #
12223 #                                                                             #
12224 #                                                                             #
12225 #                                                                             #
12226 ###############################################################################
12227 #
12228 #
12229 void
12230 QueryColor(ref,...)
12231   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12232   ALIAS:
12233     querycolor = 1
12234   PPCODE:
12235   {
12236     char
12237       *name;
12238
12239     ExceptionInfo
12240       *exception;
12241
12242     PixelInfo
12243       color;
12244
12245     register ssize_t
12246       i;
12247
12248     SV
12249       *perl_exception;
12250
12251     PERL_UNUSED_VAR(ref);
12252     PERL_UNUSED_VAR(ix);
12253     exception=AcquireExceptionInfo();
12254     perl_exception=newSVpv("",0);
12255     if (items == 1)
12256       {
12257         const ColorInfo
12258           **colorlist;
12259
12260         size_t
12261           colors;
12262
12263         colorlist=GetColorInfoList("*",&colors,exception);
12264         EXTEND(sp,colors);
12265         for (i=0; i < (ssize_t) colors; i++)
12266         {
12267           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12268         }
12269         colorlist=(const ColorInfo **)
12270           RelinquishMagickMemory((ColorInfo **) colorlist);
12271         goto PerlException;
12272       }
12273     EXTEND(sp,5*items);
12274     for (i=1; i < items; i++)
12275     {
12276       name=(char *) SvPV(ST(i),na);
12277       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12278         {
12279           PUSHs(&sv_undef);
12280           continue;
12281         }
12282       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12283       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12284       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12285       if (color.colorspace == CMYKColorspace)
12286         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12287       if (color.alpha_trait != UndefinedPixelTrait)
12288         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12289     }
12290
12291   PerlException:
12292     InheritPerlException(exception,perl_exception);
12293     exception=DestroyExceptionInfo(exception);
12294     SvREFCNT_dec(perl_exception);
12295   }
12296 \f
12297 #
12298 ###############################################################################
12299 #                                                                             #
12300 #                                                                             #
12301 #                                                                             #
12302 #   Q u e r y C o l o r N a m e                                               #
12303 #                                                                             #
12304 #                                                                             #
12305 #                                                                             #
12306 ###############################################################################
12307 #
12308 #
12309 void
12310 QueryColorname(ref,...)
12311   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12312   ALIAS:
12313     querycolorname = 1
12314   PPCODE:
12315   {
12316     AV
12317       *av;
12318
12319     char
12320       message[MagickPathExtent];
12321
12322     ExceptionInfo
12323       *exception;
12324
12325     Image
12326       *image;
12327
12328     PixelInfo
12329       target_color;
12330
12331     register ssize_t
12332       i;
12333
12334     struct PackageInfo
12335       *info;
12336
12337     SV
12338       *perl_exception,
12339       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12340
12341     PERL_UNUSED_VAR(ref);
12342     PERL_UNUSED_VAR(ix);
12343     exception=AcquireExceptionInfo();
12344     perl_exception=newSVpv("",0);
12345     reference=SvRV(ST(0));
12346     av=(AV *) reference;
12347     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12348       exception);
12349     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12350     if (image == (Image *) NULL)
12351       {
12352         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12353           PackageName);
12354         goto PerlException;
12355       }
12356     EXTEND(sp,items);
12357     for (i=1; i < items; i++)
12358     {
12359       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12360         exception);
12361       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12362         exception);
12363       PUSHs(sv_2mortal(newSVpv(message,0)));
12364     }
12365
12366   PerlException:
12367     InheritPerlException(exception,perl_exception);
12368     exception=DestroyExceptionInfo(exception);
12369     SvREFCNT_dec(perl_exception);
12370   }
12371 \f
12372 #
12373 ###############################################################################
12374 #                                                                             #
12375 #                                                                             #
12376 #                                                                             #
12377 #   Q u e r y F o n t                                                         #
12378 #                                                                             #
12379 #                                                                             #
12380 #                                                                             #
12381 ###############################################################################
12382 #
12383 #
12384 void
12385 QueryFont(ref,...)
12386   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12387   ALIAS:
12388     queryfont = 1
12389   PPCODE:
12390   {
12391     char
12392       *name,
12393       message[MagickPathExtent];
12394
12395     ExceptionInfo
12396       *exception;
12397
12398     register ssize_t
12399       i;
12400
12401     SV
12402       *perl_exception;
12403
12404     volatile const TypeInfo
12405       *type_info;
12406
12407     PERL_UNUSED_VAR(ref);
12408     PERL_UNUSED_VAR(ix);
12409     exception=AcquireExceptionInfo();
12410     perl_exception=newSVpv("",0);
12411     if (items == 1)
12412       {
12413         const TypeInfo
12414           **typelist;
12415
12416         size_t
12417           types;
12418
12419         typelist=GetTypeInfoList("*",&types,exception);
12420         EXTEND(sp,types);
12421         for (i=0; i < (ssize_t) types; i++)
12422         {
12423           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12424         }
12425         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12426           typelist);
12427         goto PerlException;
12428       }
12429     EXTEND(sp,10*items);
12430     for (i=1; i < items; i++)
12431     {
12432       name=(char *) SvPV(ST(i),na);
12433       type_info=GetTypeInfo(name,exception);
12434       if (type_info == (TypeInfo *) NULL)
12435         {
12436           PUSHs(&sv_undef);
12437           continue;
12438         }
12439       if (type_info->name == (char *) NULL)
12440         PUSHs(&sv_undef);
12441       else
12442         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12443       if (type_info->description == (char *) NULL)
12444         PUSHs(&sv_undef);
12445       else
12446         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12447       if (type_info->family == (char *) NULL)
12448         PUSHs(&sv_undef);
12449       else
12450         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12451       if (type_info->style == UndefinedStyle)
12452         PUSHs(&sv_undef);
12453       else
12454         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12455           type_info->style),0)));
12456       if (type_info->stretch == UndefinedStretch)
12457         PUSHs(&sv_undef);
12458       else
12459         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12460           type_info->stretch),0)));
12461       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12462         type_info->weight);
12463       PUSHs(sv_2mortal(newSVpv(message,0)));
12464       if (type_info->encoding == (char *) NULL)
12465         PUSHs(&sv_undef);
12466       else
12467         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12468       if (type_info->foundry == (char *) NULL)
12469         PUSHs(&sv_undef);
12470       else
12471         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12472       if (type_info->format == (char *) NULL)
12473         PUSHs(&sv_undef);
12474       else
12475         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12476       if (type_info->metrics == (char *) NULL)
12477         PUSHs(&sv_undef);
12478       else
12479         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12480       if (type_info->glyphs == (char *) NULL)
12481         PUSHs(&sv_undef);
12482       else
12483         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12484     }
12485
12486   PerlException:
12487     InheritPerlException(exception,perl_exception);
12488     exception=DestroyExceptionInfo(exception);
12489     SvREFCNT_dec(perl_exception);
12490   }
12491 \f
12492 #
12493 ###############################################################################
12494 #                                                                             #
12495 #                                                                             #
12496 #                                                                             #
12497 #   Q u e r y F o n t M e t r i c s                                           #
12498 #                                                                             #
12499 #                                                                             #
12500 #                                                                             #
12501 ###############################################################################
12502 #
12503 #
12504 void
12505 QueryFontMetrics(ref,...)
12506   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12507   ALIAS:
12508     queryfontmetrics = 1
12509   PPCODE:
12510   {
12511     AffineMatrix
12512       affine,
12513       current;
12514
12515     AV
12516       *av;
12517
12518     char
12519       *attribute;
12520
12521     double
12522       x,
12523       y;
12524
12525     DrawInfo
12526       *draw_info;
12527
12528     ExceptionInfo
12529       *exception;
12530
12531     GeometryInfo
12532       geometry_info;
12533
12534     Image
12535       *image;
12536
12537     MagickBooleanType
12538       status;
12539
12540     MagickStatusType
12541       flags;
12542
12543     register ssize_t
12544       i;
12545
12546     ssize_t
12547       type;
12548
12549     struct PackageInfo
12550       *info,
12551       *package_info;
12552
12553     SV
12554       *perl_exception,
12555       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12556
12557     TypeMetric
12558       metrics;
12559
12560     PERL_UNUSED_VAR(ref);
12561     PERL_UNUSED_VAR(ix);
12562     exception=AcquireExceptionInfo();
12563     package_info=(struct PackageInfo *) NULL;
12564     perl_exception=newSVpv("",0);
12565     reference=SvRV(ST(0));
12566     av=(AV *) reference;
12567     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12568       exception);
12569     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12570     if (image == (Image *) NULL)
12571       {
12572         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12573           PackageName);
12574         goto PerlException;
12575       }
12576     package_info=ClonePackageInfo(info,exception);
12577     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12578     CloneString(&draw_info->text,"");
12579     current=draw_info->affine;
12580     GetAffineMatrix(&affine);
12581     x=0.0;
12582     y=0.0;
12583     EXTEND(sp,7*items);
12584     for (i=2; i < items; i+=2)
12585     {
12586       attribute=(char *) SvPV(ST(i-1),na);
12587       switch (*attribute)
12588       {
12589         case 'A':
12590         case 'a':
12591         {
12592           if (LocaleCompare(attribute,"antialias") == 0)
12593             {
12594               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12595                 SvPV(ST(i),na));
12596               if (type < 0)
12597                 {
12598                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12599                     SvPV(ST(i),na));
12600                   break;
12601                 }
12602               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12603               break;
12604             }
12605           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12606             attribute);
12607           break;
12608         }
12609         case 'd':
12610         case 'D':
12611         {
12612           if (LocaleCompare(attribute,"density") == 0)
12613             {
12614               CloneString(&draw_info->density,SvPV(ST(i),na));
12615               break;
12616             }
12617           if (LocaleCompare(attribute,"direction") == 0)
12618             {
12619               draw_info->direction=(DirectionType) ParseCommandOption(
12620                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12621               break;
12622             }
12623           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12624             attribute);
12625           break;
12626         }
12627         case 'e':
12628         case 'E':
12629         {
12630           if (LocaleCompare(attribute,"encoding") == 0)
12631             {
12632               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12633               break;
12634             }
12635           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12636             attribute);
12637           break;
12638         }
12639         case 'f':
12640         case 'F':
12641         {
12642           if (LocaleCompare(attribute,"family") == 0)
12643             {
12644               CloneString(&draw_info->family,SvPV(ST(i),na));
12645               break;
12646             }
12647           if (LocaleCompare(attribute,"fill") == 0)
12648             {
12649               if (info)
12650                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12651                   &draw_info->fill,exception);
12652               break;
12653             }
12654           if (LocaleCompare(attribute,"font") == 0)
12655             {
12656               CloneString(&draw_info->font,SvPV(ST(i),na));
12657               break;
12658             }
12659           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12660             attribute);
12661           break;
12662         }
12663         case 'g':
12664         case 'G':
12665         {
12666           if (LocaleCompare(attribute,"geometry") == 0)
12667             {
12668               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12669               break;
12670             }
12671           if (LocaleCompare(attribute,"gravity") == 0)
12672             {
12673               draw_info->gravity=(GravityType) ParseCommandOption(
12674                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12675               break;
12676             }
12677           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12678             attribute);
12679           break;
12680         }
12681         case 'i':
12682         case 'I':
12683         {
12684           if (LocaleCompare(attribute,"interline-spacing") == 0)
12685             {
12686               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12687               draw_info->interline_spacing=geometry_info.rho;
12688               break;
12689             }
12690           if (LocaleCompare(attribute,"interword-spacing") == 0)
12691             {
12692               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12693               draw_info->interword_spacing=geometry_info.rho;
12694               break;
12695             }
12696           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12697             attribute);
12698           break;
12699         }
12700         case 'k':
12701         case 'K':
12702         {
12703           if (LocaleCompare(attribute,"kerning") == 0)
12704             {
12705               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12706               draw_info->kerning=geometry_info.rho;
12707               break;
12708             }
12709           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12710             attribute);
12711           break;
12712         }
12713         case 'p':
12714         case 'P':
12715         {
12716           if (LocaleCompare(attribute,"pointsize") == 0)
12717             {
12718               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12719               draw_info->pointsize=geometry_info.rho;
12720               break;
12721             }
12722           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12723             attribute);
12724           break;
12725         }
12726         case 'r':
12727         case 'R':
12728         {
12729           if (LocaleCompare(attribute,"rotate") == 0)
12730             {
12731               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12732               affine.rx=geometry_info.rho;
12733               affine.ry=geometry_info.sigma;
12734               if ((flags & SigmaValue) == 0)
12735                 affine.ry=affine.rx;
12736               break;
12737             }
12738           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12739             attribute);
12740           break;
12741         }
12742         case 's':
12743         case 'S':
12744         {
12745           if (LocaleCompare(attribute,"scale") == 0)
12746             {
12747               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12748               affine.sx=geometry_info.rho;
12749               affine.sy=geometry_info.sigma;
12750               if ((flags & SigmaValue) == 0)
12751                 affine.sy=affine.sx;
12752               break;
12753             }
12754           if (LocaleCompare(attribute,"skew") == 0)
12755             {
12756               double
12757                 x_angle,
12758                 y_angle;
12759
12760               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12761               x_angle=geometry_info.rho;
12762               y_angle=geometry_info.sigma;
12763               if ((flags & SigmaValue) == 0)
12764                 y_angle=x_angle;
12765               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12766               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12767               break;
12768             }
12769           if (LocaleCompare(attribute,"stroke") == 0)
12770             {
12771               if (info)
12772                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12773                   &draw_info->stroke,exception);
12774               break;
12775             }
12776           if (LocaleCompare(attribute,"style") == 0)
12777             {
12778               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12779                 SvPV(ST(i),na));
12780               if (type < 0)
12781                 {
12782                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12783                     SvPV(ST(i),na));
12784                   break;
12785                 }
12786               draw_info->style=(StyleType) type;
12787               break;
12788             }
12789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12790             attribute);
12791           break;
12792         }
12793         case 't':
12794         case 'T':
12795         {
12796           if (LocaleCompare(attribute,"text") == 0)
12797             {
12798               CloneString(&draw_info->text,SvPV(ST(i),na));
12799               break;
12800             }
12801           if (LocaleCompare(attribute,"translate") == 0)
12802             {
12803               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12804               affine.tx=geometry_info.rho;
12805               affine.ty=geometry_info.sigma;
12806               if ((flags & SigmaValue) == 0)
12807                 affine.ty=affine.tx;
12808               break;
12809             }
12810           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12811             attribute);
12812           break;
12813         }
12814         case 'w':
12815         case 'W':
12816         {
12817           if (LocaleCompare(attribute,"weight") == 0)
12818             {
12819               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12820               draw_info->weight=(size_t) geometry_info.rho;
12821               break;
12822             }
12823           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12824             attribute);
12825           break;
12826         }
12827         case 'x':
12828         case 'X':
12829         {
12830           if (LocaleCompare(attribute,"x") == 0)
12831             {
12832               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12833               x=geometry_info.rho;
12834               break;
12835             }
12836           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12837             attribute);
12838           break;
12839         }
12840         case 'y':
12841         case 'Y':
12842         {
12843           if (LocaleCompare(attribute,"y") == 0)
12844             {
12845               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12846               y=geometry_info.rho;
12847               break;
12848             }
12849           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12850             attribute);
12851           break;
12852         }
12853         default:
12854         {
12855           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12856             attribute);
12857           break;
12858         }
12859       }
12860     }
12861     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12862     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12863     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12864     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12865     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12866     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12867     if (draw_info->geometry == (char *) NULL)
12868       {
12869         draw_info->geometry=AcquireString((char *) NULL);
12870         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12871           "%.15g,%.15g",x,y);
12872       }
12873     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12874     (void) CatchImageException(image);
12875     if (status == MagickFalse)
12876       PUSHs(&sv_undef);
12877     else
12878       {
12879         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12880         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12881         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12882         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12883         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12884         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12885         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12886         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12887         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12888         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12889         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12890         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12891         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12892       }
12893     draw_info=DestroyDrawInfo(draw_info);
12894
12895   PerlException:
12896     if (package_info != (struct PackageInfo *) NULL)
12897       DestroyPackageInfo(package_info);
12898     InheritPerlException(exception,perl_exception);
12899     exception=DestroyExceptionInfo(exception);
12900     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12901   }
12902 \f
12903 #
12904 ###############################################################################
12905 #                                                                             #
12906 #                                                                             #
12907 #                                                                             #
12908 #   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                         #
12909 #                                                                             #
12910 #                                                                             #
12911 #                                                                             #
12912 ###############################################################################
12913 #
12914 #
12915 void
12916 QueryMultilineFontMetrics(ref,...)
12917   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12918   ALIAS:
12919     querymultilinefontmetrics = 1
12920   PPCODE:
12921   {
12922     AffineMatrix
12923       affine,
12924       current;
12925
12926     AV
12927       *av;
12928
12929     char
12930       *attribute;
12931
12932     double
12933       x,
12934       y;
12935
12936     DrawInfo
12937       *draw_info;
12938
12939     ExceptionInfo
12940       *exception;
12941
12942     GeometryInfo
12943       geometry_info;
12944
12945     Image
12946       *image;
12947
12948     MagickBooleanType
12949       status;
12950
12951     MagickStatusType
12952       flags;
12953
12954     register ssize_t
12955       i;
12956
12957     ssize_t
12958       type;
12959
12960     struct PackageInfo
12961       *info,
12962       *package_info;
12963
12964     SV
12965       *perl_exception,
12966       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12967
12968     TypeMetric
12969       metrics;
12970
12971     PERL_UNUSED_VAR(ref);
12972     PERL_UNUSED_VAR(ix);
12973     exception=AcquireExceptionInfo();
12974     package_info=(struct PackageInfo *) NULL;
12975     perl_exception=newSVpv("",0);
12976     reference=SvRV(ST(0));
12977     av=(AV *) reference;
12978     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12979       exception);
12980     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12981     if (image == (Image *) NULL)
12982       {
12983         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12984           PackageName);
12985         goto PerlException;
12986       }
12987     package_info=ClonePackageInfo(info,exception);
12988     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12989     CloneString(&draw_info->text,"");
12990     current=draw_info->affine;
12991     GetAffineMatrix(&affine);
12992     x=0.0;
12993     y=0.0;
12994     EXTEND(sp,7*items);
12995     for (i=2; i < items; i+=2)
12996     {
12997       attribute=(char *) SvPV(ST(i-1),na);
12998       switch (*attribute)
12999       {
13000         case 'A':
13001         case 'a':
13002         {
13003           if (LocaleCompare(attribute,"antialias") == 0)
13004             {
13005               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13006                 SvPV(ST(i),na));
13007               if (type < 0)
13008                 {
13009                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13010                     SvPV(ST(i),na));
13011                   break;
13012                 }
13013               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13014               break;
13015             }
13016           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13017             attribute);
13018           break;
13019         }
13020         case 'd':
13021         case 'D':
13022         {
13023           if (LocaleCompare(attribute,"density") == 0)
13024             {
13025               CloneString(&draw_info->density,SvPV(ST(i),na));
13026               break;
13027             }
13028           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13029             attribute);
13030           break;
13031         }
13032         case 'e':
13033         case 'E':
13034         {
13035           if (LocaleCompare(attribute,"encoding") == 0)
13036             {
13037               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13038               break;
13039             }
13040           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13041             attribute);
13042           break;
13043         }
13044         case 'f':
13045         case 'F':
13046         {
13047           if (LocaleCompare(attribute,"family") == 0)
13048             {
13049               CloneString(&draw_info->family,SvPV(ST(i),na));
13050               break;
13051             }
13052           if (LocaleCompare(attribute,"fill") == 0)
13053             {
13054               if (info)
13055                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13056                   &draw_info->fill,exception);
13057               break;
13058             }
13059           if (LocaleCompare(attribute,"font") == 0)
13060             {
13061               CloneString(&draw_info->font,SvPV(ST(i),na));
13062               break;
13063             }
13064           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13065             attribute);
13066           break;
13067         }
13068         case 'g':
13069         case 'G':
13070         {
13071           if (LocaleCompare(attribute,"geometry") == 0)
13072             {
13073               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13074               break;
13075             }
13076           if (LocaleCompare(attribute,"gravity") == 0)
13077             {
13078               draw_info->gravity=(GravityType) ParseCommandOption(
13079                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13080               break;
13081             }
13082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13083             attribute);
13084           break;
13085         }
13086         case 'p':
13087         case 'P':
13088         {
13089           if (LocaleCompare(attribute,"pointsize") == 0)
13090             {
13091               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13092               draw_info->pointsize=geometry_info.rho;
13093               break;
13094             }
13095           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13096             attribute);
13097           break;
13098         }
13099         case 'r':
13100         case 'R':
13101         {
13102           if (LocaleCompare(attribute,"rotate") == 0)
13103             {
13104               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13105               affine.rx=geometry_info.rho;
13106               affine.ry=geometry_info.sigma;
13107               if ((flags & SigmaValue) == 0)
13108                 affine.ry=affine.rx;
13109               break;
13110             }
13111           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13112             attribute);
13113           break;
13114         }
13115         case 's':
13116         case 'S':
13117         {
13118           if (LocaleCompare(attribute,"scale") == 0)
13119             {
13120               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13121               affine.sx=geometry_info.rho;
13122               affine.sy=geometry_info.sigma;
13123               if ((flags & SigmaValue) == 0)
13124                 affine.sy=affine.sx;
13125               break;
13126             }
13127           if (LocaleCompare(attribute,"skew") == 0)
13128             {
13129               double
13130                 x_angle,
13131                 y_angle;
13132
13133               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13134               x_angle=geometry_info.rho;
13135               y_angle=geometry_info.sigma;
13136               if ((flags & SigmaValue) == 0)
13137                 y_angle=x_angle;
13138               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13139               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13140               break;
13141             }
13142           if (LocaleCompare(attribute,"stroke") == 0)
13143             {
13144               if (info)
13145                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13146                   &draw_info->stroke,exception);
13147               break;
13148             }
13149           if (LocaleCompare(attribute,"style") == 0)
13150             {
13151               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13152                 SvPV(ST(i),na));
13153               if (type < 0)
13154                 {
13155                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13156                     SvPV(ST(i),na));
13157                   break;
13158                 }
13159               draw_info->style=(StyleType) type;
13160               break;
13161             }
13162           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13163             attribute);
13164           break;
13165         }
13166         case 't':
13167         case 'T':
13168         {
13169           if (LocaleCompare(attribute,"text") == 0)
13170             {
13171               CloneString(&draw_info->text,SvPV(ST(i),na));
13172               break;
13173             }
13174           if (LocaleCompare(attribute,"translate") == 0)
13175             {
13176               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13177               affine.tx=geometry_info.rho;
13178               affine.ty=geometry_info.sigma;
13179               if ((flags & SigmaValue) == 0)
13180                 affine.ty=affine.tx;
13181               break;
13182             }
13183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13184             attribute);
13185           break;
13186         }
13187         case 'w':
13188         case 'W':
13189         {
13190           if (LocaleCompare(attribute,"weight") == 0)
13191             {
13192               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13193               draw_info->weight=(size_t) geometry_info.rho;
13194               break;
13195             }
13196           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13197             attribute);
13198           break;
13199         }
13200         case 'x':
13201         case 'X':
13202         {
13203           if (LocaleCompare(attribute,"x") == 0)
13204             {
13205               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13206               x=geometry_info.rho;
13207               break;
13208             }
13209           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13210             attribute);
13211           break;
13212         }
13213         case 'y':
13214         case 'Y':
13215         {
13216           if (LocaleCompare(attribute,"y") == 0)
13217             {
13218               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13219               y=geometry_info.rho;
13220               break;
13221             }
13222           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13223             attribute);
13224           break;
13225         }
13226         default:
13227         {
13228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13229             attribute);
13230           break;
13231         }
13232       }
13233     }
13234     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13235     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13236     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13237     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13238     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13239     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13240     if (draw_info->geometry == (char *) NULL)
13241       {
13242         draw_info->geometry=AcquireString((char *) NULL);
13243         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13244           "%.15g,%.15g",x,y);
13245       }
13246     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13247     (void) CatchException(exception);
13248     if (status == MagickFalse)
13249       PUSHs(&sv_undef);
13250     else
13251       {
13252         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13253         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13254         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13255         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13256         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13257         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13258         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13259         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13260         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13261         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13262         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13263         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13264         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13265       }
13266     draw_info=DestroyDrawInfo(draw_info);
13267
13268   PerlException:
13269     if (package_info != (struct PackageInfo *) NULL)
13270       DestroyPackageInfo(package_info);
13271     InheritPerlException(exception,perl_exception);
13272     exception=DestroyExceptionInfo(exception);
13273     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13274   }
13275 \f
13276 #
13277 ###############################################################################
13278 #                                                                             #
13279 #                                                                             #
13280 #                                                                             #
13281 #   Q u e r y F o r m a t                                                     #
13282 #                                                                             #
13283 #                                                                             #
13284 #                                                                             #
13285 ###############################################################################
13286 #
13287 #
13288 void
13289 QueryFormat(ref,...)
13290   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13291   ALIAS:
13292     queryformat = 1
13293   PPCODE:
13294   {
13295     char
13296       *name;
13297
13298     ExceptionInfo
13299       *exception;
13300
13301     register ssize_t
13302       i;
13303
13304     SV
13305       *perl_exception;
13306
13307     volatile const MagickInfo
13308       *magick_info;
13309
13310     PERL_UNUSED_VAR(ref);
13311     PERL_UNUSED_VAR(ix);
13312     exception=AcquireExceptionInfo();
13313     perl_exception=newSVpv("",0);
13314     if (items == 1)
13315       {
13316         char
13317           format[MagickPathExtent];
13318
13319         const MagickInfo
13320           **format_list;
13321
13322         size_t
13323           types;
13324
13325         format_list=GetMagickInfoList("*",&types,exception);
13326         EXTEND(sp,types);
13327         for (i=0; i < (ssize_t) types; i++)
13328         {
13329           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13330           LocaleLower(format);
13331           PUSHs(sv_2mortal(newSVpv(format,0)));
13332         }
13333         format_list=(const MagickInfo **)
13334           RelinquishMagickMemory((MagickInfo *) format_list);
13335         goto PerlException;
13336       }
13337     EXTEND(sp,8*items);
13338     for (i=1; i < items; i++)
13339     {
13340       name=(char *) SvPV(ST(i),na);
13341       magick_info=GetMagickInfo(name,exception);
13342       if (magick_info == (const MagickInfo *) NULL)
13343         {
13344           PUSHs(&sv_undef);
13345           continue;
13346         }
13347       if (magick_info->description == (char *) NULL)
13348         PUSHs(&sv_undef);
13349       else
13350         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13351       if (magick_info->module == (char *) NULL)
13352         PUSHs(&sv_undef);
13353       else
13354         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13355     }
13356
13357   PerlException:
13358     InheritPerlException(exception,perl_exception);
13359     exception=DestroyExceptionInfo(exception);
13360     SvREFCNT_dec(perl_exception);
13361   }
13362 \f
13363 #
13364 ###############################################################################
13365 #                                                                             #
13366 #                                                                             #
13367 #                                                                             #
13368 #   Q u e r y O p t i o n                                                     #
13369 #                                                                             #
13370 #                                                                             #
13371 #                                                                             #
13372 ###############################################################################
13373 #
13374 #
13375 void
13376 QueryOption(ref,...)
13377   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13378   ALIAS:
13379     queryoption = 1
13380   PPCODE:
13381   {
13382     char
13383       **options;
13384
13385     ExceptionInfo
13386       *exception;
13387
13388     register ssize_t
13389       i;
13390
13391     ssize_t
13392       j,
13393       option;
13394
13395     SV
13396       *perl_exception;
13397
13398     PERL_UNUSED_VAR(ref);
13399     PERL_UNUSED_VAR(ix);
13400     exception=AcquireExceptionInfo();
13401     perl_exception=newSVpv("",0);
13402     EXTEND(sp,8*items);
13403     for (i=1; i < items; i++)
13404     {
13405       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13406         SvPV(ST(i),na));
13407       options=GetCommandOptions((CommandOption) option);
13408       if (options == (char **) NULL)
13409         PUSHs(&sv_undef);
13410       else
13411         {
13412           for (j=0; options[j] != (char *) NULL; j++)
13413             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13414           options=DestroyStringList(options);
13415         }
13416     }
13417
13418     InheritPerlException(exception,perl_exception);
13419     exception=DestroyExceptionInfo(exception);
13420     SvREFCNT_dec(perl_exception);
13421   }
13422 \f
13423 #
13424 ###############################################################################
13425 #                                                                             #
13426 #                                                                             #
13427 #                                                                             #
13428 #   R e a d                                                                   #
13429 #                                                                             #
13430 #                                                                             #
13431 #                                                                             #
13432 ###############################################################################
13433 #
13434 #
13435 void
13436 Read(ref,...)
13437   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13438   ALIAS:
13439     ReadImage  = 1
13440     read       = 2
13441     readimage  = 3
13442   PPCODE:
13443   {
13444     AV
13445       *av;
13446
13447     char
13448       **keep,
13449       **list;
13450
13451     ExceptionInfo
13452       *exception;
13453
13454     HV
13455       *hv;
13456
13457     Image
13458       *image;
13459
13460     int
13461       n;
13462
13463     MagickBooleanType
13464       status;
13465
13466     register char
13467       **p;
13468
13469     register ssize_t
13470       i;
13471
13472     ssize_t
13473       ac,
13474       number_images;
13475
13476     STRLEN
13477       *length;
13478
13479     struct PackageInfo
13480       *info,
13481       *package_info;
13482
13483     SV
13484       *perl_exception,  /* Perl variable for storing messages */
13485       *reference,
13486       *rv,
13487       *sv;
13488
13489     PERL_UNUSED_VAR(ref);
13490     PERL_UNUSED_VAR(ix);
13491     exception=AcquireExceptionInfo();
13492     perl_exception=newSVpv("",0);
13493     sv=NULL;
13494     package_info=(struct PackageInfo *) NULL;
13495     number_images=0;
13496     ac=(items < 2) ? 1 : items-1;
13497     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13498     keep=list;
13499     length=(STRLEN *) NULL;
13500     if (list == (char **) NULL)
13501       {
13502         ThrowPerlException(exception,ResourceLimitError,
13503           "MemoryAllocationFailed",PackageName);
13504         goto PerlException;
13505       }
13506     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13507     if (length == (STRLEN *) NULL)
13508       {
13509         ThrowPerlException(exception,ResourceLimitError,
13510           "MemoryAllocationFailed",PackageName);
13511         goto PerlException;
13512       }
13513     if (sv_isobject(ST(0)) == 0)
13514       {
13515         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13516           PackageName);
13517         goto PerlException;
13518       }
13519     reference=SvRV(ST(0));
13520     hv=SvSTASH(reference);
13521     if (SvTYPE(reference) != SVt_PVAV)
13522       {
13523         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13524           PackageName);
13525         goto PerlException;
13526       }
13527     av=(AV *) reference;
13528     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13529       exception);
13530     package_info=ClonePackageInfo(info,exception);
13531     n=1;
13532     if (items <= 1)
13533       *list=(char *) (*package_info->image_info->filename ?
13534         package_info->image_info->filename : "XC:black");
13535     else
13536       for (n=0, i=0; i < ac; i++)
13537       {
13538         list[n]=(char *) SvPV(ST(i+1),length[n]);
13539         if ((items >= 3) && strEQcase(list[n],"blob"))
13540           {
13541             void
13542               *blob;
13543
13544             i++;
13545             blob=(void *) (SvPV(ST(i+1),length[n]));
13546             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13547           }
13548         if ((items >= 3) && strEQcase(list[n],"filename"))
13549           continue;
13550         if ((items >= 3) && strEQcase(list[n],"file"))
13551           {
13552             FILE
13553               *file;
13554
13555             PerlIO
13556               *io_info;
13557
13558             i++;
13559             io_info=IoIFP(sv_2io(ST(i+1)));
13560             if (io_info == (PerlIO *) NULL)
13561               {
13562                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13563                   PackageName);
13564                 continue;
13565               }
13566             file=PerlIO_findFILE(io_info);
13567             if (file == (FILE *) NULL)
13568               {
13569                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13570                   PackageName);
13571                 continue;
13572               }
13573             SetImageInfoFile(package_info->image_info,file);
13574           }
13575         if ((items >= 3) && strEQcase(list[n],"magick"))
13576           continue;
13577         n++;
13578       }
13579     list[n]=(char *) NULL;
13580     keep=list;
13581     status=ExpandFilenames(&n,&list);
13582     if (status == MagickFalse)
13583       {
13584         ThrowPerlException(exception,ResourceLimitError,
13585           "MemoryAllocationFailed",PackageName);
13586         goto PerlException;
13587       }
13588     number_images=0;
13589     for (i=0; i < n; i++)
13590     {
13591       if ((package_info->image_info->file == (FILE *) NULL) &&
13592           (package_info->image_info->blob == (void *) NULL))
13593         image=ReadImages(package_info->image_info,list[i],exception);
13594       else
13595         {
13596           image=ReadImages(package_info->image_info,
13597             package_info->image_info->filename,exception);
13598           if (image != (Image *) NULL)
13599             DisassociateImageStream(image);
13600         }
13601       if (image == (Image *) NULL)
13602         break;
13603       for ( ; image; image=image->next)
13604       {
13605         AddImageToRegistry(sv,image);
13606         rv=newRV(sv);
13607         av_push(av,sv_bless(rv,hv));
13608         SvREFCNT_dec(sv);
13609         number_images++;
13610       }
13611     }
13612     /*
13613       Free resources.
13614     */
13615     for (i=0; i < n; i++)
13616       if (list[i] != (char *) NULL)
13617         for (p=keep; list[i] != *p++; )
13618           if (*p == (char *) NULL)
13619             {
13620               list[i]=(char *) RelinquishMagickMemory(list[i]);
13621               break;
13622             }
13623
13624   PerlException:
13625     if (package_info != (struct PackageInfo *) NULL)
13626       DestroyPackageInfo(package_info);
13627     if (list && (list != keep))
13628       list=(char **) RelinquishMagickMemory(list);
13629     if (keep)
13630       keep=(char **) RelinquishMagickMemory(keep);
13631     if (length)
13632       length=(STRLEN *) RelinquishMagickMemory(length);
13633     InheritPerlException(exception,perl_exception);
13634     exception=DestroyExceptionInfo(exception);
13635     sv_setiv(perl_exception,(IV) number_images);
13636     SvPOK_on(perl_exception);
13637     ST(0)=sv_2mortal(perl_exception);
13638     XSRETURN(1);
13639   }
13640 \f
13641 #
13642 ###############################################################################
13643 #                                                                             #
13644 #                                                                             #
13645 #                                                                             #
13646 #   R e m o t e                                                               #
13647 #                                                                             #
13648 #                                                                             #
13649 #                                                                             #
13650 ###############################################################################
13651 #
13652 #
13653 void
13654 Remote(ref,...)
13655   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13656   ALIAS:
13657     RemoteCommand  = 1
13658     remote         = 2
13659     remoteCommand  = 3
13660   PPCODE:
13661   {
13662     AV
13663       *av;
13664
13665     ExceptionInfo
13666       *exception;
13667
13668     register ssize_t
13669       i;
13670
13671     SV
13672       *perl_exception,
13673       *reference;
13674
13675     struct PackageInfo
13676       *info;
13677
13678     PERL_UNUSED_VAR(ref);
13679     PERL_UNUSED_VAR(ix);
13680     exception=AcquireExceptionInfo();
13681     perl_exception=newSVpv("",0);
13682     reference=SvRV(ST(0));
13683     av=(AV *) reference;
13684     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13685       exception);
13686     for (i=1; i < items; i++)
13687       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13688         SvPV(ST(i),na),exception);
13689     InheritPerlException(exception,perl_exception);
13690     exception=DestroyExceptionInfo(exception);
13691     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13692   }
13693 \f
13694 #
13695 ###############################################################################
13696 #                                                                             #
13697 #                                                                             #
13698 #                                                                             #
13699 #   S e t                                                                     #
13700 #                                                                             #
13701 #                                                                             #
13702 #                                                                             #
13703 ###############################################################################
13704 #
13705 #
13706 void
13707 Set(ref,...)
13708   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13709   ALIAS:
13710     SetAttributes  = 1
13711     SetAttribute   = 2
13712     set            = 3
13713     setattributes  = 4
13714     setattribute   = 5
13715   PPCODE:
13716   {
13717     ExceptionInfo
13718       *exception;
13719
13720     Image
13721       *image;
13722
13723     register ssize_t
13724       i;
13725
13726     struct PackageInfo
13727       *info;
13728
13729     SV
13730       *perl_exception,
13731       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13732
13733     PERL_UNUSED_VAR(ref);
13734     PERL_UNUSED_VAR(ix);
13735     exception=AcquireExceptionInfo();
13736     perl_exception=newSVpv("",0);
13737     if (sv_isobject(ST(0)) == 0)
13738       {
13739         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13740           PackageName);
13741         goto PerlException;
13742       }
13743     reference=SvRV(ST(0));
13744     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13745     if (items == 2)
13746       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13747     else
13748       for (i=2; i < items; i+=2)
13749         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13750
13751   PerlException:
13752     InheritPerlException(exception,perl_exception);
13753     exception=DestroyExceptionInfo(exception);
13754     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13755     SvPOK_on(perl_exception);
13756     ST(0)=sv_2mortal(perl_exception);
13757     XSRETURN(1);
13758   }
13759 \f
13760 #
13761 ###############################################################################
13762 #                                                                             #
13763 #                                                                             #
13764 #                                                                             #
13765 #   S e t P i x e l                                                           #
13766 #                                                                             #
13767 #                                                                             #
13768 #                                                                             #
13769 ###############################################################################
13770 #
13771 #
13772 void
13773 SetPixel(ref,...)
13774   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13775   ALIAS:
13776     setpixel = 1
13777     setPixel = 2
13778   PPCODE:
13779   {
13780     AV
13781       *av;
13782
13783     char
13784       *attribute;
13785
13786     ChannelType
13787       channel,
13788       channel_mask;
13789
13790     ExceptionInfo
13791       *exception;
13792
13793     Image
13794       *image;
13795
13796     MagickBooleanType
13797       normalize;
13798
13799     RectangleInfo
13800       region;
13801
13802     register ssize_t
13803       i;
13804
13805     register Quantum
13806       *q;
13807
13808     ssize_t
13809       option;
13810
13811     struct PackageInfo
13812       *info;
13813
13814     SV
13815       *perl_exception,
13816       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13817
13818     PERL_UNUSED_VAR(ref);
13819     PERL_UNUSED_VAR(ix);
13820     exception=AcquireExceptionInfo();
13821     perl_exception=newSVpv("",0);
13822     reference=SvRV(ST(0));
13823     av=(AV *) reference;
13824     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13825       exception);
13826     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13827     if (image == (Image *) NULL)
13828       {
13829         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13830           PackageName);
13831         goto PerlException;
13832       }
13833     av=(AV *) NULL;
13834     normalize=MagickTrue;
13835     region.x=0;
13836     region.y=0;
13837     region.width=image->columns;
13838     region.height=1;
13839     if (items == 1)
13840       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13841     channel=DefaultChannels;
13842     for (i=2; i < items; i+=2)
13843     {
13844       attribute=(char *) SvPV(ST(i-1),na);
13845       switch (*attribute)
13846       {
13847         case 'C':
13848         case 'c':
13849         {
13850           if (LocaleCompare(attribute,"channel") == 0)
13851             {
13852               ssize_t
13853                 option;
13854
13855               option=ParseChannelOption(SvPV(ST(i),na));
13856               if (option < 0)
13857                 {
13858                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13859                     SvPV(ST(i),na));
13860                   return;
13861                 }
13862               channel=(ChannelType) option;
13863               break;
13864             }
13865           if (LocaleCompare(attribute,"color") == 0)
13866             {
13867               if (SvTYPE(ST(i)) != SVt_RV)
13868                 {
13869                   char
13870                     message[MagickPathExtent];
13871
13872                   (void) FormatLocaleString(message,MagickPathExtent,
13873                     "invalid %.60s value",attribute);
13874                   ThrowPerlException(exception,OptionError,message,
13875                     SvPV(ST(i),na));
13876                 }
13877               av=(AV *) SvRV(ST(i));
13878               break;
13879             }
13880           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13881             attribute);
13882           break;
13883         }
13884         case 'g':
13885         case 'G':
13886         {
13887           if (LocaleCompare(attribute,"geometry") == 0)
13888             {
13889               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13890               break;
13891             }
13892           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13893             attribute);
13894           break;
13895         }
13896         case 'N':
13897         case 'n':
13898         {
13899           if (LocaleCompare(attribute,"normalize") == 0)
13900             {
13901               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13902                 SvPV(ST(i),na));
13903               if (option < 0)
13904                 {
13905                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13906                     SvPV(ST(i),na));
13907                   break;
13908                 }
13909              normalize=option != 0 ? MagickTrue : MagickFalse;
13910              break;
13911             }
13912           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13913             attribute);
13914           break;
13915         }
13916         case 'x':
13917         case 'X':
13918         {
13919           if (LocaleCompare(attribute,"x") == 0)
13920             {
13921               region.x=SvIV(ST(i));
13922               break;
13923             }
13924           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13925             attribute);
13926           break;
13927         }
13928         case 'y':
13929         case 'Y':
13930         {
13931           if (LocaleCompare(attribute,"y") == 0)
13932             {
13933               region.y=SvIV(ST(i));
13934               break;
13935             }
13936           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13937             attribute);
13938           break;
13939         }
13940         default:
13941         {
13942           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13943             attribute);
13944           break;
13945         }
13946       }
13947     }
13948     (void) SetImageStorageClass(image,DirectClass,exception);
13949     channel_mask=SetImageChannelMask(image,channel);
13950     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13951     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13952         (SvTYPE(av) != SVt_PVAV))
13953       PUSHs(&sv_undef);
13954     else
13955       {
13956         double
13957           scale;
13958
13959         register ssize_t
13960           i;
13961
13962         i=0;
13963         scale=1.0;
13964         if (normalize != MagickFalse)
13965           scale=QuantumRange;
13966         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13967             (i <= av_len(av)))
13968           {
13969             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13970               av_fetch(av,i,0)))),q);
13971             i++;
13972           }
13973         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13974             (i <= av_len(av)))
13975           {
13976             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13977               av_fetch(av,i,0)))),q);
13978             i++;
13979           }
13980         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13981             (i <= av_len(av)))
13982           {
13983             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13984               av_fetch(av,i,0)))),q);
13985             i++;
13986           }
13987         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13988             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13989           {
13990             SetPixelBlack(image,ClampToQuantum(scale*
13991               SvNV(*(av_fetch(av,i,0)))),q);
13992             i++;
13993           }
13994         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13995             (i <= av_len(av)))
13996           {
13997             SetPixelAlpha(image,ClampToQuantum(scale*
13998               SvNV(*(av_fetch(av,i,0)))),q);
13999             i++;
14000           }
14001         (void) SyncAuthenticPixels(image,exception);
14002       }
14003     (void) SetImageChannelMask(image,channel_mask);
14004
14005   PerlException:
14006     InheritPerlException(exception,perl_exception);
14007     exception=DestroyExceptionInfo(exception);
14008     SvREFCNT_dec(perl_exception);
14009   }
14010 \f
14011 #
14012 ###############################################################################
14013 #                                                                             #
14014 #                                                                             #
14015 #                                                                             #
14016 #   S m u s h                                                                 #
14017 #                                                                             #
14018 #                                                                             #
14019 #                                                                             #
14020 ###############################################################################
14021 #
14022 #
14023 void
14024 Smush(ref,...)
14025   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14026   ALIAS:
14027     SmushImage  = 1
14028     smush       = 2
14029     smushimage  = 3
14030   PPCODE:
14031   {
14032     AV
14033       *av;
14034
14035     char
14036       *attribute;
14037
14038     ExceptionInfo
14039       *exception;
14040
14041     HV
14042       *hv;
14043
14044     Image
14045       *image;
14046
14047     register ssize_t
14048       i;
14049
14050     ssize_t
14051       offset,
14052       stack;
14053
14054     struct PackageInfo
14055       *info;
14056
14057     SV
14058       *av_reference,
14059       *perl_exception,
14060       *reference,
14061       *rv,
14062       *sv;
14063
14064     PERL_UNUSED_VAR(ref);
14065     PERL_UNUSED_VAR(ix);
14066     exception=AcquireExceptionInfo();
14067     perl_exception=newSVpv("",0);
14068     sv=NULL;
14069     attribute=NULL;
14070     av=NULL;
14071     if (sv_isobject(ST(0)) == 0)
14072       {
14073         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14074           PackageName);
14075         goto PerlException;
14076       }
14077     reference=SvRV(ST(0));
14078     hv=SvSTASH(reference);
14079     av=newAV();
14080     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14081     SvREFCNT_dec(av);
14082     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14083     if (image == (Image *) NULL)
14084       {
14085         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14086           PackageName);
14087         goto PerlException;
14088       }
14089     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14090     /*
14091       Get options.
14092     */
14093     offset=0;
14094     stack=MagickTrue;
14095     for (i=2; i < items; i+=2)
14096     {
14097       attribute=(char *) SvPV(ST(i-1),na);
14098       switch (*attribute)
14099       {
14100         case 'O':
14101         case 'o':
14102         {
14103           if (LocaleCompare(attribute,"offset") == 0)
14104             {
14105               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14106               break;
14107             }
14108           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14109             attribute);
14110           break;
14111         }
14112         case 'S':
14113         case 's':
14114         {
14115           if (LocaleCompare(attribute,"stack") == 0)
14116             {
14117               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14118                 SvPV(ST(i),na));
14119               if (stack < 0)
14120                 {
14121                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14122                     SvPV(ST(i),na));
14123                   return;
14124                 }
14125               break;
14126             }
14127           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14128             attribute);
14129           break;
14130         }
14131         default:
14132         {
14133           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14134             attribute);
14135           break;
14136         }
14137       }
14138     }
14139     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14140       exception);
14141     if (image == (Image *) NULL)
14142       goto PerlException;
14143     for ( ; image; image=image->next)
14144     {
14145       AddImageToRegistry(sv,image);
14146       rv=newRV(sv);
14147       av_push(av,sv_bless(rv,hv));
14148       SvREFCNT_dec(sv);
14149     }
14150     exception=DestroyExceptionInfo(exception);
14151     ST(0)=av_reference;
14152     SvREFCNT_dec(perl_exception);
14153     XSRETURN(1);
14154
14155   PerlException:
14156     InheritPerlException(exception,perl_exception);
14157     exception=DestroyExceptionInfo(exception);
14158     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14159     SvPOK_on(perl_exception);
14160     ST(0)=sv_2mortal(perl_exception);
14161     XSRETURN(1);
14162   }
14163 \f
14164 #
14165 ###############################################################################
14166 #                                                                             #
14167 #                                                                             #
14168 #                                                                             #
14169 #   S t a t i s t i c s                                                       #
14170 #                                                                             #
14171 #                                                                             #
14172 #                                                                             #
14173 ###############################################################################
14174 #
14175 #
14176 void
14177 Statistics(ref,...)
14178   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14179   ALIAS:
14180     StatisticsImage = 1
14181     statistics      = 2
14182     statisticsimage = 3
14183   PPCODE:
14184   {
14185 #define ChannelStatistics(channel) \
14186 { \
14187   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14188     (double) channel_statistics[channel].depth); \
14189   PUSHs(sv_2mortal(newSVpv(message,0))); \
14190   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14191     channel_statistics[channel].minima/scale); \
14192   PUSHs(sv_2mortal(newSVpv(message,0))); \
14193   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14194     channel_statistics[channel].maxima/scale); \
14195   PUSHs(sv_2mortal(newSVpv(message,0))); \
14196   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14197     channel_statistics[channel].mean/scale); \
14198   PUSHs(sv_2mortal(newSVpv(message,0))); \
14199   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14200     channel_statistics[channel].standard_deviation/scale); \
14201   PUSHs(sv_2mortal(newSVpv(message,0))); \
14202   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14203     channel_statistics[channel].kurtosis); \
14204   PUSHs(sv_2mortal(newSVpv(message,0))); \
14205   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14206     channel_statistics[channel].skewness); \
14207   PUSHs(sv_2mortal(newSVpv(message,0))); \
14208   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14209     channel_statistics[channel].entropy); \
14210   PUSHs(sv_2mortal(newSVpv(message,0))); \
14211 }
14212
14213     AV
14214       *av;
14215
14216     char
14217       message[MagickPathExtent];
14218
14219     ChannelStatistics
14220       *channel_statistics;
14221
14222     double
14223       scale;
14224
14225     ExceptionInfo
14226       *exception;
14227
14228     Image
14229       *image;
14230
14231     ssize_t
14232       count;
14233
14234     struct PackageInfo
14235       *info;
14236
14237     SV
14238       *perl_exception,
14239       *reference;
14240
14241     PERL_UNUSED_VAR(ref);
14242     PERL_UNUSED_VAR(ix);
14243     exception=AcquireExceptionInfo();
14244     perl_exception=newSVpv("",0);
14245     av=NULL;
14246     if (sv_isobject(ST(0)) == 0)
14247       {
14248         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14249           PackageName);
14250         goto PerlException;
14251       }
14252     reference=SvRV(ST(0));
14253     av=newAV();
14254     SvREFCNT_dec(av);
14255     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14256     if (image == (Image *) NULL)
14257       {
14258         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14259           PackageName);
14260         goto PerlException;
14261       }
14262     count=0;
14263     for ( ; image; image=image->next)
14264     {
14265       channel_statistics=GetImageStatistics(image,exception);
14266       if (channel_statistics == (ChannelStatistics *) NULL)
14267         continue;
14268       count++;
14269       EXTEND(sp,35*count);
14270       scale=(double) QuantumRange;
14271       ChannelStatistics(RedChannel);
14272       ChannelStatistics(GreenChannel);
14273       ChannelStatistics(BlueChannel);
14274       if (image->colorspace == CMYKColorspace)
14275         ChannelStatistics(BlackChannel);
14276       if (image->alpha_trait != UndefinedPixelTrait)
14277         ChannelStatistics(AlphaChannel);
14278       channel_statistics=(ChannelStatistics *)
14279         RelinquishMagickMemory(channel_statistics);
14280     }
14281
14282   PerlException:
14283     InheritPerlException(exception,perl_exception);
14284     exception=DestroyExceptionInfo(exception);
14285     SvREFCNT_dec(perl_exception);
14286   }
14287 \f
14288 #
14289 ###############################################################################
14290 #                                                                             #
14291 #                                                                             #
14292 #                                                                             #
14293 #   S y n c A u t h e n t i c P i x e l s                                     #
14294 #                                                                             #
14295 #                                                                             #
14296 #                                                                             #
14297 ###############################################################################
14298 #
14299 #
14300 void
14301 SyncAuthenticPixels(ref,...)
14302   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14303   ALIAS:
14304     Syncauthenticpixels = 1
14305     SyncImagePixels = 2
14306     syncimagepixels = 3
14307   CODE:
14308   {
14309     ExceptionInfo
14310       *exception;
14311
14312     Image
14313       *image;
14314
14315     MagickBooleanType
14316       status;
14317
14318     struct PackageInfo
14319       *info;
14320
14321     SV
14322       *perl_exception,
14323       *reference;
14324
14325     PERL_UNUSED_VAR(ref);
14326     PERL_UNUSED_VAR(ix);
14327     exception=AcquireExceptionInfo();
14328     perl_exception=newSVpv("",0);
14329     if (sv_isobject(ST(0)) == 0)
14330       {
14331         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14332           PackageName);
14333         goto PerlException;
14334       }
14335
14336     reference=SvRV(ST(0));
14337     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14338     if (image == (Image *) NULL)
14339       {
14340         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14341           PackageName);
14342         goto PerlException;
14343       }
14344
14345     status=SyncAuthenticPixels(image,exception);
14346     if (status != MagickFalse)
14347       return;
14348
14349   PerlException:
14350     InheritPerlException(exception,perl_exception);
14351     exception=DestroyExceptionInfo(exception);
14352     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14353   }
14354 \f
14355 #
14356 ###############################################################################
14357 #                                                                             #
14358 #                                                                             #
14359 #                                                                             #
14360 #   T r a n s f o r m                                                         #
14361 #                                                                             #
14362 #                                                                             #
14363 #                                                                             #
14364 ###############################################################################
14365 #
14366 #
14367 void
14368 Transform(ref,...)
14369   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14370   ALIAS:
14371     TransformImage = 1
14372     transform      = 2
14373     transformimage = 3
14374   PPCODE:
14375   {
14376     AV
14377       *av;
14378
14379     char
14380       *attribute,
14381       *crop_geometry,
14382       *geometry;
14383
14384     ExceptionInfo
14385       *exception;
14386
14387     HV
14388       *hv;
14389
14390     Image
14391       *clone,
14392       *image;
14393
14394     register ssize_t
14395       i;
14396
14397     struct PackageInfo
14398       *info;
14399
14400     SV
14401       *av_reference,
14402       *perl_exception,
14403       *reference,
14404       *rv,
14405       *sv;
14406
14407     PERL_UNUSED_VAR(ref);
14408     PERL_UNUSED_VAR(ix);
14409     exception=AcquireExceptionInfo();
14410     perl_exception=newSVpv("",0);
14411     sv=NULL;
14412     av=NULL;
14413     attribute=NULL;
14414     if (sv_isobject(ST(0)) == 0)
14415       {
14416         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14417           PackageName);
14418         goto PerlException;
14419       }
14420     reference=SvRV(ST(0));
14421     hv=SvSTASH(reference);
14422     av=newAV();
14423     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14424     SvREFCNT_dec(av);
14425     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14426     if (image == (Image *) NULL)
14427       {
14428         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14429           PackageName);
14430         goto PerlException;
14431       }
14432     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14433     /*
14434       Get attribute.
14435     */
14436     crop_geometry=(char *) NULL;
14437     geometry=(char *) NULL;
14438     for (i=2; i < items; i+=2)
14439     {
14440       attribute=(char *) SvPV(ST(i-1),na);
14441       switch (*attribute)
14442       {
14443         case 'c':
14444         case 'C':
14445         {
14446           if (LocaleCompare(attribute,"crop") == 0)
14447             {
14448               crop_geometry=SvPV(ST(i),na);
14449               break;
14450             }
14451           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14452             attribute);
14453           break;
14454         }
14455         case 'g':
14456         case 'G':
14457         {
14458           if (LocaleCompare(attribute,"geometry") == 0)
14459             {
14460               geometry=SvPV(ST(i),na);
14461               break;
14462             }
14463           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14464             attribute);
14465           break;
14466         }
14467         default:
14468         {
14469           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14470             attribute);
14471           break;
14472         }
14473       }
14474     }
14475     for ( ; image; image=image->next)
14476     {
14477       clone=CloneImage(image,0,0,MagickTrue,exception);
14478       if (clone == (Image *) NULL)
14479         goto PerlException;
14480       TransformImage(&clone,crop_geometry,geometry,exception);
14481       for ( ; clone; clone=clone->next)
14482       {
14483         AddImageToRegistry(sv,clone);
14484         rv=newRV(sv);
14485         av_push(av,sv_bless(rv,hv));
14486         SvREFCNT_dec(sv);
14487       }
14488     }
14489     exception=DestroyExceptionInfo(exception);
14490     ST(0)=av_reference;
14491     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14492     XSRETURN(1);
14493
14494   PerlException:
14495     InheritPerlException(exception,perl_exception);
14496     exception=DestroyExceptionInfo(exception);
14497     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14498     SvPOK_on(perl_exception);
14499     ST(0)=sv_2mortal(perl_exception);
14500     XSRETURN(1);
14501   }
14502 \f
14503 #
14504 ###############################################################################
14505 #                                                                             #
14506 #                                                                             #
14507 #                                                                             #
14508 #   W r i t e                                                                 #
14509 #                                                                             #
14510 #                                                                             #
14511 #                                                                             #
14512 ###############################################################################
14513 #
14514 #
14515 void
14516 Write(ref,...)
14517   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14518   ALIAS:
14519     WriteImage    = 1
14520     write         = 2
14521     writeimage    = 3
14522   PPCODE:
14523   {
14524     char
14525       filename[MagickPathExtent];
14526
14527     ExceptionInfo
14528       *exception;
14529
14530     Image
14531       *image,
14532       *next;
14533
14534     register ssize_t
14535       i;
14536
14537     ssize_t
14538       number_images,
14539       scene;
14540
14541     struct PackageInfo
14542       *info,
14543       *package_info;
14544
14545     SV
14546       *perl_exception,
14547       *reference;
14548
14549     PERL_UNUSED_VAR(ref);
14550     PERL_UNUSED_VAR(ix);
14551     exception=AcquireExceptionInfo();
14552     perl_exception=newSVpv("",0);
14553     number_images=0;
14554     package_info=(struct PackageInfo *) NULL;
14555     if (sv_isobject(ST(0)) == 0)
14556       {
14557         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14558           PackageName);
14559         goto PerlException;
14560       }
14561     reference=SvRV(ST(0));
14562     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14563     if (image == (Image *) NULL)
14564       {
14565         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14566           PackageName);
14567         goto PerlException;
14568       }
14569     package_info=ClonePackageInfo(info,exception);
14570     if (items == 2)
14571       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14572     else
14573       if (items > 2)
14574         for (i=2; i < items; i+=2)
14575           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14576             exception);
14577     (void) CopyMagickString(filename,package_info->image_info->filename,
14578       MagickPathExtent);
14579     scene=0;
14580     for (next=image; next; next=next->next)
14581     {
14582       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14583       next->scene=scene++;
14584     }
14585     *package_info->image_info->magick='\0';
14586     SetImageInfo(package_info->image_info,(unsigned int)
14587       GetImageListLength(image),exception);
14588     for (next=image; next; next=next->next)
14589     {
14590       (void) WriteImage(package_info->image_info,next,exception);
14591       number_images++;
14592       if (package_info->image_info->adjoin)
14593         break;
14594     }
14595
14596   PerlException:
14597     if (package_info != (struct PackageInfo *) NULL)
14598       DestroyPackageInfo(package_info);
14599     InheritPerlException(exception,perl_exception);
14600     exception=DestroyExceptionInfo(exception);
14601     sv_setiv(perl_exception,(IV) number_images);
14602     SvPOK_on(perl_exception);
14603     ST(0)=sv_2mortal(perl_exception);
14604     XSRETURN(1);
14605   }