]> granicus.if.org Git - imagemagick/blob - PerlMagick/quantum/quantum.xs.in
664c9e8262bb68e0cdd3ba4599f5fad0f3684d8c
[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-2019 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 %    https://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  34
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   NullReference = 0,
146   ArrayReference = (~0),
147   RealReference = (~0)-1,
148   FileReference = (~0)-2,
149   ImageReference = (~0)-3,
150   IntegerReference = (~0)-4,
151   StringReference = (~0)-5
152 } MagickReference;
153
154 typedef struct _Arguments
155 {
156   const char
157     *method;
158
159   ssize_t
160     type;
161 } Arguments;
162
163 struct ArgumentList
164 {
165   ssize_t
166     integer_reference;
167
168   double
169     real_reference;
170
171   const char
172     *string_reference;
173
174   Image
175     *image_reference;
176
177   SV
178     *array_reference;
179
180   FILE
181     *file_reference;
182
183   size_t
184     length;
185 };
186
187 struct PackageInfo
188 {
189   ImageInfo
190     *image_info;
191 };
192
193 typedef void
194   *Image__Magick__@MAGICK_ABI_SUFFIX@;  /* data type for the Image::Magick::@MAGICK_ABI_NAME@ package */
195 \f
196 /*
197   Static declarations.
198 */
199 static struct
200   Methods
201   {
202     const char
203       *name;
204
205     Arguments
206       arguments[MaxArguments];
207   } Methods[] =
208   {
209     { "Comment", { {"comment", StringReference} } },
210     { "Label", { {"label", StringReference} } },
211     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
212       {"channel", MagickChannelOptions} } },
213     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
214     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
215       {"height", IntegerReference}, {"fill", StringReference},
216       {"bordercolor", StringReference}, {"color", StringReference},
217       {"compose", MagickComposeOptions} } },
218     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
219       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
220     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
221       {"height", IntegerReference}, {"x", IntegerReference},
222       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
223     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
224       {"height", IntegerReference}, {"x", IntegerReference},
225       {"y", IntegerReference}, {"fuzz", StringReference},
226       {"gravity", MagickGravityOptions} } },
227     { "Despeckle", { { (const char *) NULL, NullReference } } },
228     { "Edge", { {"radius", RealReference} } },
229     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
230       {"sigma", RealReference} } },
231     { "Enhance", { { (const char *) NULL, NullReference } } },
232     { "Flip", { { (const char *) NULL, NullReference } } },
233     { "Flop", { { (const char *) NULL, NullReference } } },
234     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
235       {"height", IntegerReference}, {"inner", IntegerReference},
236       {"outer", IntegerReference}, {"fill", StringReference},
237       {"color", StringReference}, {"compose", MagickComposeOptions} } },
238     { "Implode", { {"amount", RealReference},
239       {"interpolate", MagickInterpolateOptions} } },
240     { "Magnify", { { (const char *) NULL, NullReference } } },
241     { "MedianFilter", { {"geometry", StringReference},
242       {"width", IntegerReference}, {"height", IntegerReference},
243       {"channel", MagickChannelOptions} } },
244     { "Minify", { { (const char *) NULL, NullReference } } },
245     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
246     { "ReduceNoise", { {"geometry", StringReference},
247       {"width", IntegerReference},{"height", IntegerReference},
248       {"channel", MagickChannelOptions} } },
249     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
250       {"y", IntegerReference} } },
251     { "Rotate", { {"degrees", RealReference},
252       {"background", StringReference} } },
253     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
254       {"height", IntegerReference} } },
255     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
256       {"height", IntegerReference} } },
257     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
258       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
259     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
260       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
261     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
262       {"y", RealReference}, { "fill", StringReference},
263       {"color", StringReference} } },
264     { "Spread", { {"radius", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Swirl", { {"degrees", RealReference},
267       {"interpolate", MagickInterpolateOptions} } },
268     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
269       {"height", IntegerReference}, {"filter", MagickFilterOptions},
270       {"support", StringReference } } },
271     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
272       {"height", IntegerReference}, {"filter", MagickFilterOptions},
273       {"support", RealReference } } },
274     { "Annotate", { {"text", StringReference}, {"font", StringReference},
275       {"pointsize", RealReference}, {"density", StringReference},
276       {"undercolor", StringReference}, {"stroke", StringReference},
277       {"fill", StringReference}, {"geometry", StringReference},
278       {"sans", StringReference}, {"x", RealReference},
279       {"y", RealReference}, {"gravity", MagickGravityOptions},
280       {"translate", StringReference}, {"scale", StringReference},
281       {"rotate", RealReference}, {"skewX", RealReference},
282       {"skewY", RealReference}, {"strokewidth", RealReference},
283       {"antialias", MagickBooleanOptions}, {"family", StringReference},
284       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
285       {"weight", IntegerReference}, {"align", MagickAlignOptions},
286       {"encoding", StringReference}, {"affine", ArrayReference},
287       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
288       {"tile", ImageReference}, {"kerning", RealReference},
289       {"interline-spacing", RealReference},
290       {"interword-spacing", RealReference},
291       {"direction", MagickDirectionOptions},
292       {"decorate", MagickDecorateOptions} } },
293     { "ColorFloodfill", { {"geometry", StringReference},
294       {"x", IntegerReference}, {"y", IntegerReference},
295       {"fill", StringReference}, {"bordercolor", StringReference},
296       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
297     { "Composite", { {"image", ImageReference},
298       {"compose", MagickComposeOptions}, {"geometry", StringReference},
299       {"x", IntegerReference}, {"y", IntegerReference},
300       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
301       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
302       {"color", StringReference}, {"mask", ImageReference},
303       {"channel", MagickChannelOptions},
304       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
305       {"blend", StringReference}, {"clip-to-self", MagickBooleanOptions} } },
306     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
307     { "CycleColormap", { {"display", IntegerReference} } },
308     { "Draw", { {"primitive", MagickPrimitiveOptions},
309       {"points", StringReference}, {"method", MagickMethodOptions},
310       {"stroke", StringReference}, {"fill", StringReference},
311       {"strokewidth", RealReference}, {"font", StringReference},
312       {"bordercolor", StringReference}, {"x", RealReference},
313       {"y", RealReference}, {"translate", StringReference},
314       {"scale", StringReference}, {"rotate", RealReference},
315       {"skewX", RealReference}, {"skewY", RealReference},
316       {"tile", ImageReference}, {"pointsize", RealReference},
317       {"antialias", MagickBooleanOptions}, {"density", StringReference},
318       {"linewidth", RealReference}, {"affine", ArrayReference},
319       {"stroke-dashoffset", RealReference},
320       {"stroke-dasharray", ArrayReference},
321       {"interpolate", MagickInterpolateOptions},
322       {"origin", StringReference}, {"text", StringReference},
323       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
324       {"vector-graphics", StringReference}, {"kerning", RealReference},
325       {"interline-spacing", RealReference},
326       {"interword-spacing", RealReference},
327       {"direction", MagickDirectionOptions} } },
328     { "Equalize", { {"channel", MagickChannelOptions} } },
329     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
330       {"red", RealReference}, {"green", RealReference},
331       {"blue", RealReference} } },
332     { "Map", { {"image", ImageReference},
333       {"dither-method", MagickDitherOptions} } },
334     { "MatteFloodfill", { {"geometry", StringReference},
335       {"x", IntegerReference}, {"y", IntegerReference},
336       {"opacity", StringReference}, {"bordercolor", StringReference},
337       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
338     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
339       {"saturation", RealReference}, {"whiteness", RealReference},
340       {"brightness", RealReference}, {"lightness", RealReference},
341       {"blackness", RealReference} } },
342     { "Negate", { {"gray", MagickBooleanOptions},
343       {"channel", MagickChannelOptions} } },
344     { "Normalize", { {"channel", MagickChannelOptions} } },
345     { "NumberColors", { { (const char *) NULL, NullReference } } },
346     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
347       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
348       {"invert", MagickBooleanOptions} } },
349     { "Quantize", { {"colors", IntegerReference},
350       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
351       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
352       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
353       {"dither-method", MagickDitherOptions} } },
354     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
355       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
356     { "Segment", { {"geometry", StringReference},
357       {"cluster-threshold", RealReference},
358       {"smoothing-threshold", RealReference},
359       {"colorspace", MagickColorspaceOptions},
360       {"verbose", MagickBooleanOptions} } },
361     { "Signature", { { (const char *) NULL, NullReference } } },
362     { "Solarize", { {"geometry", StringReference},
363       {"threshold", StringReference} } },
364     { "Sync", { { (const char *) NULL, NullReference } } },
365     { "Texture", { {"texture", ImageReference} } },
366     { "Evaluate", { {"value", RealReference},
367       {"operator", MagickEvaluateOptions},
368       {"channel", MagickChannelOptions} } },
369     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
370       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
371     { "Threshold", { {"threshold", StringReference},
372       {"channel", MagickChannelOptions} } },
373     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
374       {"sigma", RealReference} } },
375     { "Trim", { {"fuzz", StringReference} } },
376     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
377       {"wavelength", RealReference},
378       {"interpolate", MagickInterpolateOptions} } },
379     { "Separate", { {"channel", MagickChannelOptions} } },
380     { "Condense", { { (const char *) NULL, NullReference } } },
381     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
382       {"y", IntegerReference} } },
383     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
384     { "Deconstruct", { { (const char *) NULL, NullReference } } },
385     { "GaussianBlur", { {"geometry", StringReference},
386       {"radius", RealReference}, {"sigma", RealReference},
387       {"channel", MagickChannelOptions} } },
388     { "Convolve", { {"coefficients", ArrayReference},
389       {"channel", MagickChannelOptions}, {"bias", StringReference},
390       {"kernel", StringReference} } },
391     { "Profile", { {"name", StringReference}, {"profile", StringReference},
392       { "rendering-intent", MagickIntentOptions},
393       { "black-point-compensation", MagickBooleanOptions} } },
394     { "UnsharpMask", { {"geometry", StringReference},
395       {"radius", RealReference}, {"sigma", RealReference},
396       {"gain", RealReference}, {"threshold", RealReference},
397       {"channel", MagickChannelOptions} } },
398     { "MotionBlur", { {"geometry", StringReference},
399       {"radius", RealReference}, {"sigma", RealReference},
400       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
401     { "OrderedDither", { {"threshold", StringReference},
402       {"channel", MagickChannelOptions} } },
403     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
404       {"height", IntegerReference} } },
405     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
406       {"white-point", RealReference}, {"gamma", RealReference},
407       {"channel", MagickChannelOptions}, {"level", StringReference} } },
408     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
409     { "AffineTransform", { {"affine", ArrayReference},
410       {"translate", StringReference}, {"scale", StringReference},
411       {"rotate", RealReference}, {"skewX", RealReference},
412       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
413       {"background", StringReference} } },
414     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
415     { "AdaptiveThreshold", { {"geometry", StringReference},
416       {"width", IntegerReference}, {"height", IntegerReference},
417       {"bias", RealReference} } },
418     { "Resample", { {"density", StringReference}, {"x", RealReference},
419       {"y", RealReference}, {"filter", MagickFilterOptions},
420       {"support", RealReference } } },
421     { "Describe", { {"file", FileReference} } },
422     { "BlackThreshold", { {"threshold", StringReference},
423       {"channel", MagickChannelOptions} } },
424     { "WhiteThreshold", { {"threshold", StringReference},
425       {"channel", MagickChannelOptions} } },
426     { "RotationalBlur", { {"geometry", StringReference},
427       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
428     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
429       {"height", IntegerReference} } },
430     { "Strip", { { (const char *) NULL, NullReference } } },
431     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
432     { "Channel", { {"channel", MagickChannelOptions} } },
433     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
434       {"height", IntegerReference}, {"x", IntegerReference},
435       {"y", IntegerReference}, {"fuzz", StringReference},
436       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
437     { "Posterize", { {"levels", IntegerReference},
438       {"dither", MagickBooleanOptions} } },
439     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
440       {"sigma", RealReference}, {"x", IntegerReference},
441       {"y", IntegerReference} } },
442     { "Identify", { {"file", FileReference}, {"features", StringReference},
443       {"unique", MagickBooleanOptions} } },
444     { "SepiaTone", { {"threshold", RealReference} } },
445     { "SigmoidalContrast", { {"geometry", StringReference},
446       {"contrast", RealReference}, {"mid-point", RealReference},
447       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
448     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
449       {"height", IntegerReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"fuzz", StringReference},
451       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
452     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
453       {"sigma", RealReference}, {"x", IntegerReference},
454       {"y", IntegerReference}, {"background", StringReference} } },
455     { "ContrastStretch", { {"levels", StringReference},
456       {"black-point", RealReference},{"white-point", RealReference},
457       {"channel", MagickChannelOptions} } },
458     { "Sans0", { { (const char *) NULL, NullReference } } },
459     { "Sans1", { { (const char *) NULL, NullReference } } },
460     { "AdaptiveSharpen", { {"geometry", StringReference},
461       {"radius", RealReference}, {"sigma", RealReference},
462       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
463     { "Transpose", { { (const char *) NULL, NullReference } } },
464     { "Transverse", { { (const char *) NULL, NullReference } } },
465     { "AutoOrient", { { (const char *) NULL, NullReference } } },
466     { "AdaptiveBlur", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"channel", MagickChannelOptions} } },
469     { "Sketch", { {"geometry", StringReference},
470       {"radius", RealReference}, {"sigma", RealReference},
471       {"angle", RealReference} } },
472     { "UniqueColors", { { (const char *) NULL, NullReference } } },
473     { "AdaptiveResize", { {"geometry", StringReference},
474       {"width", IntegerReference}, {"height", IntegerReference},
475       {"filter", MagickFilterOptions}, {"support", StringReference },
476       {"blur", RealReference } } },
477     { "ClipMask", { {"mask", ImageReference} } },
478     { "LinearStretch", { {"levels", StringReference},
479       {"black-point", RealReference},{"white-point", RealReference} } },
480     { "ColorMatrix", { {"matrix", ArrayReference} } },
481     { "Mask", { {"mask", ImageReference} } },
482     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
483       {"font", StringReference}, {"stroke", StringReference},
484       {"fill", StringReference}, {"strokewidth", RealReference},
485       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
486       {"background", StringReference},
487       {"interpolate", MagickInterpolateOptions} } },
488     { "FloodfillPaint", { {"geometry", StringReference},
489       {"x", IntegerReference}, {"y", IntegerReference},
490       {"fill", StringReference}, {"bordercolor", StringReference},
491       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
492       {"invert", MagickBooleanOptions} } },
493     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
494       {"virtual-pixel", MagickVirtualPixelOptions},
495       {"best-fit", MagickBooleanOptions} } },
496     { "Clut", { {"image", ImageReference},
497       {"interpolate", MagickInterpolateOptions},
498       {"channel", MagickChannelOptions} } },
499     { "LiquidRescale", { {"geometry", StringReference},
500       {"width", IntegerReference}, {"height", IntegerReference},
501       {"delta-x", RealReference}, {"rigidity", RealReference } } },
502     { "Encipher", { {"passphrase", StringReference} } },
503     { "Decipher", { {"passphrase", StringReference} } },
504     { "Deskew", { {"geometry", StringReference},
505       {"threshold", StringReference} } },
506     { "Remap", { {"image", ImageReference},
507       {"dither-method", MagickDitherOptions} } },
508     { "SparseColor", { {"points", ArrayReference},
509       {"method", MagickSparseColorOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions},
511       {"channel", MagickChannelOptions} } },
512     { "Function", { {"parameters", ArrayReference},
513       {"function", MagickFunctionOptions},
514       {"virtual-pixel", MagickVirtualPixelOptions} } },
515     { "SelectiveBlur", { {"geometry", StringReference},
516       {"radius", RealReference}, {"sigma", RealReference},
517       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
518     { "HaldClut", { {"image", ImageReference},
519       {"channel", MagickChannelOptions} } },
520     { "BlueShift", { {"factor", StringReference} } },
521     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
522     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
523     { "ColorDecisionList", {
524       {"color-correction-collection", StringReference} } },
525     { "AutoGamma", { {"channel", MagickChannelOptions} } },
526     { "AutoLevel", { {"channel", MagickChannelOptions} } },
527     { "LevelColors", { {"invert", MagickBooleanOptions},
528       {"black-point", StringReference}, {"white-point", StringReference},
529       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
530     { "Clamp", { {"channel", MagickChannelOptions} } },
531     { "BrightnessContrast", { {"levels", StringReference},
532       {"brightness", RealReference},{"contrast", RealReference},
533       {"channel", MagickChannelOptions} } },
534     { "Morphology", { {"kernel", StringReference},
535       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
536       {"iterations", IntegerReference} } },
537     { "Mode", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions} } },
540     { "Statistic", { {"geometry", StringReference},
541       {"width", IntegerReference},{"height", IntegerReference},
542       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
543     { "Perceptible", { {"epsilon", RealReference},
544       {"channel", MagickChannelOptions} } },
545     { "Poly", { {"terms", ArrayReference},
546       {"channel", MagickChannelOptions} } },
547     { "Grayscale", { {"method", MagickNoiseOptions} } },
548     { "CannyEdge", { {"geometry", StringReference},
549       {"radius", RealReference}, {"sigma", RealReference},
550       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
551     { "HoughLine", { {"geometry", StringReference},
552       {"width", IntegerReference}, {"height", IntegerReference},
553       {"threshold", IntegerReference} } },
554     { "MeanShift", { {"geometry", StringReference},
555       {"width", IntegerReference}, {"height", IntegerReference},
556       {"distance", RealReference} } },
557     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
558       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
559     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
560     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
561       {"width", IntegerReference}, {"height", IntegerReference},
562       {"x", IntegerReference}, {"y", IntegerReference},
563       {"gravity", MagickGravityOptions}, {"offset", StringReference},
564       {"dx", IntegerReference}, {"dy", IntegerReference} } },
565     { "Color", { {"color", StringReference} } },
566     { "WaveletDenoise", {  {"geometry", StringReference},
567       {"threshold", RealReference}, {"softness", RealReference},
568       {"channel", MagickChannelOptions} } },
569     { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
570     { "AutoThreshold", { {"method", MagickAutoThresholdOptions} } },
571     { "RangeThreshold", { {"geometry", StringReference},
572       {"low-black", RealReference}, {"low-white", RealReference},
573       {"high-white", RealReference}, {"high-black", RealReference},
574       {"channel", MagickChannelOptions} } },
575     { "CLAHE", { {"geometry", StringReference}, {"width", IntegerReference},
576       {"height", IntegerReference}, {"number-bins", IntegerReference},
577       {"clip-limit", RealReference} } },
578     { "OTSUThreshold", { {"channel", MagickChannelOptions} } },
579   };
580
581 static SplayTreeInfo
582   *magick_registry = (SplayTreeInfo *) NULL;
583 \f
584 /*
585   Forward declarations.
586 */
587 static Image
588   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
589
590 static ssize_t
591   strEQcase(const char *,const char *);
592 \f
593 /*
594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595 %                                                                             %
596 %                                                                             %
597 %                                                                             %
598 %   C l o n e P a c k a g e I n f o                                           %
599 %                                                                             %
600 %                                                                             %
601 %                                                                             %
602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
603 %
604 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
605 %  a new one.
606 %
607 %  The format of the ClonePackageInfo routine is:
608 %
609 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
610 %        exception)
611 %
612 %  A description of each parameter follows:
613 %
614 %    o info: a structure of type info.
615 %
616 %    o exception: Return any errors or warnings in this structure.
617 %
618 */
619 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
620   ExceptionInfo *exception)
621 {
622   struct PackageInfo
623     *clone_info;
624
625   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
626   if (clone_info == (struct PackageInfo *) NULL)
627     {
628       ThrowPerlException(exception,ResourceLimitError,
629         "UnableToClonePackageInfo",PackageName);
630       return((struct PackageInfo *) NULL);
631     }
632   if (info == (struct PackageInfo *) NULL)
633     {
634       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
635       return(clone_info);
636     }
637   *clone_info=(*info);
638   clone_info->image_info=CloneImageInfo(info->image_info);
639   return(clone_info);
640 }
641 \f
642 /*
643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
644 %                                                                             %
645 %                                                                             %
646 %                                                                             %
647 %   c o n s t a n t                                                           %
648 %                                                                             %
649 %                                                                             %
650 %                                                                             %
651 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652 %
653 %  constant() returns a double value for the specified name.
654 %
655 %  The format of the constant routine is:
656 %
657 %      double constant(char *name,ssize_t sans)
658 %
659 %  A description of each parameter follows:
660 %
661 %    o value: Method constant returns a double value for the specified name.
662 %
663 %    o name: The name of the constant.
664 %
665 %    o sans: This integer value is not used.
666 %
667 */
668 static double constant(char *name,ssize_t sans)
669 {
670   (void) sans;
671   errno=0;
672   switch (*name)
673   {
674     case 'B':
675     {
676       if (strEQ(name,"BlobError"))
677         return(BlobError);
678       if (strEQ(name,"BlobWarning"))
679         return(BlobWarning);
680       break;
681     }
682     case 'C':
683     {
684       if (strEQ(name,"CacheError"))
685         return(CacheError);
686       if (strEQ(name,"CacheWarning"))
687         return(CacheWarning);
688       if (strEQ(name,"CoderError"))
689         return(CoderError);
690       if (strEQ(name,"CoderWarning"))
691         return(CoderWarning);
692       if (strEQ(name,"ConfigureError"))
693         return(ConfigureError);
694       if (strEQ(name,"ConfigureWarning"))
695         return(ConfigureWarning);
696       if (strEQ(name,"CorruptImageError"))
697         return(CorruptImageError);
698       if (strEQ(name,"CorruptImageWarning"))
699         return(CorruptImageWarning);
700       break;
701     }
702     case 'D':
703     {
704       if (strEQ(name,"DelegateError"))
705         return(DelegateError);
706       if (strEQ(name,"DelegateWarning"))
707         return(DelegateWarning);
708       if (strEQ(name,"DrawError"))
709         return(DrawError);
710       if (strEQ(name,"DrawWarning"))
711         return(DrawWarning);
712       break;
713     }
714     case 'E':
715     {
716       if (strEQ(name,"ErrorException"))
717         return(ErrorException);
718       if (strEQ(name,"ExceptionError"))
719         return(CoderError);
720       if (strEQ(name,"ExceptionWarning"))
721         return(CoderWarning);
722       break;
723     }
724     case 'F':
725     {
726       if (strEQ(name,"FatalErrorException"))
727         return(FatalErrorException);
728       if (strEQ(name,"FileOpenError"))
729         return(FileOpenError);
730       if (strEQ(name,"FileOpenWarning"))
731         return(FileOpenWarning);
732       break;
733     }
734     case 'I':
735     {
736       if (strEQ(name,"ImageError"))
737         return(ImageError);
738       if (strEQ(name,"ImageWarning"))
739         return(ImageWarning);
740       break;
741     }
742     case 'M':
743     {
744       if (strEQ(name,"MaxRGB"))
745         return(QuantumRange);
746       if (strEQ(name,"MissingDelegateError"))
747         return(MissingDelegateError);
748       if (strEQ(name,"MissingDelegateWarning"))
749         return(MissingDelegateWarning);
750       if (strEQ(name,"ModuleError"))
751         return(ModuleError);
752       if (strEQ(name,"ModuleWarning"))
753         return(ModuleWarning);
754       break;
755     }
756     case 'O':
757     {
758       if (strEQ(name,"Opaque"))
759         return(OpaqueAlpha);
760       if (strEQ(name,"OptionError"))
761         return(OptionError);
762       if (strEQ(name,"OptionWarning"))
763         return(OptionWarning);
764       break;
765     }
766     case 'Q':
767     {
768       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
769         return(MAGICKCORE_QUANTUM_DEPTH);
770       if (strEQ(name,"QuantumDepth"))
771         return(MAGICKCORE_QUANTUM_DEPTH);
772       if (strEQ(name,"QuantumRange"))
773         return(QuantumRange);
774       break;
775     }
776     case 'R':
777     {
778       if (strEQ(name,"ResourceLimitError"))
779         return(ResourceLimitError);
780       if (strEQ(name,"ResourceLimitWarning"))
781         return(ResourceLimitWarning);
782       if (strEQ(name,"RegistryError"))
783         return(RegistryError);
784       if (strEQ(name,"RegistryWarning"))
785         return(RegistryWarning);
786       break;
787     }
788     case 'S':
789     {
790       if (strEQ(name,"StreamError"))
791         return(StreamError);
792       if (strEQ(name,"StreamWarning"))
793         return(StreamWarning);
794       if (strEQ(name,"Success"))
795         return(0);
796       break;
797     }
798     case 'T':
799     {
800       if (strEQ(name,"Transparent"))
801         return(TransparentAlpha);
802       if (strEQ(name,"TypeError"))
803         return(TypeError);
804       if (strEQ(name,"TypeWarning"))
805         return(TypeWarning);
806       break;
807     }
808     case 'W':
809     {
810       if (strEQ(name,"WarningException"))
811         return(WarningException);
812       break;
813     }
814     case 'X':
815     {
816       if (strEQ(name,"XServerError"))
817         return(XServerError);
818       if (strEQ(name,"XServerWarning"))
819         return(XServerWarning);
820       break;
821     }
822   }
823   errno=EINVAL;
824   return(0);
825 }
826 \f
827 /*
828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829 %                                                                             %
830 %                                                                             %
831 %                                                                             %
832 %   D e s t r o y P a c k a g e I n f o                                       %
833 %                                                                             %
834 %                                                                             %
835 %                                                                             %
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 %
838 %  Method DestroyPackageInfo frees a previously created info structure.
839 %
840 %  The format of the DestroyPackageInfo routine is:
841 %
842 %      DestroyPackageInfo(struct PackageInfo *info)
843 %
844 %  A description of each parameter follows:
845 %
846 %    o info: a structure of type info.
847 %
848 */
849 static void DestroyPackageInfo(struct PackageInfo *info)
850 {
851   info->image_info=DestroyImageInfo(info->image_info);
852   info=(struct PackageInfo *) RelinquishMagickMemory(info);
853 }
854 \f
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 %                                                                             %
858 %                                                                             %
859 %                                                                             %
860 %   G e t L i s t                                                             %
861 %                                                                             %
862 %                                                                             %
863 %                                                                             %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 %  Method GetList is recursively called by SetupList to traverse the
867 %  Image__Magick reference.  If building an reference_vector (see SetupList),
868 %  *current is the current position in *reference_vector and *last is the final
869 %  entry in *reference_vector.
870 %
871 %  The format of the GetList routine is:
872 %
873 %      GetList(info)
874 %
875 %  A description of each parameter follows:
876 %
877 %    o info: a structure of type info.
878 %
879 */
880 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
881   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
882 {
883   Image
884     *image;
885
886   if (reference == (SV *) NULL)
887     return(NULL);
888   switch (SvTYPE(reference))
889   {
890     case SVt_PVAV:
891     {
892       AV
893         *av;
894
895       Image
896         *head,
897         *previous;
898
899       register ssize_t
900         i;
901
902       ssize_t
903         n;
904
905       /*
906         Array of images.
907       */
908       previous=(Image *) NULL;
909       head=(Image *) NULL;
910       av=(AV *) reference;
911       n=av_len(av);
912       for (i=0; i <= n; i++)
913       {
914         SV
915           **rv;
916
917         rv=av_fetch(av,i,0);
918         if (rv && *rv && sv_isobject(*rv))
919           {
920             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
921               exception);
922             if (image == (Image *) NULL)
923               continue;
924             if (image == previous)
925               {
926                 image=CloneImage(image,0,0,MagickTrue,exception);
927                 if (image == (Image *) NULL)
928                   return(NULL);
929               }
930             image->previous=previous;
931             *(previous ? &previous->next : &head)=image;
932             for (previous=image; previous->next; previous=previous->next) ;
933           }
934       }
935       return(head);
936     }
937     case SVt_PVMG:
938     {
939       /*
940         Blessed scalar, one image.
941       */
942       image=INT2PTR(Image *,SvIV(reference));
943       if (image == (Image *) NULL)
944         return(NULL);
945       image->previous=(Image *) NULL;
946       image->next=(Image *) NULL;
947       if (reference_vector)
948         {
949           if (*current == *last)
950             {
951               *last+=256;
952               if (*reference_vector == (SV **) NULL)
953                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
954                   sizeof(*reference_vector));
955               else
956                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
957                   *last,sizeof(*reference_vector));
958             }
959           if (*reference_vector == (SV **) NULL)
960             {
961               ThrowPerlException(exception,ResourceLimitError,
962                 "MemoryAllocationFailed",PackageName);
963               return((Image *) NULL);
964             }
965           (*reference_vector)[*current]=reference;
966           (*reference_vector)[++(*current)]=NULL;
967         }
968       return(image);
969     }
970     default:
971       break;
972   }
973   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
974     (double) SvTYPE(reference));
975   return((Image *) NULL);
976 }
977 \f
978 /*
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 %                                                                             %
981 %                                                                             %
982 %                                                                             %
983 %   G e t P a c k a g e I n f o                                               %
984 %                                                                             %
985 %                                                                             %
986 %                                                                             %
987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
988 %
989 %  Method GetPackageInfo looks up or creates an info structure for the given
990 %  Image__Magick reference.  If it does create a new one, the information in
991 %  package_info is used to initialize it.
992 %
993 %  The format of the GetPackageInfo routine is:
994 %
995 %      struct PackageInfo *GetPackageInfo(void *reference,
996 %        struct PackageInfo *package_info,ExceptionInfo *exception)
997 %
998 %  A description of each parameter follows:
999 %
1000 %    o info: a structure of type info.
1001 %
1002 %    o exception: Return any errors or warnings in this structure.
1003 %
1004 */
1005 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
1006   struct PackageInfo *package_info,ExceptionInfo *exception)
1007 {
1008   char
1009     message[MagickPathExtent];
1010
1011   struct PackageInfo
1012     *clone_info;
1013
1014   SV
1015     *sv;
1016
1017   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1018     PackageName,XS_VERSION,reference);
1019   sv=perl_get_sv(message,(TRUE | 0x02));
1020   if (sv == (SV *) NULL)
1021     {
1022       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1023         message);
1024       return(package_info);
1025     }
1026   if (SvREFCNT(sv) == 0)
1027     (void) SvREFCNT_inc(sv);
1028   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1029     return(clone_info);
1030   clone_info=ClonePackageInfo(package_info,exception);
1031   sv_setiv(sv,PTR2IV(clone_info));
1032   return(clone_info);
1033 }
1034 \f
1035 /*
1036 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037 %                                                                             %
1038 %                                                                             %
1039 %                                                                             %
1040 %   S e t A t t r i b u t e                                                   %
1041 %                                                                             %
1042 %                                                                             %
1043 %                                                                             %
1044 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045 %
1046 %  SetAttribute() sets the attribute to the value in sval.  This can change
1047 %  either or both of image or info.
1048 %
1049 %  The format of the SetAttribute routine is:
1050 %
1051 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1052 %        SV *sval,ExceptionInfo *exception)
1053 %
1054 %  A description of each parameter follows:
1055 %
1056 %    o list: a list of strings.
1057 %
1058 %    o string: a character string.
1059 %
1060 */
1061
1062 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1063 {
1064   char
1065     *q;
1066
1067   double
1068     value;
1069
1070   value=InterpretSiPrefixValue(string,&q);
1071   if (*q == '%')
1072     value*=interval/100.0;
1073   return(value);
1074 }
1075
1076 static inline double StringToDouble(const char *string,char **sentinal)
1077 {
1078   return(InterpretLocaleValue(string,sentinal));
1079 }
1080
1081 static double StringToDoubleInterval(const char *string,const double interval)
1082 {
1083   char
1084     *q;
1085
1086   double
1087     value;
1088
1089   value=InterpretLocaleValue(string,&q);
1090   if (*q == '%')
1091     value*=interval/100.0;
1092   return(value);
1093 }
1094
1095 static inline ssize_t StringToLong(const char *value)
1096 {
1097   return(strtol(value,(char **) NULL,10));
1098 }
1099
1100 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1101   const char *attribute,SV *sval,ExceptionInfo *exception)
1102 {
1103   GeometryInfo
1104     geometry_info;
1105
1106   long
1107     x,
1108     y;
1109
1110   PixelInfo
1111     pixel;
1112
1113   MagickStatusType
1114     flags;
1115
1116   PixelInfo
1117     *color,
1118     target_color;
1119
1120   ssize_t
1121     sp;
1122
1123   switch (*attribute)
1124   {
1125     case 'A':
1126     case 'a':
1127     {
1128       if (LocaleCompare(attribute,"adjoin") == 0)
1129         {
1130           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1131             SvPV(sval,na)) : SvIV(sval);
1132           if (sp < 0)
1133             {
1134               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1135                 SvPV(sval,na));
1136               break;
1137             }
1138           if (info)
1139             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"alpha") == 0)
1143         {
1144           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1145             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1146           if (sp < 0)
1147             {
1148               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1149                 SvPV(sval,na));
1150               break;
1151             }
1152           for ( ; image; image=image->next)
1153             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1154               exception);
1155           break;
1156         }
1157       if (LocaleCompare(attribute,"antialias") == 0)
1158         {
1159           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1160             SvPV(sval,na)) : SvIV(sval);
1161           if (sp < 0)
1162             {
1163               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1164                 SvPV(sval,na));
1165               break;
1166             }
1167           if (info)
1168             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1169           break;
1170         }
1171       if (LocaleCompare(attribute,"area-limit") == 0)
1172         {
1173           MagickSizeType
1174             limit;
1175
1176           limit=MagickResourceInfinity;
1177           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1178             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1179               100.0);
1180           (void) SetMagickResourceLimit(AreaResource,limit);
1181           break;
1182         }
1183       if (LocaleCompare(attribute,"attenuate") == 0)
1184         {
1185           if (info)
1186             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1187           break;
1188         }
1189       if (LocaleCompare(attribute,"authenticate") == 0)
1190         {
1191           if (info)
1192             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1193           break;
1194         }
1195       if (info)
1196         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1197       for ( ; image; image=image->next)
1198       {
1199         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1200         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1201       }
1202       break;
1203     }
1204     case 'B':
1205     case 'b':
1206     {
1207       if (LocaleCompare(attribute,"background") == 0)
1208         {
1209           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1210             exception);
1211           if (info)
1212             info->image_info->background_color=target_color;
1213           for ( ; image; image=image->next)
1214             image->background_color=target_color;
1215           break;
1216         }
1217       if (LocaleCompare(attribute,"blue-primary") == 0)
1218         {
1219           for ( ; image; image=image->next)
1220           {
1221             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1222             image->chromaticity.blue_primary.x=geometry_info.rho;
1223             image->chromaticity.blue_primary.y=geometry_info.sigma;
1224             if ((flags & SigmaValue) == 0)
1225               image->chromaticity.blue_primary.y=
1226                 image->chromaticity.blue_primary.x;
1227           }
1228           break;
1229         }
1230       if (LocaleCompare(attribute,"bordercolor") == 0)
1231         {
1232           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1233             exception);
1234           if (info)
1235             info->image_info->border_color=target_color;
1236           for ( ; image; image=image->next)
1237             image->border_color=target_color;
1238           break;
1239         }
1240       if (info)
1241         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1242       for ( ; image; image=image->next)
1243       {
1244         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1245         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1246       }
1247       break;
1248     }
1249     case 'C':
1250     case 'c':
1251     {
1252       if (LocaleCompare(attribute,"cache-threshold") == 0)
1253         {
1254           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1255             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1256           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1257             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1258           break;
1259         }
1260       if (LocaleCompare(attribute,"clip-mask") == 0)
1261         {
1262           Image
1263             *clip_mask;
1264
1265           clip_mask=(Image *) NULL;
1266           if (SvPOK(sval))
1267             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1268           for ( ; image; image=image->next)
1269             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1270           break;
1271         }
1272       if (LocaleNCompare(attribute,"colormap",8) == 0)
1273         {
1274           for ( ; image; image=image->next)
1275           {
1276             int
1277               items;
1278
1279             long
1280               i;
1281
1282             if (image->storage_class == DirectClass)
1283               continue;
1284             i=0;
1285             items=sscanf(attribute,"%*[^[][%ld",&i);
1286             (void) items;
1287             if (i > (ssize_t) image->colors)
1288               i%=image->colors;
1289             if ((strchr(SvPV(sval,na),',') == 0) ||
1290                 (strchr(SvPV(sval,na),')') != 0))
1291               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1292                 image->colormap+i,exception);
1293             else
1294               {
1295                 color=image->colormap+i;
1296                 pixel.red=color->red;
1297                 pixel.green=color->green;
1298                 pixel.blue=color->blue;
1299                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1300                 pixel.red=geometry_info.rho;
1301                 pixel.green=geometry_info.sigma;
1302                 pixel.blue=geometry_info.xi;
1303                 color->red=ClampToQuantum(pixel.red);
1304                 color->green=ClampToQuantum(pixel.green);
1305                 color->blue=ClampToQuantum(pixel.blue);
1306               }
1307           }
1308           break;
1309         }
1310       if (LocaleCompare(attribute,"colorspace") == 0)
1311         {
1312           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1313             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1314           if (sp < 0)
1315             {
1316               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1317                 SvPV(sval,na));
1318               break;
1319             }
1320           for ( ; image; image=image->next)
1321             (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
1322           break;
1323         }
1324       if (LocaleCompare(attribute,"comment") == 0)
1325         {
1326           for ( ; image; image=image->next)
1327             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1328               info ? info->image_info : (ImageInfo *) NULL,image,
1329               SvPV(sval,na),exception),exception);
1330           break;
1331         }
1332       if (LocaleCompare(attribute,"compression") == 0)
1333         {
1334           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1335             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1336           if (sp < 0)
1337             {
1338               ThrowPerlException(exception,OptionError,
1339                 "UnrecognizedImageCompression",SvPV(sval,na));
1340               break;
1341             }
1342           if (info)
1343             info->image_info->compression=(CompressionType) sp;
1344           for ( ; image; image=image->next)
1345             image->compression=(CompressionType) sp;
1346           break;
1347         }
1348       if (info)
1349         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1350       for ( ; image; image=image->next)
1351       {
1352         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1353         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1354       }
1355       break;
1356     }
1357     case 'D':
1358     case 'd':
1359     {
1360       if (LocaleCompare(attribute,"debug") == 0)
1361         {
1362           SetLogEventMask(SvPV(sval,na));
1363           break;
1364         }
1365       if (LocaleCompare(attribute,"delay") == 0)
1366         {
1367           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1368           for ( ; image; image=image->next)
1369           {
1370             image->delay=(size_t) floor(geometry_info.rho+0.5);
1371             if ((flags & SigmaValue) != 0)
1372               image->ticks_per_second=(ssize_t)
1373                 floor(geometry_info.sigma+0.5);
1374           }
1375           break;
1376         }
1377       if (LocaleCompare(attribute,"disk-limit") == 0)
1378         {
1379           MagickSizeType
1380             limit;
1381
1382           limit=MagickResourceInfinity;
1383           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1384             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1385               100.0);
1386           (void) SetMagickResourceLimit(DiskResource,limit);
1387           break;
1388         }
1389       if (LocaleCompare(attribute,"density") == 0)
1390         {
1391           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1392             {
1393               ThrowPerlException(exception,OptionError,"MissingGeometry",
1394                 SvPV(sval,na));
1395               break;
1396             }
1397           if (info)
1398             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1399           for ( ; image; image=image->next)
1400           {
1401             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1402             image->resolution.x=geometry_info.rho;
1403             image->resolution.y=geometry_info.sigma;
1404             if ((flags & SigmaValue) == 0)
1405               image->resolution.y=image->resolution.x;
1406           }
1407           break;
1408         }
1409       if (LocaleCompare(attribute,"depth") == 0)
1410         {
1411           if (info)
1412             info->image_info->depth=SvIV(sval);
1413           for ( ; image; image=image->next)
1414             (void) SetImageDepth(image,SvIV(sval),exception);
1415           break;
1416         }
1417       if (LocaleCompare(attribute,"dispose") == 0)
1418         {
1419           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1420             SvPV(sval,na)) : SvIV(sval);
1421           if (sp < 0)
1422             {
1423               ThrowPerlException(exception,OptionError,
1424                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1425               break;
1426             }
1427           for ( ; image; image=image->next)
1428             image->dispose=(DisposeType) sp;
1429           break;
1430         }
1431       if (LocaleCompare(attribute,"dither") == 0)
1432         {
1433           if (info)
1434             {
1435               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1436                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1437               if (sp < 0)
1438                 {
1439                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1440                     SvPV(sval,na));
1441                   break;
1442                 }
1443               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1444             }
1445           break;
1446         }
1447       if (LocaleCompare(attribute,"display") == 0)
1448         {
1449           display:
1450           if (info)
1451             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1452           break;
1453         }
1454       if (info)
1455         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1456       for ( ; image; image=image->next)
1457       {
1458         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1459         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1460       }
1461       break;
1462     }
1463     case 'E':
1464     case 'e':
1465     {
1466       if (LocaleCompare(attribute,"endian") == 0)
1467         {
1468           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1469             SvPV(sval,na)) : SvIV(sval);
1470           if (sp < 0)
1471             {
1472               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1473                 SvPV(sval,na));
1474               break;
1475             }
1476           if (info)
1477             info->image_info->endian=(EndianType) sp;
1478           for ( ; image; image=image->next)
1479             image->endian=(EndianType) sp;
1480           break;
1481         }
1482       if (LocaleCompare(attribute,"extract") == 0)
1483         {
1484           /*
1485             Set image extract geometry.
1486           */
1487           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1488           break;
1489         }
1490       if (info)
1491         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1492       for ( ; image; image=image->next)
1493       {
1494         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1495         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1496       }
1497       break;
1498     }
1499     case 'F':
1500     case 'f':
1501     {
1502       if (LocaleCompare(attribute,"filename") == 0)
1503         {
1504           if (info)
1505             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1506               MagickPathExtent);
1507           for ( ; image; image=image->next)
1508             (void) CopyMagickString(image->filename,SvPV(sval,na),
1509               MagickPathExtent);
1510           break;
1511         }
1512       if (LocaleCompare(attribute,"file") == 0)
1513         {
1514           FILE
1515             *file;
1516
1517           PerlIO
1518             *io_info;
1519
1520           if (info == (struct PackageInfo *) NULL)
1521             break;
1522           io_info=IoIFP(sv_2io(sval));
1523           if (io_info == (PerlIO *) NULL)
1524             {
1525               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1526                 PackageName);
1527               break;
1528             }
1529           file=PerlIO_findFILE(io_info);
1530           if (file == (FILE *) NULL)
1531             {
1532               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1533                 PackageName);
1534               break;
1535             }
1536           SetImageInfoFile(info->image_info,file);
1537           break;
1538         }
1539       if (LocaleCompare(attribute,"fill") == 0)
1540         {
1541           if (info)
1542             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1543           break;
1544         }
1545       if (LocaleCompare(attribute,"font") == 0)
1546         {
1547           if (info)
1548             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1549           break;
1550         }
1551       if (LocaleCompare(attribute,"foreground") == 0)
1552         break;
1553       if (LocaleCompare(attribute,"fuzz") == 0)
1554         {
1555           if (info)
1556             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1557               QuantumRange+1.0);
1558           for ( ; image; image=image->next)
1559             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1560               QuantumRange+1.0);
1561           break;
1562         }
1563       if (info)
1564         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1565       for ( ; image; image=image->next)
1566       {
1567         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1568         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1569       }
1570       break;
1571     }
1572     case 'G':
1573     case 'g':
1574     {
1575       if (LocaleCompare(attribute,"gamma") == 0)
1576         {
1577           for ( ; image; image=image->next)
1578             image->gamma=SvNV(sval);
1579           break;
1580         }
1581       if (LocaleCompare(attribute,"gravity") == 0)
1582         {
1583           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1584             SvPV(sval,na)) : SvIV(sval);
1585           if (sp < 0)
1586             {
1587               ThrowPerlException(exception,OptionError,
1588                 "UnrecognizedGravityType",SvPV(sval,na));
1589               break;
1590             }
1591           if (info)
1592             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1593           for ( ; image; image=image->next)
1594             image->gravity=(GravityType) sp;
1595           break;
1596         }
1597       if (LocaleCompare(attribute,"green-primary") == 0)
1598         {
1599           for ( ; image; image=image->next)
1600           {
1601             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1602             image->chromaticity.green_primary.x=geometry_info.rho;
1603             image->chromaticity.green_primary.y=geometry_info.sigma;
1604             if ((flags & SigmaValue) == 0)
1605               image->chromaticity.green_primary.y=
1606                 image->chromaticity.green_primary.x;
1607           }
1608           break;
1609         }
1610       if (info)
1611         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1612       for ( ; image; image=image->next)
1613       {
1614         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1615         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1616       }
1617       break;
1618     }
1619     case 'I':
1620     case 'i':
1621     {
1622       if (LocaleNCompare(attribute,"index",5) == 0)
1623         {
1624           int
1625             items;
1626
1627           long
1628             index;
1629
1630           register Quantum
1631             *q;
1632
1633           CacheView
1634             *image_view;
1635
1636           for ( ; image; image=image->next)
1637           {
1638             if (image->storage_class != PseudoClass)
1639               continue;
1640             x=0;
1641             y=0;
1642             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1643             (void) items;
1644             image_view=AcquireAuthenticCacheView(image,exception);
1645             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1646             if (q != (Quantum *) NULL)
1647               {
1648                 items=sscanf(SvPV(sval,na),"%ld",&index);
1649                 if ((index >= 0) && (index < (ssize_t) image->colors))
1650                   SetPixelIndex(image,index,q);
1651                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1652               }
1653             image_view=DestroyCacheView(image_view);
1654           }
1655           break;
1656         }
1657       if (LocaleCompare(attribute,"iterations") == 0)
1658         {
1659   iterations:
1660           for ( ; image; image=image->next)
1661             image->iterations=SvIV(sval);
1662           break;
1663         }
1664       if (LocaleCompare(attribute,"interlace") == 0)
1665         {
1666           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1667             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1668           if (sp < 0)
1669             {
1670               ThrowPerlException(exception,OptionError,
1671                 "UnrecognizedInterlaceType",SvPV(sval,na));
1672               break;
1673             }
1674           if (info)
1675             info->image_info->interlace=(InterlaceType) sp;
1676           for ( ; image; image=image->next)
1677             image->interlace=(InterlaceType) sp;
1678           break;
1679         }
1680       if (info)
1681         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1682       for ( ; image; image=image->next)
1683         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1684       break;
1685     }
1686     case 'L':
1687     case 'l':
1688     {
1689       if (LocaleCompare(attribute,"label") == 0)
1690         {
1691           for ( ; image; image=image->next)
1692             (void) SetImageProperty(image,"label",InterpretImageProperties(
1693               info ? info->image_info : (ImageInfo *) NULL,image,
1694               SvPV(sval,na),exception),exception);
1695           break;
1696         }
1697       if (LocaleCompare(attribute,"loop") == 0)
1698         goto iterations;
1699       if (info)
1700         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1701       for ( ; image; image=image->next)
1702       {
1703         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1704         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1705       }
1706       break;
1707     }
1708     case 'M':
1709     case 'm':
1710     {
1711       if (LocaleCompare(attribute,"magick") == 0)
1712         {
1713           if (info)
1714             (void) FormatLocaleString(info->image_info->filename,
1715               MagickPathExtent,"%s:",SvPV(sval,na));
1716           for ( ; image; image=image->next)
1717             (void) CopyMagickString(image->magick,SvPV(sval,na),
1718               MagickPathExtent);
1719           break;
1720         }
1721       if (LocaleCompare(attribute,"map-limit") == 0)
1722         {
1723           MagickSizeType
1724             limit;
1725
1726           limit=MagickResourceInfinity;
1727           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1728             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1729               100.0);
1730           (void) SetMagickResourceLimit(MapResource,limit);
1731           break;
1732         }
1733       if (LocaleCompare(attribute,"mask") == 0)
1734         {
1735           Image
1736             *mask;
1737
1738           mask=(Image *) NULL;
1739           if (SvPOK(sval))
1740             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1741           for ( ; image; image=image->next)
1742             SetImageMask(image,ReadPixelMask,mask,exception);
1743           break;
1744         }
1745       if (LocaleCompare(attribute,"mattecolor") == 0)
1746         {
1747           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1748             exception);
1749           if (info)
1750             info->image_info->alpha_color=target_color;
1751           for ( ; image; image=image->next)
1752             image->alpha_color=target_color;
1753           break;
1754         }
1755       if (LocaleCompare(attribute,"matte") == 0)
1756         {
1757           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1758             SvPV(sval,na)) : SvIV(sval);
1759           if (sp < 0)
1760             {
1761               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1762                 SvPV(sval,na));
1763               break;
1764             }
1765           for ( ; image; image=image->next)
1766             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1767           break;
1768         }
1769       if (LocaleCompare(attribute,"memory-limit") == 0)
1770         {
1771           MagickSizeType
1772             limit;
1773
1774           limit=MagickResourceInfinity;
1775           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1776             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1777               100.0);
1778           (void) SetMagickResourceLimit(MemoryResource,limit);
1779           break;
1780         }
1781       if (LocaleCompare(attribute,"monochrome") == 0)
1782         {
1783           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1784             SvPV(sval,na)) : SvIV(sval);
1785           if (sp < 0)
1786             {
1787               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1788                 SvPV(sval,na));
1789               break;
1790             }
1791           if (info)
1792             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1793           for ( ; image; image=image->next)
1794             (void) SetImageType(image,BilevelType,exception);
1795           break;
1796         }
1797       if (info)
1798         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1799       for ( ; image; image=image->next)
1800       {
1801         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1802         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1803       }
1804       break;
1805     }
1806     case 'O':
1807     case 'o':
1808     {
1809       if (LocaleCompare(attribute,"option") == 0)
1810         {
1811           if (info)
1812             DefineImageOption(info->image_info,SvPV(sval,na));
1813           break;
1814         }
1815       if (LocaleCompare(attribute,"orientation") == 0)
1816         {
1817           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1818             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1819           if (sp < 0)
1820             {
1821               ThrowPerlException(exception,OptionError,
1822                 "UnrecognizedOrientationType",SvPV(sval,na));
1823               break;
1824             }
1825           if (info)
1826             info->image_info->orientation=(OrientationType) sp;
1827           for ( ; image; image=image->next)
1828             image->orientation=(OrientationType) sp;
1829           break;
1830         }
1831       if (info)
1832         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1833       for ( ; image; image=image->next)
1834       {
1835         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1836         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1837       }
1838       break;
1839     }
1840     case 'P':
1841     case 'p':
1842     {
1843       if (LocaleCompare(attribute,"page") == 0)
1844         {
1845           char
1846             *geometry;
1847
1848           geometry=GetPageGeometry(SvPV(sval,na));
1849           if (info)
1850             (void) CloneString(&info->image_info->page,geometry);
1851           for ( ; image; image=image->next)
1852             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1853           geometry=(char *) RelinquishMagickMemory(geometry);
1854           break;
1855         }
1856       if (LocaleNCompare(attribute,"pixel",5) == 0)
1857         {
1858           int
1859             items;
1860
1861           PixelInfo
1862             pixel;
1863
1864           register Quantum
1865             *q;
1866
1867           CacheView
1868             *image_view;
1869
1870           for ( ; image; image=image->next)
1871           {
1872             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1873               break;
1874             x=0;
1875             y=0;
1876             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1877             (void) items;
1878             image_view=AcquireVirtualCacheView(image,exception);
1879             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1880             if (q != (Quantum *) NULL)
1881               {
1882                 if ((strchr(SvPV(sval,na),',') == 0) ||
1883                     (strchr(SvPV(sval,na),')') != 0))
1884                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1885                     &pixel,exception);
1886                 else
1887                   {
1888                     GetPixelInfo(image,&pixel);
1889                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1890                     pixel.red=geometry_info.rho;
1891                     if ((flags & SigmaValue) != 0)
1892                       pixel.green=geometry_info.sigma;
1893                     if ((flags & XiValue) != 0)
1894                       pixel.blue=geometry_info.xi;
1895                     if ((flags & PsiValue) != 0)
1896                       pixel.alpha=geometry_info.psi;
1897                     if ((flags & ChiValue) != 0)
1898                       pixel.black=geometry_info.chi;
1899                   }
1900                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1901                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1902                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1903                 if (image->colorspace == CMYKColorspace)
1904                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1905                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1906                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1907               }
1908             image_view=DestroyCacheView(image_view);
1909           }
1910           break;
1911         }
1912       if (LocaleCompare(attribute,"pointsize") == 0)
1913         {
1914           if (info)
1915             {
1916               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1917               info->image_info->pointsize=geometry_info.rho;
1918             }
1919           break;
1920         }
1921       if (info)
1922         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1923       for ( ; image; image=image->next)
1924       {
1925         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1926         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1927       }
1928       break;
1929     }
1930     case 'Q':
1931     case 'q':
1932     {
1933       if (LocaleCompare(attribute,"quality") == 0)
1934         {
1935           if (info)
1936             info->image_info->quality=SvIV(sval);
1937           for ( ; image; image=image->next)
1938             image->quality=SvIV(sval);
1939           break;
1940         }
1941       if (info)
1942         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1943       for ( ; image; image=image->next)
1944       {
1945         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
1946         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
1947       }
1948       break;
1949     }
1950     case 'R':
1951     case 'r':
1952     {
1953       if (LocaleCompare(attribute,"read-mask") == 0)
1954         {
1955           Image
1956             *mask;
1957
1958           mask=(Image *) NULL;
1959           if (SvPOK(sval))
1960             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1961           for ( ; image; image=image->next)
1962             SetImageMask(image,ReadPixelMask,mask,exception);
1963           break;
1964         }
1965       if (LocaleCompare(attribute,"red-primary") == 0)
1966         {
1967           for ( ; image; image=image->next)
1968           {
1969             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1970             image->chromaticity.red_primary.x=geometry_info.rho;
1971             image->chromaticity.red_primary.y=geometry_info.sigma;
1972             if ((flags & SigmaValue) == 0)
1973               image->chromaticity.red_primary.y=
1974                 image->chromaticity.red_primary.x;
1975           }
1976           break;
1977         }
1978       if (LocaleCompare(attribute,"render") == 0)
1979         {
1980           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1981             SvPV(sval,na)) : SvIV(sval);
1982           if (sp < 0)
1983             {
1984               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1985                 SvPV(sval,na));
1986               break;
1987             }
1988          for ( ; image; image=image->next)
1989            image->rendering_intent=(RenderingIntent) sp;
1990          break;
1991        }
1992       if (LocaleCompare(attribute,"repage") == 0)
1993         {
1994           RectangleInfo
1995             geometry;
1996
1997           for ( ; image; image=image->next)
1998           {
1999             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
2000             if ((flags & WidthValue) != 0)
2001               {
2002                 if ((flags & HeightValue) == 0)
2003                   geometry.height=geometry.width;
2004                 image->page.width=geometry.width;
2005                 image->page.height=geometry.height;
2006               }
2007             if ((flags & AspectValue) != 0)
2008               {
2009                 if ((flags & XValue) != 0)
2010                   image->page.x+=geometry.x;
2011                 if ((flags & YValue) != 0)
2012                   image->page.y+=geometry.y;
2013               }
2014             else
2015               {
2016                 if ((flags & XValue) != 0)
2017                   {
2018                     image->page.x=geometry.x;
2019                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
2020                       image->page.width=image->columns+geometry.x;
2021                   }
2022                 if ((flags & YValue) != 0)
2023                   {
2024                     image->page.y=geometry.y;
2025                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
2026                       image->page.height=image->rows+geometry.y;
2027                   }
2028               }
2029           }
2030           break;
2031         }
2032       if (info)
2033         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2034       for ( ; image; image=image->next)
2035       {
2036         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2037         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2038       }
2039       break;
2040     }
2041     case 'S':
2042     case 's':
2043     {
2044       if (LocaleCompare(attribute,"sampling-factor") == 0)
2045         {
2046           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2047             {
2048               ThrowPerlException(exception,OptionError,"MissingGeometry",
2049                 SvPV(sval,na));
2050               break;
2051             }
2052           if (info)
2053             (void) CloneString(&info->image_info->sampling_factor,
2054               SvPV(sval,na));
2055           break;
2056         }
2057       if (LocaleCompare(attribute,"scene") == 0)
2058         {
2059           for ( ; image; image=image->next)
2060             image->scene=SvIV(sval);
2061           break;
2062         }
2063       if (LocaleCompare(attribute,"server") == 0)
2064         goto display;
2065       if (LocaleCompare(attribute,"size") == 0)
2066         {
2067           if (info)
2068             {
2069               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2070                 {
2071                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2072                     SvPV(sval,na));
2073                   break;
2074                 }
2075               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2076             }
2077           break;
2078         }
2079       if (LocaleCompare(attribute,"stroke") == 0)
2080         {
2081           if (info)
2082             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2083           break;
2084         }
2085       if (info)
2086         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2087       for ( ; image; image=image->next)
2088       {
2089         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2090         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2091       }
2092       break;
2093     }
2094     case 'T':
2095     case 't':
2096     {
2097       if (LocaleCompare(attribute,"texture") == 0)
2098         {
2099           if (info)
2100             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2101           break;
2102         }
2103       if (LocaleCompare(attribute,"thread-limit") == 0)
2104         {
2105           MagickSizeType
2106             limit;
2107
2108           limit=MagickResourceInfinity;
2109           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2110             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2111               100.0);
2112           (void) SetMagickResourceLimit(ThreadResource,limit);
2113           break;
2114         }
2115       if (LocaleCompare(attribute,"tile-offset") == 0)
2116         {
2117           char
2118             *geometry;
2119
2120           geometry=GetPageGeometry(SvPV(sval,na));
2121           if (info)
2122             (void) CloneString(&info->image_info->page,geometry);
2123           for ( ; image; image=image->next)
2124             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2125               exception);
2126           geometry=(char *) RelinquishMagickMemory(geometry);
2127           break;
2128         }
2129       if (LocaleCompare(attribute,"time-limit") == 0)
2130         {
2131           MagickSizeType
2132             limit;
2133
2134           limit=MagickResourceInfinity;
2135           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2136             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2137               100.0);
2138           (void) SetMagickResourceLimit(TimeResource,limit);
2139           break;
2140         }
2141       if (LocaleCompare(attribute,"transparent-color") == 0)
2142         {
2143           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2144             exception);
2145           if (info)
2146             info->image_info->transparent_color=target_color;
2147           for ( ; image; image=image->next)
2148             image->transparent_color=target_color;
2149           break;
2150         }
2151       if (LocaleCompare(attribute,"type") == 0)
2152         {
2153           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2154             SvPV(sval,na)) : SvIV(sval);
2155           if (sp < 0)
2156             {
2157               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2158                 SvPV(sval,na));
2159               break;
2160             }
2161           if (info)
2162             info->image_info->type=(ImageType) sp;
2163           for ( ; image; image=image->next)
2164             SetImageType(image,(ImageType) sp,exception);
2165           break;
2166         }
2167       if (info)
2168         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2169       for ( ; image; image=image->next)
2170       {
2171         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2172         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2173       }
2174       break;
2175     }
2176     case 'U':
2177     case 'u':
2178     {
2179       if (LocaleCompare(attribute,"units") == 0)
2180         {
2181           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2182             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2183           if (sp < 0)
2184             {
2185               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2186                 SvPV(sval,na));
2187               break;
2188             }
2189           if (info)
2190             info->image_info->units=(ResolutionType) sp;
2191           for ( ; image; image=image->next)
2192           {
2193             ResolutionType
2194               units;
2195
2196             units=(ResolutionType) sp;
2197             if (image->units != units)
2198               switch (image->units)
2199               {
2200                 case UndefinedResolution:
2201                 case PixelsPerInchResolution:
2202                 {
2203                   if (units == PixelsPerCentimeterResolution)
2204                     {
2205                       image->resolution.x*=2.54;
2206                       image->resolution.y*=2.54;
2207                     }
2208                   break;
2209                 }
2210                 case PixelsPerCentimeterResolution:
2211                 {
2212                   if (units == PixelsPerInchResolution)
2213                     {
2214                       image->resolution.x/=2.54;
2215                       image->resolution.y/=2.54;
2216                     }
2217                   break;
2218                 }
2219               }
2220             image->units=units;
2221           }
2222           break;
2223         }
2224       if (info)
2225         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2226       for ( ; image; image=image->next)
2227       {
2228         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2229         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2230       }
2231       break;
2232     }
2233     case 'V':
2234     case 'v':
2235     {
2236       if (LocaleCompare(attribute,"verbose") == 0)
2237         {
2238           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2239             SvPV(sval,na)) : SvIV(sval);
2240           if (sp < 0)
2241             {
2242               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2243                 SvPV(sval,na));
2244               break;
2245             }
2246           if (info)
2247             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2248           break;
2249         }
2250       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2251         {
2252           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2253             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2254           if (sp < 0)
2255             {
2256               ThrowPerlException(exception,OptionError,
2257                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2258               break;
2259             }
2260           for ( ; image; image=image->next)
2261             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2262           break;
2263         }
2264       if (info)
2265         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2266       for ( ; image; image=image->next)
2267       {
2268         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2269         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2270       }
2271       break;
2272     }
2273     case 'W':
2274     case 'w':
2275     {
2276       if (LocaleCompare(attribute,"white-point") == 0)
2277         {
2278           for ( ; image; image=image->next)
2279           {
2280             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2281             image->chromaticity.white_point.x=geometry_info.rho;
2282             image->chromaticity.white_point.y=geometry_info.sigma;
2283             if ((flags & SigmaValue) == 0)
2284               image->chromaticity.white_point.y=
2285                 image->chromaticity.white_point.x;
2286           }
2287           break;
2288         }
2289       if (LocaleCompare(attribute,"write-mask") == 0)
2290         {
2291           Image
2292             *mask;
2293
2294           mask=(Image *) NULL;
2295           if (SvPOK(sval))
2296             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2297           for ( ; image; image=image->next)
2298             SetImageMask(image,WritePixelMask,mask,exception);
2299           break;
2300         }
2301       if (info)
2302         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2303       for ( ; image; image=image->next)
2304       {
2305         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2306         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2307       }
2308       break;
2309     }
2310     default:
2311     {
2312       if (info)
2313         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2314       for ( ; image; image=image->next)
2315       {
2316         (void) SetImageProperty(image,attribute,SvPV(sval,na),exception);
2317         (void) SetImageArtifact(image,attribute,SvPV(sval,na));
2318       }
2319       break;
2320     }
2321   }
2322 }
2323 \f
2324 /*
2325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2326 %                                                                             %
2327 %                                                                             %
2328 %                                                                             %
2329 %   S e t u p L i s t                                                         %
2330 %                                                                             %
2331 %                                                                             %
2332 %                                                                             %
2333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2334 %
2335 %  Method SetupList returns the list of all the images linked by their
2336 %  image->next and image->previous link lists for use with ImageMagick.  If
2337 %  info is non-NULL, an info structure is returned in *info.  If
2338 %  reference_vector is non-NULL,an array of SV* are returned in
2339 %  *reference_vector.  Reference_vector is used when the images are going to be
2340 %  replaced with new Image*'s.
2341 %
2342 %  The format of the SetupList routine is:
2343 %
2344 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2345 %        SV ***reference_vector,ExceptionInfo *exception)
2346 %
2347 %  A description of each parameter follows:
2348 %
2349 %    o list: a list of strings.
2350 %
2351 %    o string: a character string.
2352 %
2353 %    o exception: Return any errors or warnings in this structure.
2354 %
2355 */
2356 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2357   SV ***reference_vector,ExceptionInfo *exception)
2358 {
2359   Image
2360     *image;
2361
2362   ssize_t
2363     current,
2364     last;
2365
2366   if (reference_vector)
2367     *reference_vector=NULL;
2368   if (info)
2369     *info=NULL;
2370   current=0;
2371   last=0;
2372   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2373   if (info && (SvTYPE(reference) == SVt_PVAV))
2374     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2375       exception);
2376   return(image);
2377 }
2378 \f
2379 /*
2380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2381 %                                                                             %
2382 %                                                                             %
2383 %                                                                             %
2384 %   s t r E Q c a s e                                                         %
2385 %                                                                             %
2386 %                                                                             %
2387 %                                                                             %
2388 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2389 %
2390 %  strEQcase() compares two strings and returns 0 if they are the
2391 %  same or if the second string runs out first.  The comparison is case
2392 %  insensitive.
2393 %
2394 %  The format of the strEQcase routine is:
2395 %
2396 %      ssize_t strEQcase(const char *p,const char *q)
2397 %
2398 %  A description of each parameter follows:
2399 %
2400 %    o p: a character string.
2401 %
2402 %    o q: a character string.
2403 %
2404 %
2405 */
2406 static ssize_t strEQcase(const char *p,const char *q)
2407 {
2408   char
2409     c;
2410
2411   register ssize_t
2412     i;
2413
2414   for (i=0 ; (c=(*q)) != 0; i++)
2415   {
2416     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2417         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2418       return(0);
2419     p++;
2420     q++;
2421   }
2422   return(((*q == 0) && (*p == 0)) ? i : 0);
2423 }
2424 \f
2425 /*
2426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2427 %                                                                             %
2428 %                                                                             %
2429 %                                                                             %
2430 %   I m a g e : : M a g i c k                                                 %
2431 %                                                                             %
2432 %                                                                             %
2433 %                                                                             %
2434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2435 %
2436 %
2437 */
2438 MODULE = Image::Magick::@MAGICK_ABI_SUFFIX@ PACKAGE = Image::Magick::@MAGICK_ABI_SUFFIX@
2439
2440 PROTOTYPES: ENABLE
2441
2442 BOOT:
2443   MagickCoreGenesis("PerlMagick",MagickFalse);
2444   SetWarningHandler(NULL);
2445   SetErrorHandler(NULL);
2446   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2447     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2448
2449 void
2450 UNLOAD()
2451   PPCODE:
2452   {
2453     if (magick_registry != (SplayTreeInfo *) NULL)
2454       magick_registry=DestroySplayTree(magick_registry);
2455     MagickCoreTerminus();
2456   }
2457
2458 double
2459 constant(name,argument)
2460   char *name
2461   ssize_t argument
2462 \f
2463 #
2464 ###############################################################################
2465 #                                                                             #
2466 #                                                                             #
2467 #                                                                             #
2468 #   A n i m a t e                                                             #
2469 #                                                                             #
2470 #                                                                             #
2471 #                                                                             #
2472 ###############################################################################
2473 #
2474 #
2475 void
2476 Animate(ref,...)
2477   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2478   ALIAS:
2479     AnimateImage  = 1
2480     animate       = 2
2481     animateimage  = 3
2482   PPCODE:
2483   {
2484     ExceptionInfo
2485       *exception;
2486
2487     Image
2488       *image;
2489
2490     register ssize_t
2491       i;
2492
2493     struct PackageInfo
2494       *info,
2495       *package_info;
2496
2497     SV
2498       *perl_exception,
2499       *reference;
2500
2501     PERL_UNUSED_VAR(ref);
2502     PERL_UNUSED_VAR(ix);
2503     exception=AcquireExceptionInfo();
2504     perl_exception=newSVpv("",0);
2505     package_info=(struct PackageInfo *) NULL;
2506     if (sv_isobject(ST(0)) == 0)
2507       {
2508         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2509           PackageName);
2510         goto PerlException;
2511       }
2512     reference=SvRV(ST(0));
2513     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2514     if (image == (Image *) NULL)
2515       {
2516         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2517           PackageName);
2518         goto PerlException;
2519       }
2520     package_info=ClonePackageInfo(info,exception);
2521     if (items == 2)
2522       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2523     else
2524       if (items > 2)
2525         for (i=2; i < items; i+=2)
2526           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2527             exception);
2528     (void) AnimateImages(package_info->image_info,image,exception);
2529     (void) CatchImageException(image);
2530
2531   PerlException:
2532     if (package_info != (struct PackageInfo *) NULL)
2533       DestroyPackageInfo(package_info);
2534     InheritPerlException(exception,perl_exception);
2535     exception=DestroyExceptionInfo(exception);
2536     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2537     SvPOK_on(perl_exception);
2538     ST(0)=sv_2mortal(perl_exception);
2539     XSRETURN(1);
2540   }
2541 \f
2542 #
2543 ###############################################################################
2544 #                                                                             #
2545 #                                                                             #
2546 #                                                                             #
2547 #   A p p e n d                                                               #
2548 #                                                                             #
2549 #                                                                             #
2550 #                                                                             #
2551 ###############################################################################
2552 #
2553 #
2554 void
2555 Append(ref,...)
2556   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2557   ALIAS:
2558     AppendImage  = 1
2559     append       = 2
2560     appendimage  = 3
2561   PPCODE:
2562   {
2563     AV
2564       *av;
2565
2566     char
2567       *attribute;
2568
2569     ExceptionInfo
2570       *exception;
2571
2572     HV
2573       *hv;
2574
2575     Image
2576       *image;
2577
2578     register ssize_t
2579       i;
2580
2581     ssize_t
2582       stack;
2583
2584     struct PackageInfo
2585       *info;
2586
2587     SV
2588       *av_reference,
2589       *perl_exception,
2590       *reference,
2591       *rv,
2592       *sv;
2593
2594     PERL_UNUSED_VAR(ref);
2595     PERL_UNUSED_VAR(ix);
2596     exception=AcquireExceptionInfo();
2597     perl_exception=newSVpv("",0);
2598     sv=NULL;
2599     attribute=NULL;
2600     av=NULL;
2601     if (sv_isobject(ST(0)) == 0)
2602       {
2603         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2604           PackageName);
2605         goto PerlException;
2606       }
2607     reference=SvRV(ST(0));
2608     hv=SvSTASH(reference);
2609     av=newAV();
2610     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2611     SvREFCNT_dec(av);
2612     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2613     if (image == (Image *) NULL)
2614       {
2615         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2616           PackageName);
2617         goto PerlException;
2618       }
2619     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2620     /*
2621       Get options.
2622     */
2623     stack=MagickTrue;
2624     for (i=2; i < items; i+=2)
2625     {
2626       attribute=(char *) SvPV(ST(i-1),na);
2627       switch (*attribute)
2628       {
2629         case 'S':
2630         case 's':
2631         {
2632           if (LocaleCompare(attribute,"stack") == 0)
2633             {
2634               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2635                 SvPV(ST(i),na));
2636               if (stack < 0)
2637                 {
2638                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2639                     SvPV(ST(i),na));
2640                   return;
2641                 }
2642               break;
2643             }
2644           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2645             attribute);
2646           break;
2647         }
2648         default:
2649         {
2650           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2651             attribute);
2652           break;
2653         }
2654       }
2655     }
2656     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2657     if (image == (Image *) NULL)
2658       goto PerlException;
2659     for ( ; image; image=image->next)
2660     {
2661       AddImageToRegistry(sv,image);
2662       rv=newRV(sv);
2663       av_push(av,sv_bless(rv,hv));
2664       SvREFCNT_dec(sv);
2665     }
2666     exception=DestroyExceptionInfo(exception);
2667     ST(0)=av_reference;
2668     SvREFCNT_dec(perl_exception);
2669     XSRETURN(1);
2670
2671   PerlException:
2672     InheritPerlException(exception,perl_exception);
2673     exception=DestroyExceptionInfo(exception);
2674     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2675     SvPOK_on(perl_exception);
2676     ST(0)=sv_2mortal(perl_exception);
2677     XSRETURN(1);
2678   }
2679 \f
2680 #
2681 ###############################################################################
2682 #                                                                             #
2683 #                                                                             #
2684 #                                                                             #
2685 #   A v e r a g e                                                             #
2686 #                                                                             #
2687 #                                                                             #
2688 #                                                                             #
2689 ###############################################################################
2690 #
2691 #
2692 void
2693 Average(ref)
2694   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2695   ALIAS:
2696     AverageImage   = 1
2697     average        = 2
2698     averageimage   = 3
2699   PPCODE:
2700   {
2701     AV
2702       *av;
2703
2704     char
2705       *p;
2706
2707     ExceptionInfo
2708       *exception;
2709
2710     HV
2711       *hv;
2712
2713     Image
2714       *image;
2715
2716     struct PackageInfo
2717       *info;
2718
2719     SV
2720       *perl_exception,
2721       *reference,
2722       *rv,
2723       *sv;
2724
2725     PERL_UNUSED_VAR(ref);
2726     PERL_UNUSED_VAR(ix);
2727     exception=AcquireExceptionInfo();
2728     perl_exception=newSVpv("",0);
2729     sv=NULL;
2730     if (sv_isobject(ST(0)) == 0)
2731       {
2732         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2733           PackageName);
2734         goto PerlException;
2735       }
2736     reference=SvRV(ST(0));
2737     hv=SvSTASH(reference);
2738     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2739     if (image == (Image *) NULL)
2740       {
2741         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2742           PackageName);
2743         goto PerlException;
2744       }
2745     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2746     if (image == (Image *) NULL)
2747       goto PerlException;
2748     /*
2749       Create blessed Perl array for the returned image.
2750     */
2751     av=newAV();
2752     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2753     SvREFCNT_dec(av);
2754     AddImageToRegistry(sv,image);
2755     rv=newRV(sv);
2756     av_push(av,sv_bless(rv,hv));
2757     SvREFCNT_dec(sv);
2758     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2759     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2760       "average-%.*s",(int) (MagickPathExtent-9),
2761       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2762     (void) CopyMagickString(image->filename,info->image_info->filename,
2763       MagickPathExtent);
2764     SetImageInfo(info->image_info,0,exception);
2765     exception=DestroyExceptionInfo(exception);
2766     SvREFCNT_dec(perl_exception);
2767     XSRETURN(1);
2768
2769   PerlException:
2770     InheritPerlException(exception,perl_exception);
2771     exception=DestroyExceptionInfo(exception);
2772     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2773     SvPOK_on(perl_exception);
2774     ST(0)=sv_2mortal(perl_exception);
2775     XSRETURN(1);
2776   }
2777 \f
2778 #
2779 ###############################################################################
2780 #                                                                             #
2781 #                                                                             #
2782 #                                                                             #
2783 #   B l o b T o I m a g e                                                     #
2784 #                                                                             #
2785 #                                                                             #
2786 #                                                                             #
2787 ###############################################################################
2788 #
2789 #
2790 void
2791 BlobToImage(ref,...)
2792   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2793   ALIAS:
2794     BlobToImage  = 1
2795     blobtoimage  = 2
2796     blobto       = 3
2797   PPCODE:
2798   {
2799     AV
2800       *av;
2801
2802     char
2803       **keep,
2804       **list;
2805
2806     ExceptionInfo
2807       *exception;
2808
2809     HV
2810       *hv;
2811
2812     Image
2813       *image;
2814
2815     register char
2816       **p;
2817
2818     register ssize_t
2819       i;
2820
2821     ssize_t
2822       ac,
2823       n,
2824       number_images;
2825
2826     STRLEN
2827       *length;
2828
2829     struct PackageInfo
2830       *info;
2831
2832     SV
2833       *perl_exception,
2834       *reference,
2835       *rv,
2836       *sv;
2837
2838     PERL_UNUSED_VAR(ref);
2839     PERL_UNUSED_VAR(ix);
2840     exception=AcquireExceptionInfo();
2841     perl_exception=newSVpv("",0);
2842     sv=NULL;
2843     number_images=0;
2844     ac=(items < 2) ? 1 : items-1;
2845     length=(STRLEN *) NULL;
2846     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2847     if (list == (char **) NULL)
2848       {
2849         ThrowPerlException(exception,ResourceLimitError,
2850           "MemoryAllocationFailed",PackageName);
2851         goto PerlException;
2852       }
2853     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2854     if (length == (STRLEN *) NULL)
2855       {
2856         ThrowPerlException(exception,ResourceLimitError,
2857           "MemoryAllocationFailed",PackageName);
2858         goto PerlException;
2859       }
2860     if (sv_isobject(ST(0)) == 0)
2861       {
2862         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2863           PackageName);
2864         goto PerlException;
2865       }
2866     reference=SvRV(ST(0));
2867     hv=SvSTASH(reference);
2868     if (SvTYPE(reference) != SVt_PVAV)
2869       {
2870         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2871           PackageName);
2872         goto PerlException;
2873       }
2874     av=(AV *) reference;
2875     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2876       exception);
2877     n=1;
2878     if (items <= 1)
2879       {
2880         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2881         goto PerlException;
2882       }
2883     for (n=0, i=0; i < ac; i++)
2884     {
2885       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2886       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2887         {
2888           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2889           continue;
2890         }
2891       n++;
2892     }
2893     list[n]=(char *) NULL;
2894     keep=list;
2895     for (i=number_images=0; i < n; i++)
2896     {
2897       image=BlobToImage(info->image_info,list[i],length[i],exception);
2898       if (image == (Image *) NULL)
2899         break;
2900       for ( ; image; image=image->next)
2901       {
2902         AddImageToRegistry(sv,image);
2903         rv=newRV(sv);
2904         av_push(av,sv_bless(rv,hv));
2905         SvREFCNT_dec(sv);
2906         number_images++;
2907       }
2908     }
2909     /*
2910       Free resources.
2911     */
2912     for (i=0; i < n; i++)
2913       if (list[i] != (char *) NULL)
2914         for (p=keep; list[i] != *p++; )
2915           if (*p == (char *) NULL)
2916             {
2917               list[i]=(char *) RelinquishMagickMemory(list[i]);
2918               break;
2919             }
2920
2921   PerlException:
2922     if (list)
2923       list=(char **) RelinquishMagickMemory(list);
2924     if (length)
2925       length=(STRLEN *) RelinquishMagickMemory(length);
2926     InheritPerlException(exception,perl_exception);
2927     exception=DestroyExceptionInfo(exception);
2928     sv_setiv(perl_exception,(IV) number_images);
2929     SvPOK_on(perl_exception);
2930     ST(0)=sv_2mortal(perl_exception);
2931     XSRETURN(1);
2932   }
2933 \f
2934 #
2935 ###############################################################################
2936 #                                                                             #
2937 #                                                                             #
2938 #                                                                             #
2939 #   C h a n n e l F x                                                         #
2940 #                                                                             #
2941 #                                                                             #
2942 #                                                                             #
2943 ###############################################################################
2944 #
2945 #
2946 void
2947 ChannelFx(ref,...)
2948   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
2949   ALIAS:
2950     ChannelFxImage  = 1
2951     channelfx       = 2
2952     channelfximage  = 3
2953   PPCODE:
2954   {
2955     AV
2956       *av;
2957
2958     char
2959       *attribute,
2960       expression[MagickPathExtent];
2961
2962     ChannelType
2963       channel,
2964       channel_mask;
2965
2966     ExceptionInfo
2967       *exception;
2968
2969     HV
2970       *hv;
2971
2972     Image
2973       *image;
2974
2975     register ssize_t
2976       i;
2977
2978     struct PackageInfo
2979       *info;
2980
2981     SV
2982       *av_reference,
2983       *perl_exception,
2984       *reference,
2985       *rv,
2986       *sv;
2987
2988     PERL_UNUSED_VAR(ref);
2989     PERL_UNUSED_VAR(ix);
2990     exception=AcquireExceptionInfo();
2991     perl_exception=newSVpv("",0);
2992     sv=NULL;
2993     attribute=NULL;
2994     av=NULL;
2995     if (sv_isobject(ST(0)) == 0)
2996       {
2997         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2998           PackageName);
2999         goto PerlException;
3000       }
3001     reference=SvRV(ST(0));
3002     hv=SvSTASH(reference);
3003     av=newAV();
3004     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3005     SvREFCNT_dec(av);
3006     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3007     if (image == (Image *) NULL)
3008       {
3009         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3010           PackageName);
3011         goto PerlException;
3012       }
3013     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3014     /*
3015       Get options.
3016     */
3017     channel=DefaultChannels;
3018     (void) CopyMagickString(expression,"u",MagickPathExtent);
3019     if (items == 2)
3020       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
3021     else
3022       for (i=2; i < items; i+=2)
3023       {
3024         attribute=(char *) SvPV(ST(i-1),na);
3025         switch (*attribute)
3026         {
3027           case 'C':
3028           case 'c':
3029           {
3030             if (LocaleCompare(attribute,"channel") == 0)
3031               {
3032                 ssize_t
3033                   option;
3034
3035                 option=ParseChannelOption(SvPV(ST(i),na));
3036                 if (option < 0)
3037                   {
3038                     ThrowPerlException(exception,OptionError,
3039                       "UnrecognizedType",SvPV(ST(i),na));
3040                     return;
3041                   }
3042                 channel=(ChannelType) option;
3043                 break;
3044               }
3045             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3046               attribute);
3047             break;
3048           }
3049           case 'E':
3050           case 'e':
3051           {
3052             if (LocaleCompare(attribute,"expression") == 0)
3053               {
3054                 (void) CopyMagickString(expression,SvPV(ST(i),na),
3055                   MagickPathExtent);
3056                 break;
3057               }
3058             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3059               attribute);
3060             break;
3061           }
3062           default:
3063           {
3064             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3065               attribute);
3066             break;
3067           }
3068         }
3069       }
3070     channel_mask=SetImageChannelMask(image,channel);
3071     image=ChannelFxImage(image,expression,exception);
3072     if (image != (Image *) NULL)
3073       (void) SetImageChannelMask(image,channel_mask);
3074     if (image == (Image *) NULL)
3075       goto PerlException;
3076     for ( ; image; image=image->next)
3077     {
3078       AddImageToRegistry(sv,image);
3079       rv=newRV(sv);
3080       av_push(av,sv_bless(rv,hv));
3081       SvREFCNT_dec(sv);
3082     }
3083     exception=DestroyExceptionInfo(exception);
3084     ST(0)=av_reference;
3085     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3086     XSRETURN(1);
3087
3088   PerlException:
3089     InheritPerlException(exception,perl_exception);
3090     exception=DestroyExceptionInfo(exception);
3091     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3092     SvPOK_on(perl_exception);
3093     ST(0)=sv_2mortal(perl_exception);
3094     XSRETURN(1);
3095   }
3096 \f
3097 #
3098 ###############################################################################
3099 #                                                                             #
3100 #                                                                             #
3101 #                                                                             #
3102 #   C l o n e                                                                 #
3103 #                                                                             #
3104 #                                                                             #
3105 #                                                                             #
3106 ###############################################################################
3107 #
3108 #
3109 void
3110 Clone(ref)
3111   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3112   ALIAS:
3113     CopyImage   = 1
3114     copy        = 2
3115     copyimage   = 3
3116     CloneImage  = 4
3117     clone       = 5
3118     cloneimage  = 6
3119     Clone       = 7
3120   PPCODE:
3121   {
3122     AV
3123       *av;
3124
3125     ExceptionInfo
3126       *exception;
3127
3128     HV
3129       *hv;
3130
3131     Image
3132       *clone,
3133       *image;
3134
3135     struct PackageInfo
3136       *info;
3137
3138     SV
3139       *perl_exception,
3140       *reference,
3141       *rv,
3142       *sv;
3143
3144     PERL_UNUSED_VAR(ref);
3145     PERL_UNUSED_VAR(ix);
3146     exception=AcquireExceptionInfo();
3147     perl_exception=newSVpv("",0);
3148     sv=NULL;
3149     if (sv_isobject(ST(0)) == 0)
3150       {
3151         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3152           PackageName);
3153         goto PerlException;
3154       }
3155     reference=SvRV(ST(0));
3156     hv=SvSTASH(reference);
3157     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3158     if (image == (Image *) NULL)
3159       {
3160         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3161           PackageName);
3162         goto PerlException;
3163       }
3164     /*
3165       Create blessed Perl array for the returned image.
3166     */
3167     av=newAV();
3168     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3169     SvREFCNT_dec(av);
3170     for ( ; image; image=image->next)
3171     {
3172       clone=CloneImage(image,0,0,MagickTrue,exception);
3173       if (clone == (Image *) NULL)
3174         break;
3175       AddImageToRegistry(sv,clone);
3176       rv=newRV(sv);
3177       av_push(av,sv_bless(rv,hv));
3178       SvREFCNT_dec(sv);
3179     }
3180     exception=DestroyExceptionInfo(exception);
3181     SvREFCNT_dec(perl_exception);
3182     XSRETURN(1);
3183
3184   PerlException:
3185     InheritPerlException(exception,perl_exception);
3186     exception=DestroyExceptionInfo(exception);
3187     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3188     SvPOK_on(perl_exception);
3189     ST(0)=sv_2mortal(perl_exception);
3190     XSRETURN(1);
3191   }
3192 \f
3193 #
3194 ###############################################################################
3195 #                                                                             #
3196 #                                                                             #
3197 #                                                                             #
3198 #   C L O N E                                                                 #
3199 #                                                                             #
3200 #                                                                             #
3201 #                                                                             #
3202 ###############################################################################
3203 #
3204 #
3205 void
3206 CLONE(ref,...)
3207   SV *ref;
3208   CODE:
3209   {
3210     PERL_UNUSED_VAR(ref);
3211     if (magick_registry != (SplayTreeInfo *) NULL)
3212       {
3213         register Image
3214           *p;
3215
3216         ResetSplayTreeIterator(magick_registry);
3217         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3218         while (p != (Image *) NULL)
3219         {
3220           ReferenceImage(p);
3221           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3222         }
3223       }
3224   }
3225 \f
3226 #
3227 ###############################################################################
3228 #                                                                             #
3229 #                                                                             #
3230 #                                                                             #
3231 #   C o a l e s c e                                                           #
3232 #                                                                             #
3233 #                                                                             #
3234 #                                                                             #
3235 ###############################################################################
3236 #
3237 #
3238 void
3239 Coalesce(ref)
3240   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3241   ALIAS:
3242     CoalesceImage   = 1
3243     coalesce        = 2
3244     coalesceimage   = 3
3245   PPCODE:
3246   {
3247     AV
3248       *av;
3249
3250     ExceptionInfo
3251       *exception;
3252
3253     HV
3254       *hv;
3255
3256     Image
3257       *image;
3258
3259     struct PackageInfo
3260       *info;
3261
3262     SV
3263       *av_reference,
3264       *perl_exception,
3265       *reference,
3266       *rv,
3267       *sv;
3268
3269     PERL_UNUSED_VAR(ref);
3270     PERL_UNUSED_VAR(ix);
3271     exception=AcquireExceptionInfo();
3272     perl_exception=newSVpv("",0);
3273     sv=NULL;
3274     if (sv_isobject(ST(0)) == 0)
3275       {
3276         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3277           PackageName);
3278         goto PerlException;
3279       }
3280     reference=SvRV(ST(0));
3281     hv=SvSTASH(reference);
3282     av=newAV();
3283     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3284     SvREFCNT_dec(av);
3285     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3286     if (image == (Image *) NULL)
3287       {
3288         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3289           PackageName);
3290         goto PerlException;
3291       }
3292     image=CoalesceImages(image,exception);
3293     if (image == (Image *) NULL)
3294       goto PerlException;
3295     for ( ; image; image=image->next)
3296     {
3297       AddImageToRegistry(sv,image);
3298       rv=newRV(sv);
3299       av_push(av,sv_bless(rv,hv));
3300       SvREFCNT_dec(sv);
3301     }
3302     exception=DestroyExceptionInfo(exception);
3303     ST(0)=av_reference;
3304     SvREFCNT_dec(perl_exception);
3305     XSRETURN(1);
3306
3307   PerlException:
3308     InheritPerlException(exception,perl_exception);
3309     exception=DestroyExceptionInfo(exception);
3310     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3311     SvPOK_on(perl_exception);
3312     ST(0)=sv_2mortal(perl_exception);
3313     XSRETURN(1);
3314   }
3315 \f
3316 #
3317 ###############################################################################
3318 #                                                                             #
3319 #                                                                             #
3320 #                                                                             #
3321 #   C o m p a r e                                                             #
3322 #                                                                             #
3323 #                                                                             #
3324 #                                                                             #
3325 ###############################################################################
3326 #
3327 #
3328 void
3329 Compare(ref,...)
3330   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3331   ALIAS:
3332     CompareImages = 1
3333     compare      = 2
3334     compareimage = 3
3335   PPCODE:
3336   {
3337     AV
3338       *av;
3339
3340     char
3341       *attribute;
3342
3343     double
3344       distortion;
3345
3346     ExceptionInfo
3347       *exception;
3348
3349     HV
3350       *hv;
3351
3352     Image
3353       *difference_image,
3354       *image,
3355       *reconstruct_image;
3356
3357     MetricType
3358       metric;
3359
3360     register ssize_t
3361       i;
3362
3363     ssize_t
3364       option;
3365
3366     struct PackageInfo
3367       *info;
3368
3369     SV
3370       *av_reference,
3371       *perl_exception,
3372       *reference,
3373       *rv,
3374       *sv;
3375
3376     PERL_UNUSED_VAR(ref);
3377     PERL_UNUSED_VAR(ix);
3378     exception=AcquireExceptionInfo();
3379     perl_exception=newSVpv("",0);
3380     sv=NULL;
3381     av=NULL;
3382     attribute=NULL;
3383     if (sv_isobject(ST(0)) == 0)
3384       {
3385         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3386           PackageName);
3387         goto PerlException;
3388       }
3389     reference=SvRV(ST(0));
3390     hv=SvSTASH(reference);
3391     av=newAV();
3392     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3393     SvREFCNT_dec(av);
3394     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3395     if (image == (Image *) NULL)
3396       {
3397         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3398           PackageName);
3399         goto PerlException;
3400       }
3401     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3402     /*
3403       Get attribute.
3404     */
3405     reconstruct_image=image;
3406     metric=RootMeanSquaredErrorMetric;
3407     for (i=2; i < items; i+=2)
3408     {
3409       attribute=(char *) SvPV(ST(i-1),na);
3410       switch (*attribute)
3411       {
3412         case 'C':
3413         case 'c':
3414         {
3415           if (LocaleCompare(attribute,"channel") == 0)
3416             {
3417               ssize_t
3418                 option;
3419
3420               option=ParseChannelOption(SvPV(ST(i),na));
3421               if (option < 0)
3422                 {
3423                   ThrowPerlException(exception,OptionError,
3424                     "UnrecognizedType",SvPV(ST(i),na));
3425                   return;
3426                 }
3427               (void) SetPixelChannelMask(image,(ChannelType) option);
3428               break;
3429             }
3430           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3431             attribute);
3432           break;
3433         }
3434         case 'F':
3435         case 'f':
3436         {
3437           if (LocaleCompare(attribute,"fuzz") == 0)
3438             {
3439               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3440               break;
3441             }
3442           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3443             attribute);
3444           break;
3445         }
3446         case 'I':
3447         case 'i':
3448         {
3449           if (LocaleCompare(attribute,"image") == 0)
3450             {
3451               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3452                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3453               break;
3454             }
3455           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3456             attribute);
3457           break;
3458         }
3459         case 'M':
3460         case 'm':
3461         {
3462           if (LocaleCompare(attribute,"metric") == 0)
3463             {
3464               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3465                 SvPV(ST(i),na));
3466               if (option < 0)
3467                 {
3468                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3469                     SvPV(ST(i),na));
3470                   break;
3471                 }
3472               metric=(MetricType) option;
3473               break;
3474             }
3475           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3476             attribute);
3477           break;
3478         }
3479         default:
3480         {
3481           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3482             attribute);
3483           break;
3484         }
3485       }
3486     }
3487     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3488       exception);
3489     if (difference_image != (Image *) NULL)
3490       {
3491         difference_image->error.mean_error_per_pixel=distortion;
3492         AddImageToRegistry(sv,difference_image);
3493         rv=newRV(sv);
3494         av_push(av,sv_bless(rv,hv));
3495         SvREFCNT_dec(sv);
3496       }
3497     exception=DestroyExceptionInfo(exception);
3498     ST(0)=av_reference;
3499     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3500     XSRETURN(1);
3501
3502   PerlException:
3503     InheritPerlException(exception,perl_exception);
3504     exception=DestroyExceptionInfo(exception);
3505     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3506     SvPOK_on(perl_exception);
3507     ST(0)=sv_2mortal(perl_exception);
3508     XSRETURN(1);
3509   }
3510 \f
3511 #
3512 ###############################################################################
3513 #                                                                             #
3514 #                                                                             #
3515 #                                                                             #
3516 #   C o m p l e x I m a g e s                                                 #
3517 #                                                                             #
3518 #                                                                             #
3519 #                                                                             #
3520 ###############################################################################
3521 #
3522 #
3523 void
3524 ComplexImages(ref,...)
3525   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3526   ALIAS:
3527     ComplexImages   = 1
3528     compleximages   = 2
3529   PPCODE:
3530   {
3531     AV
3532       *av;
3533
3534     char
3535       *attribute,
3536       *p;
3537
3538     ComplexOperator
3539       op;
3540
3541     ExceptionInfo
3542       *exception;
3543
3544     HV
3545       *hv;
3546
3547     Image
3548       *image;
3549
3550     register ssize_t
3551       i;
3552
3553     struct PackageInfo
3554       *info;
3555
3556     SV
3557       *perl_exception,
3558       *reference,
3559       *rv,
3560       *sv;
3561
3562     PERL_UNUSED_VAR(ref);
3563     PERL_UNUSED_VAR(ix);
3564     exception=AcquireExceptionInfo();
3565     perl_exception=newSVpv("",0);
3566     sv=NULL;
3567     if (sv_isobject(ST(0)) == 0)
3568       {
3569         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3570           PackageName);
3571         goto PerlException;
3572       }
3573     reference=SvRV(ST(0));
3574     hv=SvSTASH(reference);
3575     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3576     if (image == (Image *) NULL)
3577       {
3578         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3579           PackageName);
3580         goto PerlException;
3581       }
3582     op=UndefinedComplexOperator;
3583     if (items == 2)
3584       {
3585         ssize_t
3586           in;
3587
3588         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3589           SvPV(ST(1),na));
3590         if (in < 0)
3591           {
3592             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3593               SvPV(ST(1),na));
3594             return;
3595           }
3596         op=(ComplexOperator) in;
3597       }
3598     else
3599       for (i=2; i < items; i+=2)
3600       {
3601         attribute=(char *) SvPV(ST(i-1),na);
3602         switch (*attribute)
3603         {
3604           case 'O':
3605           case 'o':
3606           {
3607             if (LocaleCompare(attribute,"operator") == 0)
3608               {
3609                 ssize_t
3610                   in;
3611
3612                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3613                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3614                 if (in < 0)
3615                   {
3616                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3617                       SvPV(ST(i),na));
3618                     return;
3619                   }
3620                 op=(ComplexOperator) in;
3621                 break;
3622               }
3623             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3624               attribute);
3625             break;
3626           }
3627           default:
3628           {
3629             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3630               attribute);
3631             break;
3632           }
3633         }
3634       }
3635     image=ComplexImages(image,op,exception);
3636     if (image == (Image *) NULL)
3637       goto PerlException;
3638     /*
3639       Create blessed Perl array for the returned image.
3640     */
3641     av=newAV();
3642     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3643     SvREFCNT_dec(av);
3644     AddImageToRegistry(sv,image);
3645     rv=newRV(sv);
3646     av_push(av,sv_bless(rv,hv));
3647     SvREFCNT_dec(sv);
3648     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3649     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3650       "complex-%.*s",(int) (MagickPathExtent-9),
3651       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3652     (void) CopyMagickString(image->filename,info->image_info->filename,
3653       MagickPathExtent);
3654     SetImageInfo(info->image_info,0,exception);
3655     exception=DestroyExceptionInfo(exception);
3656     SvREFCNT_dec(perl_exception);
3657     XSRETURN(1);
3658
3659   PerlException:
3660     InheritPerlException(exception,perl_exception);
3661     exception=DestroyExceptionInfo(exception);
3662     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3663     SvPOK_on(perl_exception);
3664     ST(0)=sv_2mortal(perl_exception);
3665     XSRETURN(1);
3666   }
3667 \f
3668 #
3669 ###############################################################################
3670 #                                                                             #
3671 #                                                                             #
3672 #                                                                             #
3673 #   C o m p a r e L a y e r s                                                 #
3674 #                                                                             #
3675 #                                                                             #
3676 #                                                                             #
3677 ###############################################################################
3678 #
3679 #
3680 void
3681 CompareLayers(ref,...)
3682   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3683   ALIAS:
3684     CompareImagesLayers   = 1
3685     comparelayers        = 2
3686     compareimagelayers   = 3
3687   PPCODE:
3688   {
3689     AV
3690       *av;
3691
3692     char
3693       *attribute;
3694
3695     ExceptionInfo
3696       *exception;
3697
3698     HV
3699       *hv;
3700
3701     Image
3702       *image;
3703
3704     LayerMethod
3705       method;
3706
3707     register ssize_t
3708       i;
3709
3710     ssize_t
3711       option;
3712
3713     struct PackageInfo
3714       *info;
3715
3716     SV
3717       *av_reference,
3718       *perl_exception,
3719       *reference,
3720       *rv,
3721       *sv;
3722
3723     PERL_UNUSED_VAR(ref);
3724     PERL_UNUSED_VAR(ix);
3725     exception=AcquireExceptionInfo();
3726     perl_exception=newSVpv("",0);
3727     sv=NULL;
3728     if (sv_isobject(ST(0)) == 0)
3729       {
3730         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3731           PackageName);
3732         goto PerlException;
3733       }
3734     reference=SvRV(ST(0));
3735     hv=SvSTASH(reference);
3736     av=newAV();
3737     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3738     SvREFCNT_dec(av);
3739     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3740     if (image == (Image *) NULL)
3741       {
3742         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3743           PackageName);
3744         goto PerlException;
3745       }
3746     method=CompareAnyLayer;
3747     for (i=2; i < items; i+=2)
3748     {
3749       attribute=(char *) SvPV(ST(i-1),na);
3750       switch (*attribute)
3751       {
3752         case 'M':
3753         case 'm':
3754         {
3755           if (LocaleCompare(attribute,"method") == 0)
3756             {
3757               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3758                 SvPV(ST(i),na));
3759               if (option < 0)
3760                 {
3761                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3762                     SvPV(ST(i),na));
3763                   break;
3764                 }
3765                method=(LayerMethod) option;
3766               break;
3767             }
3768           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3769             attribute);
3770           break;
3771         }
3772         default:
3773         {
3774           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3775             attribute);
3776           break;
3777         }
3778       }
3779     }
3780     image=CompareImagesLayers(image,method,exception);
3781     if (image == (Image *) NULL)
3782       goto PerlException;
3783     for ( ; image; image=image->next)
3784     {
3785       AddImageToRegistry(sv,image);
3786       rv=newRV(sv);
3787       av_push(av,sv_bless(rv,hv));
3788       SvREFCNT_dec(sv);
3789     }
3790     exception=DestroyExceptionInfo(exception);
3791     ST(0)=av_reference;
3792     SvREFCNT_dec(perl_exception);
3793     XSRETURN(1);
3794
3795   PerlException:
3796     InheritPerlException(exception,perl_exception);
3797     exception=DestroyExceptionInfo(exception);
3798     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3799     SvPOK_on(perl_exception);
3800     ST(0)=sv_2mortal(perl_exception);
3801     XSRETURN(1);
3802   }
3803 \f
3804 #
3805 ###############################################################################
3806 #                                                                             #
3807 #                                                                             #
3808 #                                                                             #
3809 #   D e s t r o y                                                             #
3810 #                                                                             #
3811 #                                                                             #
3812 #                                                                             #
3813 ###############################################################################
3814 #
3815 #
3816 void
3817 DESTROY(ref)
3818   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3819   PPCODE:
3820   {
3821     SV
3822       *reference;
3823
3824     PERL_UNUSED_VAR(ref);
3825     if (sv_isobject(ST(0)) == 0)
3826       croak("ReferenceIsNotMyType");
3827     reference=SvRV(ST(0));
3828     switch (SvTYPE(reference))
3829     {
3830       case SVt_PVAV:
3831       {
3832         char
3833           message[MagickPathExtent];
3834
3835         const SV
3836           *key;
3837
3838         HV
3839           *hv;
3840
3841         GV
3842           **gvp;
3843
3844         struct PackageInfo
3845           *info;
3846
3847         SV
3848           *sv;
3849
3850         /*
3851           Array (AV *) reference
3852         */
3853         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3854           XS_VERSION,reference);
3855         hv=gv_stashpv(PackageName, FALSE);
3856         if (!hv)
3857           break;
3858         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3859         if (!gvp)
3860           break;
3861         sv=GvSV(*gvp);
3862         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3863           {
3864             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3865             DestroyPackageInfo(info);
3866           }
3867         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3868         (void) key;
3869         break;
3870       }
3871       case SVt_PVMG:
3872       {
3873         Image
3874           *image;
3875
3876         /*
3877           Blessed scalar = (Image *) SvIV(reference)
3878         */
3879         image=INT2PTR(Image *,SvIV(reference));
3880         if (image != (Image *) NULL)
3881           DeleteImageFromRegistry(reference,image);
3882         break;
3883       }
3884       default:
3885         break;
3886     }
3887   }
3888 \f
3889 #
3890 ###############################################################################
3891 #                                                                             #
3892 #                                                                             #
3893 #                                                                             #
3894 #   D i s p l a y                                                             #
3895 #                                                                             #
3896 #                                                                             #
3897 #                                                                             #
3898 ###############################################################################
3899 #
3900 #
3901 void
3902 Display(ref,...)
3903   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3904   ALIAS:
3905     DisplayImage  = 1
3906     display       = 2
3907     displayimage  = 3
3908   PPCODE:
3909   {
3910     ExceptionInfo
3911       *exception;
3912
3913     Image
3914       *image;
3915
3916     register ssize_t
3917       i;
3918
3919     struct PackageInfo
3920       *info,
3921       *package_info;
3922
3923     SV
3924       *perl_exception,
3925       *reference;
3926
3927     PERL_UNUSED_VAR(ref);
3928     PERL_UNUSED_VAR(ix);
3929     exception=AcquireExceptionInfo();
3930     perl_exception=newSVpv("",0);
3931     package_info=(struct PackageInfo *) NULL;
3932     if (sv_isobject(ST(0)) == 0)
3933       {
3934         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3935           PackageName);
3936         goto PerlException;
3937       }
3938     reference=SvRV(ST(0));
3939     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3940     if (image == (Image *) NULL)
3941       {
3942         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3943           PackageName);
3944         goto PerlException;
3945       }
3946     package_info=ClonePackageInfo(info,exception);
3947     if (items == 2)
3948       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3949     else
3950       if (items > 2)
3951         for (i=2; i < items; i+=2)
3952           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3953             exception);
3954     (void) DisplayImages(package_info->image_info,image,exception);
3955     (void) CatchImageException(image);
3956
3957   PerlException:
3958     if (package_info != (struct PackageInfo *) NULL)
3959       DestroyPackageInfo(package_info);
3960     InheritPerlException(exception,perl_exception);
3961     exception=DestroyExceptionInfo(exception);
3962     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3963     SvPOK_on(perl_exception);
3964     ST(0)=sv_2mortal(perl_exception);
3965     XSRETURN(1);
3966   }
3967 \f
3968 #
3969 ###############################################################################
3970 #                                                                             #
3971 #                                                                             #
3972 #                                                                             #
3973 #   E v a l u a t e I m a g e s                                               #
3974 #                                                                             #
3975 #                                                                             #
3976 #                                                                             #
3977 ###############################################################################
3978 #
3979 #
3980 void
3981 EvaluateImages(ref,...)
3982   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
3983   ALIAS:
3984     EvaluateImages   = 1
3985     evaluateimages   = 2
3986   PPCODE:
3987   {
3988     AV
3989       *av;
3990
3991     char
3992       *attribute,
3993       *p;
3994
3995     ExceptionInfo
3996       *exception;
3997
3998     HV
3999       *hv;
4000
4001     Image
4002       *image;
4003
4004     MagickEvaluateOperator
4005       op;
4006
4007     register ssize_t
4008       i;
4009
4010     struct PackageInfo
4011       *info;
4012
4013     SV
4014       *perl_exception,
4015       *reference,
4016       *rv,
4017       *sv;
4018
4019     PERL_UNUSED_VAR(ref);
4020     PERL_UNUSED_VAR(ix);
4021     exception=AcquireExceptionInfo();
4022     perl_exception=newSVpv("",0);
4023     sv=NULL;
4024     if (sv_isobject(ST(0)) == 0)
4025       {
4026         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4027           PackageName);
4028         goto PerlException;
4029       }
4030     reference=SvRV(ST(0));
4031     hv=SvSTASH(reference);
4032     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4033     if (image == (Image *) NULL)
4034       {
4035         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4036           PackageName);
4037         goto PerlException;
4038       }
4039     op=MeanEvaluateOperator;
4040     if (items == 2)
4041       {
4042         ssize_t
4043           in;
4044
4045         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
4046           SvPV(ST(1),na));
4047         if (in < 0)
4048           {
4049             ThrowPerlException(exception,OptionError,"UnrecognizedType",
4050               SvPV(ST(1),na));
4051             return;
4052           }
4053         op=(MagickEvaluateOperator) in;
4054       }
4055     else
4056       for (i=2; i < items; i+=2)
4057       {
4058         attribute=(char *) SvPV(ST(i-1),na);
4059         switch (*attribute)
4060         {
4061           case 'O':
4062           case 'o':
4063           {
4064             if (LocaleCompare(attribute,"operator") == 0)
4065               {
4066                 ssize_t
4067                   in;
4068
4069                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4070                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4071                 if (in < 0)
4072                   {
4073                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4074                       SvPV(ST(i),na));
4075                     return;
4076                   }
4077                 op=(MagickEvaluateOperator) in;
4078                 break;
4079               }
4080             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4081               attribute);
4082             break;
4083           }
4084           default:
4085           {
4086             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4087               attribute);
4088             break;
4089           }
4090         }
4091       }
4092     image=EvaluateImages(image,op,exception);
4093     if (image == (Image *) NULL)
4094       goto PerlException;
4095     /*
4096       Create blessed Perl array for the returned image.
4097     */
4098     av=newAV();
4099     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4100     SvREFCNT_dec(av);
4101     AddImageToRegistry(sv,image);
4102     rv=newRV(sv);
4103     av_push(av,sv_bless(rv,hv));
4104     SvREFCNT_dec(sv);
4105     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4106     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4107       "evaluate-%.*s",(int) (MagickPathExtent-9),
4108       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4109     (void) CopyMagickString(image->filename,info->image_info->filename,
4110       MagickPathExtent);
4111     SetImageInfo(info->image_info,0,exception);
4112     exception=DestroyExceptionInfo(exception);
4113     SvREFCNT_dec(perl_exception);
4114     XSRETURN(1);
4115
4116   PerlException:
4117     InheritPerlException(exception,perl_exception);
4118     exception=DestroyExceptionInfo(exception);
4119     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4120     SvPOK_on(perl_exception);
4121     ST(0)=sv_2mortal(perl_exception);
4122     XSRETURN(1);
4123   }
4124 \f
4125 #
4126 ###############################################################################
4127 #                                                                             #
4128 #                                                                             #
4129 #                                                                             #
4130 #   F e a t u r e s                                                           #
4131 #                                                                             #
4132 #                                                                             #
4133 #                                                                             #
4134 ###############################################################################
4135 #
4136 #
4137 void
4138 Features(ref,...)
4139   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4140   ALIAS:
4141     FeaturesImage = 1
4142     features      = 2
4143     featuresimage = 3
4144   PPCODE:
4145   {
4146 #define ChannelFeatures(channel,direction) \
4147 { \
4148   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4149     channel_features[channel].angular_second_moment[direction]); \
4150   PUSHs(sv_2mortal(newSVpv(message,0))); \
4151   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4152     channel_features[channel].contrast[direction]); \
4153   PUSHs(sv_2mortal(newSVpv(message,0))); \
4154   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4155     channel_features[channel].contrast[direction]); \
4156   PUSHs(sv_2mortal(newSVpv(message,0))); \
4157   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4158     channel_features[channel].variance_sum_of_squares[direction]); \
4159   PUSHs(sv_2mortal(newSVpv(message,0))); \
4160   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4161     channel_features[channel].inverse_difference_moment[direction]); \
4162   PUSHs(sv_2mortal(newSVpv(message,0))); \
4163   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4164     channel_features[channel].sum_average[direction]); \
4165   PUSHs(sv_2mortal(newSVpv(message,0))); \
4166   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4167     channel_features[channel].sum_variance[direction]); \
4168   PUSHs(sv_2mortal(newSVpv(message,0))); \
4169   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4170     channel_features[channel].sum_entropy[direction]); \
4171   PUSHs(sv_2mortal(newSVpv(message,0))); \
4172   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4173     channel_features[channel].entropy[direction]); \
4174   PUSHs(sv_2mortal(newSVpv(message,0))); \
4175   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4176     channel_features[channel].difference_variance[direction]); \
4177   PUSHs(sv_2mortal(newSVpv(message,0))); \
4178   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4179     channel_features[channel].difference_entropy[direction]); \
4180   PUSHs(sv_2mortal(newSVpv(message,0))); \
4181   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4182     channel_features[channel].measure_of_correlation_1[direction]); \
4183   PUSHs(sv_2mortal(newSVpv(message,0))); \
4184   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4185     channel_features[channel].measure_of_correlation_2[direction]); \
4186   PUSHs(sv_2mortal(newSVpv(message,0))); \
4187   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4188     channel_features[channel].maximum_correlation_coefficient[direction]); \
4189   PUSHs(sv_2mortal(newSVpv(message,0))); \
4190 }
4191
4192     AV
4193       *av;
4194
4195     char
4196       *attribute,
4197       message[MagickPathExtent];
4198
4199     ChannelFeatures
4200       *channel_features;
4201
4202     double
4203       distance;
4204
4205     ExceptionInfo
4206       *exception;
4207
4208     Image
4209       *image;
4210
4211     register ssize_t
4212       i;
4213
4214     ssize_t
4215       count;
4216
4217     struct PackageInfo
4218       *info;
4219
4220     SV
4221       *perl_exception,
4222       *reference;
4223
4224     PERL_UNUSED_VAR(ref);
4225     PERL_UNUSED_VAR(ix);
4226     exception=AcquireExceptionInfo();
4227     perl_exception=newSVpv("",0);
4228     av=NULL;
4229     if (sv_isobject(ST(0)) == 0)
4230       {
4231         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4232           PackageName);
4233         goto PerlException;
4234       }
4235     reference=SvRV(ST(0));
4236     av=newAV();
4237     SvREFCNT_dec(av);
4238     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4239     if (image == (Image *) NULL)
4240       {
4241         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4242           PackageName);
4243         goto PerlException;
4244       }
4245     distance=1.0;
4246     for (i=2; i < items; i+=2)
4247     {
4248       attribute=(char *) SvPV(ST(i-1),na);
4249       switch (*attribute)
4250       {
4251         case 'D':
4252         case 'd':
4253         {
4254           if (LocaleCompare(attribute,"distance") == 0)
4255             {
4256               distance=StringToLong((char *) SvPV(ST(1),na));
4257               break;
4258             }
4259           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4260             attribute);
4261           break;
4262         }
4263         default:
4264         {
4265           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4266             attribute);
4267           break;
4268         }
4269       }
4270     }
4271     count=0;
4272     for ( ; image; image=image->next)
4273     {
4274       register ssize_t
4275         j;
4276
4277       channel_features=GetImageFeatures(image,distance,exception);
4278       if (channel_features == (ChannelFeatures *) NULL)
4279         continue;
4280       count++;
4281       for (j=0; j < 4; j++)
4282       {
4283         for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4284         {
4285           PixelChannel channel=GetPixelChannelChannel(image,i);
4286           PixelTrait traits=GetPixelChannelTraits(image,channel);
4287           if (traits == UndefinedPixelTrait)
4288             continue;
4289           EXTEND(sp,14*(i+1)*count);
4290           ChannelFeatures(channel,j);
4291         }
4292       }
4293       channel_features=(ChannelFeatures *)
4294         RelinquishMagickMemory(channel_features);
4295     }
4296
4297   PerlException:
4298     InheritPerlException(exception,perl_exception);
4299     exception=DestroyExceptionInfo(exception);
4300     SvREFCNT_dec(perl_exception);
4301   }
4302 \f
4303 #
4304 ###############################################################################
4305 #                                                                             #
4306 #                                                                             #
4307 #                                                                             #
4308 #   F l a t t e n                                                             #
4309 #                                                                             #
4310 #                                                                             #
4311 #                                                                             #
4312 ###############################################################################
4313 #
4314 #
4315 void
4316 Flatten(ref,...)
4317   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4318   ALIAS:
4319     FlattenImage   = 1
4320     flatten        = 2
4321     flattenimage   = 3
4322   PPCODE:
4323   {
4324     AV
4325       *av;
4326
4327     char
4328       *attribute,
4329       *p;
4330
4331     ExceptionInfo
4332       *exception;
4333
4334     HV
4335       *hv;
4336
4337     Image
4338       *image;
4339
4340     PixelInfo
4341       background_color;
4342
4343     register ssize_t
4344       i;
4345
4346     struct PackageInfo
4347       *info;
4348
4349     SV
4350       *perl_exception,
4351       *reference,
4352       *rv,
4353       *sv;
4354
4355     PERL_UNUSED_VAR(ref);
4356     PERL_UNUSED_VAR(ix);
4357     exception=AcquireExceptionInfo();
4358     perl_exception=newSVpv("",0);
4359     sv=NULL;
4360     if (sv_isobject(ST(0)) == 0)
4361       {
4362         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4363           PackageName);
4364         goto PerlException;
4365       }
4366     reference=SvRV(ST(0));
4367     hv=SvSTASH(reference);
4368     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4369     if (image == (Image *) NULL)
4370       {
4371         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4372           PackageName);
4373         goto PerlException;
4374       }
4375     background_color=image->background_color;
4376     if (items == 2)
4377       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4378         &background_color,exception);
4379     else
4380       for (i=2; i < items; i+=2)
4381       {
4382         attribute=(char *) SvPV(ST(i-1),na);
4383         switch (*attribute)
4384         {
4385           case 'B':
4386           case 'b':
4387           {
4388             if (LocaleCompare(attribute,"background") == 0)
4389               {
4390                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4391                   AllCompliance,&background_color,exception);
4392                 break;
4393               }
4394             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4395               attribute);
4396             break;
4397           }
4398           default:
4399           {
4400             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4401               attribute);
4402             break;
4403           }
4404         }
4405       }
4406     image->background_color=background_color;
4407     image=MergeImageLayers(image,FlattenLayer,exception);
4408     if (image == (Image *) NULL)
4409       goto PerlException;
4410     /*
4411       Create blessed Perl array for the returned image.
4412     */
4413     av=newAV();
4414     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4415     SvREFCNT_dec(av);
4416     AddImageToRegistry(sv,image);
4417     rv=newRV(sv);
4418     av_push(av,sv_bless(rv,hv));
4419     SvREFCNT_dec(sv);
4420     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4421     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4422       "flatten-%.*s",(int) (MagickPathExtent-9),
4423       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4424     (void) CopyMagickString(image->filename,info->image_info->filename,
4425       MagickPathExtent);
4426     SetImageInfo(info->image_info,0,exception);
4427     exception=DestroyExceptionInfo(exception);
4428     SvREFCNT_dec(perl_exception);
4429     XSRETURN(1);
4430
4431   PerlException:
4432     InheritPerlException(exception,perl_exception);
4433     exception=DestroyExceptionInfo(exception);
4434     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4435     SvPOK_on(perl_exception);  /* return messages in string context */
4436     ST(0)=sv_2mortal(perl_exception);
4437     XSRETURN(1);
4438   }
4439 \f
4440 #
4441 ###############################################################################
4442 #                                                                             #
4443 #                                                                             #
4444 #                                                                             #
4445 #   F x                                                                       #
4446 #                                                                             #
4447 #                                                                             #
4448 #                                                                             #
4449 ###############################################################################
4450 #
4451 #
4452 void
4453 Fx(ref,...)
4454   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4455   ALIAS:
4456     FxImage  = 1
4457     fx       = 2
4458     fximage  = 3
4459   PPCODE:
4460   {
4461     AV
4462       *av;
4463
4464     char
4465       *attribute,
4466       expression[MagickPathExtent];
4467
4468     ChannelType
4469       channel,
4470       channel_mask;
4471
4472     ExceptionInfo
4473       *exception;
4474
4475     HV
4476       *hv;
4477
4478     Image
4479       *image;
4480
4481     register ssize_t
4482       i;
4483
4484     struct PackageInfo
4485       *info;
4486
4487     SV
4488       *av_reference,
4489       *perl_exception,
4490       *reference,
4491       *rv,
4492       *sv;
4493
4494     PERL_UNUSED_VAR(ref);
4495     PERL_UNUSED_VAR(ix);
4496     exception=AcquireExceptionInfo();
4497     perl_exception=newSVpv("",0);
4498     sv=NULL;
4499     attribute=NULL;
4500     av=NULL;
4501     if (sv_isobject(ST(0)) == 0)
4502       {
4503         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4504           PackageName);
4505         goto PerlException;
4506       }
4507     reference=SvRV(ST(0));
4508     hv=SvSTASH(reference);
4509     av=newAV();
4510     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4511     SvREFCNT_dec(av);
4512     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4513     if (image == (Image *) NULL)
4514       {
4515         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4516           PackageName);
4517         goto PerlException;
4518       }
4519     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4520     /*
4521       Get options.
4522     */
4523     channel=DefaultChannels;
4524     (void) CopyMagickString(expression,"u",MagickPathExtent);
4525     if (items == 2)
4526       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),
4527         MagickPathExtent);
4528     else
4529       for (i=2; i < items; i+=2)
4530       {
4531         attribute=(char *) SvPV(ST(i-1),na);
4532         switch (*attribute)
4533         {
4534           case 'C':
4535           case 'c':
4536           {
4537             if (LocaleCompare(attribute,"channel") == 0)
4538               {
4539                 ssize_t
4540                   option;
4541
4542                 option=ParseChannelOption(SvPV(ST(i),na));
4543                 if (option < 0)
4544                   {
4545                     ThrowPerlException(exception,OptionError,
4546                       "UnrecognizedType",SvPV(ST(i),na));
4547                     return;
4548                   }
4549                 channel=(ChannelType) option;
4550                 break;
4551               }
4552             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4553               attribute);
4554             break;
4555           }
4556           case 'E':
4557           case 'e':
4558           {
4559             if (LocaleCompare(attribute,"expression") == 0)
4560               {
4561                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4562                   MagickPathExtent);
4563                 break;
4564               }
4565             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4566               attribute);
4567             break;
4568           }
4569           default:
4570           {
4571             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4572               attribute);
4573             break;
4574           }
4575         }
4576       }
4577     channel_mask=SetImageChannelMask(image,channel);
4578     image=FxImage(image,expression,exception);
4579     if (image != (Image *) NULL)
4580       (void) SetImageChannelMask(image,channel_mask);
4581     if (image == (Image *) NULL)
4582       goto PerlException;
4583     for ( ; image; image=image->next)
4584     {
4585       AddImageToRegistry(sv,image);
4586       rv=newRV(sv);
4587       av_push(av,sv_bless(rv,hv));
4588       SvREFCNT_dec(sv);
4589     }
4590     exception=DestroyExceptionInfo(exception);
4591     ST(0)=av_reference;
4592     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4593     XSRETURN(1);
4594
4595   PerlException:
4596     InheritPerlException(exception,perl_exception);
4597     exception=DestroyExceptionInfo(exception);
4598     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4599     SvPOK_on(perl_exception);
4600     ST(0)=sv_2mortal(perl_exception);
4601     XSRETURN(1);
4602   }
4603 \f
4604 #
4605 ###############################################################################
4606 #                                                                             #
4607 #                                                                             #
4608 #                                                                             #
4609 #   G e t                                                                     #
4610 #                                                                             #
4611 #                                                                             #
4612 #                                                                             #
4613 ###############################################################################
4614 #
4615 #
4616 void
4617 Get(ref,...)
4618   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
4619   ALIAS:
4620     GetAttributes = 1
4621     GetAttribute  = 2
4622     get           = 3
4623     getattributes = 4
4624     getattribute  = 5
4625   PPCODE:
4626   {
4627     char
4628       *attribute,
4629       color[MagickPathExtent];
4630
4631     const char
4632       *value;
4633
4634     ExceptionInfo
4635       *exception;
4636
4637     Image
4638       *image;
4639
4640     long
4641       j;
4642
4643     register ssize_t
4644       i;
4645
4646     struct PackageInfo
4647       *info;
4648
4649     SV
4650       *perl_exception,
4651       *reference,
4652       *s;
4653
4654     PERL_UNUSED_VAR(ref);
4655     PERL_UNUSED_VAR(ix);
4656     exception=AcquireExceptionInfo();
4657     perl_exception=newSVpv("",0);
4658     if (sv_isobject(ST(0)) == 0)
4659       {
4660         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4661           PackageName);
4662         XSRETURN_EMPTY;
4663       }
4664     reference=SvRV(ST(0));
4665     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4666     if (image == (Image *) NULL && !info)
4667       XSRETURN_EMPTY;
4668     EXTEND(sp,items);
4669     for (i=1; i < items; i++)
4670     {
4671       attribute=(char *) SvPV(ST(i),na);
4672       s=NULL;
4673       switch (*attribute)
4674       {
4675         case 'A':
4676         case 'a':
4677         {
4678           if (LocaleCompare(attribute,"adjoin") == 0)
4679             {
4680               if (info)
4681                 s=newSViv((ssize_t) info->image_info->adjoin);
4682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683               continue;
4684             }
4685           if (LocaleCompare(attribute,"antialias") == 0)
4686             {
4687               if (info)
4688                 s=newSViv((ssize_t) info->image_info->antialias);
4689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4690               continue;
4691             }
4692           if (LocaleCompare(attribute,"area") == 0)
4693             {
4694               s=newSViv(GetMagickResource(AreaResource));
4695               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4696               continue;
4697             }
4698           if (LocaleCompare(attribute,"attenuate") == 0)
4699             {
4700               const char
4701                 *value;
4702
4703               value=GetImageProperty(image,attribute,exception);
4704               if (value != (const char *) NULL)
4705                 s=newSVpv(value,0);
4706               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4707               continue;
4708             }
4709           if (LocaleCompare(attribute,"authenticate") == 0)
4710             {
4711               if (info)
4712                 {
4713                   const char
4714                     *option;
4715
4716                   option=GetImageOption(info->image_info,attribute);
4717                   if (option != (const char *) NULL)
4718                     s=newSVpv(option,0);
4719                 }
4720               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4721               continue;
4722             }
4723           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4724             attribute);
4725           break;
4726         }
4727         case 'B':
4728         case 'b':
4729         {
4730           if (LocaleCompare(attribute,"background") == 0)
4731             {
4732               if (image == (Image *) NULL)
4733                 break;
4734               (void) FormatLocaleString(color,MagickPathExtent,
4735                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4736                 (double) image->background_color.green,
4737                 (double) image->background_color.blue,
4738                 (double) image->background_color.alpha);
4739               s=newSVpv(color,0);
4740               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4741               continue;
4742             }
4743           if (LocaleCompare(attribute,"base-columns") == 0)
4744             {
4745               if (image != (Image *) NULL)
4746                 s=newSViv((ssize_t) image->magick_columns);
4747               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4748               continue;
4749             }
4750           if (LocaleCompare(attribute,"base-filename") == 0)
4751             {
4752               if (image != (Image *) NULL)
4753                 s=newSVpv(image->magick_filename,0);
4754               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4755               continue;
4756             }
4757           if (LocaleCompare(attribute,"base-height") == 0)
4758             {
4759               if (image != (Image *) NULL)
4760                 s=newSViv((ssize_t) image->magick_rows);
4761               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4762               continue;
4763             }
4764           if (LocaleCompare(attribute,"base-rows") == 0)
4765             {
4766               if (image != (Image *) NULL)
4767                 s=newSViv((ssize_t) image->magick_rows);
4768               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4769               continue;
4770             }
4771           if (LocaleCompare(attribute,"base-width") == 0)
4772             {
4773               if (image != (Image *) NULL)
4774                 s=newSViv((ssize_t) image->magick_columns);
4775               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4776               continue;
4777             }
4778           if (LocaleCompare(attribute,"blue-primary") == 0)
4779             {
4780               if (image == (Image *) NULL)
4781                 break;
4782               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
4783                 image->chromaticity.blue_primary.x,
4784                 image->chromaticity.blue_primary.y);
4785               s=newSVpv(color,0);
4786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787               continue;
4788             }
4789           if (LocaleCompare(attribute,"bordercolor") == 0)
4790             {
4791               if (image == (Image *) NULL)
4792                 break;
4793               (void) FormatLocaleString(color,MagickPathExtent,
4794                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4795                 (double) image->border_color.green,
4796                 (double) image->border_color.blue,
4797                 (double) image->border_color.alpha);
4798               s=newSVpv(color,0);
4799               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4800               continue;
4801             }
4802           if (LocaleCompare(attribute,"bounding-box") == 0)
4803             {
4804               char
4805                 geometry[MagickPathExtent];
4806
4807               RectangleInfo
4808                 page;
4809
4810               if (image == (Image *) NULL)
4811                 break;
4812               page=GetImageBoundingBox(image,exception);
4813               (void) FormatLocaleString(geometry,MagickPathExtent,
4814                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4815                 page.height,(double) page.x,(double) page.y);
4816               s=newSVpv(geometry,0);
4817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818               continue;
4819             }
4820           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4821             attribute);
4822           break;
4823         }
4824         case 'C':
4825         case 'c':
4826         {
4827           if (LocaleCompare(attribute,"class") == 0)
4828             {
4829               if (image == (Image *) NULL)
4830                 break;
4831               s=newSViv(image->storage_class);
4832               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4833                 image->storage_class));
4834               SvIOK_on(s);
4835               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4836               continue;
4837             }
4838           if (LocaleCompare(attribute,"clip-mask") == 0)
4839             {
4840               if (image != (Image *) NULL)
4841                 {
4842                   Image
4843                     *mask_image;
4844
4845                   SV
4846                     *sv;
4847
4848                   sv=NULL;
4849                   if ((image->channels & WriteMaskChannel) == 0)
4850                     (void) ClipImage(image,exception);
4851                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4852                   if (mask_image != (Image *) NULL)
4853                     {
4854                       AddImageToRegistry(sv,mask_image);
4855                       s=sv_bless(newRV(sv),SvSTASH(reference));
4856                     }
4857                 }
4858               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4859               continue;
4860             }
4861           if (LocaleCompare(attribute,"clip-path") == 0)
4862             {
4863               if (image != (Image *) NULL)
4864                 {
4865                   Image
4866                     *mask_image;
4867
4868                   SV
4869                     *sv;
4870
4871                   sv=NULL;
4872                   if ((image->channels & WriteMaskChannel) == 0)
4873                     (void) ClipImage(image,exception);
4874                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4875                   if (mask_image != (Image *) NULL)
4876                     {
4877                       AddImageToRegistry(sv,mask_image);
4878                       s=sv_bless(newRV(sv),SvSTASH(reference));
4879                     }
4880                 }
4881               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4882               continue;
4883             }
4884           if (LocaleCompare(attribute,"compression") == 0)
4885             {
4886               j=info ? info->image_info->compression : image ?
4887                 image->compression : UndefinedCompression;
4888               if (info)
4889                 if (info->image_info->compression == UndefinedCompression)
4890                   j=image->compression;
4891               s=newSViv(j);
4892               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4893                 j));
4894               SvIOK_on(s);
4895               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4896               continue;
4897             }
4898           if (LocaleCompare(attribute,"colorspace") == 0)
4899             {
4900               j=image ? image->colorspace : RGBColorspace;
4901               s=newSViv(j);
4902               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4903                 j));
4904               SvIOK_on(s);
4905               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4906               continue;
4907             }
4908           if (LocaleCompare(attribute,"colors") == 0)
4909             {
4910               if (image != (Image *) NULL)
4911                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4912                   exception));
4913               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4914               continue;
4915             }
4916           if (LocaleNCompare(attribute,"colormap",8) == 0)
4917             {
4918               int
4919                 items;
4920
4921               if (image == (Image *) NULL || !image->colormap)
4922                 break;
4923               j=0;
4924               items=sscanf(attribute,"%*[^[][%ld",&j);
4925               (void) items;
4926               if (j > (ssize_t) image->colors)
4927                 j%=image->colors;
4928               (void) FormatLocaleString(color,MagickPathExtent,
4929                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4930                 (double) image->colormap[j].green,
4931                 (double) image->colormap[j].blue,
4932                 (double) image->colormap[j].alpha);
4933               s=newSVpv(color,0);
4934               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4935               continue;
4936             }
4937           if (LocaleCompare(attribute,"columns") == 0)
4938             {
4939               if (image != (Image *) NULL)
4940                 s=newSViv((ssize_t) image->columns);
4941               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4942               continue;
4943             }
4944           if (LocaleCompare(attribute,"comment") == 0)
4945             {
4946               const char
4947                 *value;
4948
4949               value=GetImageProperty(image,attribute,exception);
4950               if (value != (const char *) NULL)
4951                 s=newSVpv(value,0);
4952               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4953               continue;
4954             }
4955           if (LocaleCompare(attribute,"copyright") == 0)
4956             {
4957               s=newSVpv(GetMagickCopyright(),0);
4958               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4959               continue;
4960             }
4961           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4962             attribute);
4963           break;
4964         }
4965         case 'D':
4966         case 'd':
4967         {
4968           if (LocaleCompare(attribute,"density") == 0)
4969             {
4970               char
4971                 geometry[MagickPathExtent];
4972
4973               if (image == (Image *) NULL)
4974                 break;
4975               (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
4976                 image->resolution.x,image->resolution.y);
4977               s=newSVpv(geometry,0);
4978               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4979               continue;
4980             }
4981           if (LocaleCompare(attribute,"delay") == 0)
4982             {
4983               if (image != (Image *) NULL)
4984                 s=newSViv((ssize_t) image->delay);
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleCompare(attribute,"depth") == 0)
4989             {
4990               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4991               if (image != (Image *) NULL)
4992                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4993               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4994               continue;
4995             }
4996           if (LocaleCompare(attribute,"directory") == 0)
4997             {
4998               if (image && image->directory)
4999                 s=newSVpv(image->directory,0);
5000               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5001               continue;
5002             }
5003           if (LocaleCompare(attribute,"dispose") == 0)
5004             {
5005               if (image == (Image *) NULL)
5006                 break;
5007
5008               s=newSViv(image->dispose);
5009               (void) sv_setpv(s,
5010                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
5011               SvIOK_on(s);
5012               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5013               continue;
5014             }
5015           if (LocaleCompare(attribute,"disk") == 0)
5016             {
5017               s=newSViv(GetMagickResource(DiskResource));
5018               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5019               continue;
5020             }
5021           if (LocaleCompare(attribute,"dither") == 0)
5022             {
5023               if (info)
5024                 s=newSViv((ssize_t) info->image_info->dither);
5025               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5026               continue;
5027             }
5028           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
5029             {
5030               if (info && info->image_info->server_name)
5031                 s=newSVpv(info->image_info->server_name,0);
5032               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5033               continue;
5034             }
5035           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5036             attribute);
5037           break;
5038         }
5039         case 'E':
5040         case 'e':
5041         {
5042           if (LocaleCompare(attribute,"elapsed-time") == 0)
5043             {
5044               if (image != (Image *) NULL)
5045                 s=newSVnv(GetElapsedTime(&image->timer));
5046               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047               continue;
5048             }
5049           if (LocaleCompare(attribute,"endian") == 0)
5050             {
5051               j=info ? info->image_info->endian : image ? image->endian :
5052                 UndefinedEndian;
5053               s=newSViv(j);
5054               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
5055               SvIOK_on(s);
5056               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5057               continue;
5058             }
5059           if (LocaleCompare(attribute,"error") == 0)
5060             {
5061               if (image != (Image *) NULL)
5062                 s=newSVnv(image->error.mean_error_per_pixel);
5063               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5064               continue;
5065             }
5066           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5067             attribute);
5068           break;
5069         }
5070         case 'F':
5071         case 'f':
5072         {
5073           if (LocaleCompare(attribute,"filesize") == 0)
5074             {
5075               if (image != (Image *) NULL)
5076                 s=newSViv((ssize_t) GetBlobSize(image));
5077               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5078               continue;
5079             }
5080           if (LocaleCompare(attribute,"filename") == 0)
5081             {
5082               if (image != (Image *) NULL)
5083                 s=newSVpv(image->filename,0);
5084               else
5085                 if (info && *info->image_info->filename)
5086                   s=newSVpv(info->image_info->filename,0);
5087               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5088               continue;
5089             }
5090           if (LocaleCompare(attribute,"filter") == 0)
5091             {
5092               s=image ? newSViv(image->filter) : newSViv(0);
5093               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5094                 image->filter));
5095               SvIOK_on(s);
5096               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5097               continue;
5098             }
5099           if (LocaleCompare(attribute,"font") == 0)
5100             {
5101               if (info && info->image_info->font)
5102                 s=newSVpv(info->image_info->font,0);
5103               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5104               continue;
5105             }
5106           if (LocaleCompare(attribute,"foreground") == 0)
5107             continue;
5108           if (LocaleCompare(attribute,"format") == 0)
5109             {
5110               const MagickInfo
5111                 *magick_info;
5112
5113               magick_info=(const MagickInfo *) NULL;
5114               if (info && (*info->image_info->magick != '\0'))
5115                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5116               if (image != (Image *) NULL)
5117                 magick_info=GetMagickInfo(image->magick,exception);
5118               if ((magick_info != (const MagickInfo *) NULL) &&
5119                   (*magick_info->description != '\0'))
5120                 s=newSVpv((char *) magick_info->description,0);
5121               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122               continue;
5123             }
5124           if (LocaleCompare(attribute,"fuzz") == 0)
5125             {
5126               if (info)
5127                 s=newSVnv(info->image_info->fuzz);
5128               if (image != (Image *) NULL)
5129                 s=newSVnv(image->fuzz);
5130               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5131               continue;
5132             }
5133           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5134             attribute);
5135           break;
5136         }
5137         case 'G':
5138         case 'g':
5139         {
5140           if (LocaleCompare(attribute,"gamma") == 0)
5141             {
5142               if (image != (Image *) NULL)
5143                 s=newSVnv(image->gamma);
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           if (LocaleCompare(attribute,"geometry") == 0)
5148             {
5149               if (image && image->geometry)
5150                 s=newSVpv(image->geometry,0);
5151               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5152               continue;
5153             }
5154           if (LocaleCompare(attribute,"gravity") == 0)
5155             {
5156               s=image ? newSViv(image->gravity) : newSViv(0);
5157               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5158                 image->gravity));
5159               SvIOK_on(s);
5160               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5161               continue;
5162             }
5163           if (LocaleCompare(attribute,"green-primary") == 0)
5164             {
5165               if (image == (Image *) NULL)
5166                 break;
5167               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5168                 image->chromaticity.green_primary.x,
5169                 image->chromaticity.green_primary.y);
5170               s=newSVpv(color,0);
5171               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5172               continue;
5173             }
5174           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5175             attribute);
5176           break;
5177         }
5178         case 'H':
5179         case 'h':
5180         {
5181           if (LocaleCompare(attribute,"height") == 0)
5182             {
5183               if (image != (Image *) NULL)
5184                 s=newSViv((ssize_t) image->rows);
5185               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5186               continue;
5187             }
5188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5189             attribute);
5190           break;
5191         }
5192         case 'I':
5193         case 'i':
5194         {
5195           if (LocaleCompare(attribute,"icc") == 0)
5196             {
5197               if (image != (Image *) NULL)
5198                 {
5199                   const StringInfo
5200                     *profile;
5201
5202                   profile=GetImageProfile(image,"icc");
5203                   if (profile != (StringInfo *) NULL)
5204                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5205                       GetStringInfoLength(profile));
5206                 }
5207               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5208               continue;
5209             }
5210           if (LocaleCompare(attribute,"icm") == 0)
5211             {
5212               if (image != (Image *) NULL)
5213                 {
5214                   const StringInfo
5215                     *profile;
5216
5217                   profile=GetImageProfile(image,"icm");
5218                   if (profile != (const StringInfo *) NULL)
5219                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5220                       GetStringInfoLength(profile));
5221                 }
5222               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5223               continue;
5224             }
5225           if (LocaleCompare(attribute,"id") == 0)
5226             {
5227               if (image != (Image *) NULL)
5228                 {
5229                   char
5230                     key[MagickPathExtent];
5231
5232                   MagickBooleanType
5233                     status;
5234
5235                   static ssize_t
5236                     id = 0;
5237
5238                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5239                     id);
5240                   status=SetImageRegistry(ImageRegistryType,key,image,
5241                     exception);
5242                   (void) status;
5243                   s=newSViv(id++);
5244                 }
5245               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5246               continue;
5247             }
5248           if (LocaleNCompare(attribute,"index",5) == 0)
5249             {
5250               char
5251                 name[MagickPathExtent];
5252
5253               int
5254                 items;
5255
5256               long
5257                 x,
5258                 y;
5259
5260               register const Quantum
5261                 *p;
5262
5263               CacheView
5264                 *image_view;
5265
5266               if (image == (Image *) NULL)
5267                 break;
5268               if (image->storage_class != PseudoClass)
5269                 break;
5270               x=0;
5271               y=0;
5272               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5273               (void) items;
5274               image_view=AcquireVirtualCacheView(image,exception);
5275               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5276               if (p != (const Quantum *) NULL)
5277                 {
5278                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5279                     GetPixelIndex(image,p));
5280                   s=newSVpv(name,0);
5281                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5282                 }
5283               image_view=DestroyCacheView(image_view);
5284               continue;
5285             }
5286           if (LocaleCompare(attribute,"iptc") == 0)
5287             {
5288               if (image != (Image *) NULL)
5289                 {
5290                   const StringInfo
5291                     *profile;
5292
5293                   profile=GetImageProfile(image,"iptc");
5294                   if (profile != (const StringInfo *) NULL)
5295                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5296                       GetStringInfoLength(profile));
5297                 }
5298               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5299               continue;
5300             }
5301           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5302             {
5303               if (image != (Image *) NULL)
5304                 s=newSViv((ssize_t) image->iterations);
5305               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5306               continue;
5307             }
5308           if (LocaleCompare(attribute,"interlace") == 0)
5309             {
5310               j=info ? info->image_info->interlace : image ? image->interlace :
5311                 UndefinedInterlace;
5312               s=newSViv(j);
5313               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5314                 j));
5315               SvIOK_on(s);
5316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5317               continue;
5318             }
5319           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5320             attribute);
5321           break;
5322         }
5323         case 'L':
5324         case 'l':
5325         {
5326           if (LocaleCompare(attribute,"label") == 0)
5327             {
5328               const char
5329                 *value;
5330
5331               if (image == (Image *) NULL)
5332                 break;
5333               value=GetImageProperty(image,"Label",exception);
5334               if (value != (const char *) NULL)
5335                 s=newSVpv(value,0);
5336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5337               continue;
5338             }
5339           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5340             {
5341               if (image != (Image *) NULL)
5342                 s=newSViv((ssize_t) image->iterations);
5343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5344               continue;
5345             }
5346           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5347             attribute);
5348           break;
5349         }
5350         case 'M':
5351         case 'm':
5352         {
5353           if (LocaleCompare(attribute,"magick") == 0)
5354             {
5355               if (info && *info->image_info->magick)
5356                 s=newSVpv(info->image_info->magick,0);
5357               if (image != (Image *) NULL)
5358                 s=newSVpv(image->magick,0);
5359               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5360               continue;
5361             }
5362           if (LocaleCompare(attribute,"map") == 0)
5363             {
5364               s=newSViv(GetMagickResource(MapResource));
5365               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5366               continue;
5367             }
5368           if (LocaleCompare(attribute,"maximum-error") == 0)
5369             {
5370               if (image != (Image *) NULL)
5371                 s=newSVnv(image->error.normalized_maximum_error);
5372               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5373               continue;
5374             }
5375           if (LocaleCompare(attribute,"memory") == 0)
5376             {
5377               s=newSViv(GetMagickResource(MemoryResource));
5378               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5379               continue;
5380             }
5381           if (LocaleCompare(attribute,"mean-error") == 0)
5382             {
5383               if (image != (Image *) NULL)
5384                 s=newSVnv(image->error.normalized_mean_error);
5385               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386               continue;
5387             }
5388           if (LocaleCompare(attribute,"mime") == 0)
5389             {
5390               if (info && *info->image_info->magick)
5391                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5392               if (image != (Image *) NULL)
5393                 s=newSVpv(MagickToMime(image->magick),0);
5394               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5395               continue;
5396             }
5397           if (LocaleCompare(attribute,"mattecolor") == 0)
5398             {
5399               if (image == (Image *) NULL)
5400                 break;
5401               (void) FormatLocaleString(color,MagickPathExtent,
5402                 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5403                 (double) image->alpha_color.green,
5404                 (double) image->alpha_color.blue,
5405                 (double) image->alpha_color.alpha);
5406               s=newSVpv(color,0);
5407               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5408               continue;
5409             }
5410           if (LocaleCompare(attribute,"matte") == 0)
5411             {
5412               if (image != (Image *) NULL)
5413                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5414                   1 : 0);
5415               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5416               continue;
5417             }
5418           if (LocaleCompare(attribute,"mime") == 0)
5419             {
5420               const char
5421                 *magick;
5422
5423               magick=NULL;
5424               if (info && *info->image_info->magick)
5425                 magick=info->image_info->magick;
5426               if (image != (Image *) NULL)
5427                 magick=image->magick;
5428               if (magick)
5429                 {
5430                   char
5431                     *mime;
5432
5433                   mime=MagickToMime(magick);
5434                   s=newSVpv(mime,0);
5435                   mime=(char *) RelinquishMagickMemory(mime);
5436                 }
5437               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5438               continue;
5439             }
5440           if (LocaleCompare(attribute,"monochrome") == 0)
5441             {
5442               if (image == (Image *) NULL)
5443                 continue;
5444               j=info ? info->image_info->monochrome :
5445                 SetImageMonochrome(image,exception);
5446               s=newSViv(j);
5447               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5448               continue;
5449             }
5450           if (LocaleCompare(attribute,"montage") == 0)
5451             {
5452               if (image && image->montage)
5453                 s=newSVpv(image->montage,0);
5454               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5455               continue;
5456             }
5457           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5458             attribute);
5459           break;
5460         }
5461         case 'O':
5462         case 'o':
5463         {
5464           if (LocaleCompare(attribute,"orientation") == 0)
5465             {
5466               j=info ? info->image_info->orientation : image ?
5467                 image->orientation : UndefinedOrientation;
5468               s=newSViv(j);
5469               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5470                 j));
5471               SvIOK_on(s);
5472               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5473               continue;
5474             }
5475           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5476             attribute);
5477           break;
5478         }
5479         case 'P':
5480         case 'p':
5481         {
5482           if (LocaleCompare(attribute,"page") == 0)
5483             {
5484               if (info && info->image_info->page)
5485                 s=newSVpv(info->image_info->page,0);
5486               if (image != (Image *) NULL)
5487                 {
5488                   char
5489                     geometry[MagickPathExtent];
5490
5491                   (void) FormatLocaleString(geometry,MagickPathExtent,
5492                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5493                     (double) image->page.height,(double) image->page.x,(double)
5494                     image->page.y);
5495                   s=newSVpv(geometry,0);
5496                 }
5497               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5498               continue;
5499             }
5500           if (LocaleCompare(attribute,"page.x") == 0)
5501             {
5502               if (image != (Image *) NULL)
5503                 s=newSViv((ssize_t) image->page.x);
5504               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5505               continue;
5506             }
5507           if (LocaleCompare(attribute,"page.y") == 0)
5508             {
5509               if (image != (Image *) NULL)
5510                 s=newSViv((ssize_t) image->page.y);
5511               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5512               continue;
5513             }
5514           if (LocaleNCompare(attribute,"pixel",5) == 0)
5515             {
5516               char
5517                 tuple[MagickPathExtent];
5518
5519               int
5520                 items;
5521
5522               long
5523                 x,
5524                 y;
5525
5526               register const Quantum
5527                 *p;
5528
5529               if (image == (Image *) NULL)
5530                 break;
5531               x=0;
5532               y=0;
5533               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5534               (void) items;
5535               p=GetVirtualPixels(image,x,y,1,1,exception);
5536               if (image->colorspace != CMYKColorspace)
5537                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5538                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5539                   GetPixelRed(image,p),GetPixelGreen(image,p),
5540                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5541               else
5542                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5543                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5544                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5545                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5546                   GetPixelAlpha(image,p));
5547               s=newSVpv(tuple,0);
5548               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5549               continue;
5550             }
5551           if (LocaleCompare(attribute,"pointsize") == 0)
5552             {
5553               if (info)
5554                 s=newSViv((ssize_t) info->image_info->pointsize);
5555               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5556               continue;
5557             }
5558           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5559             attribute);
5560           break;
5561         }
5562         case 'Q':
5563         case 'q':
5564         {
5565           if (LocaleCompare(attribute,"quality") == 0)
5566             {
5567               if (info)
5568                 s=newSViv((ssize_t) info->image_info->quality);
5569               if (image != (Image *) NULL)
5570                 s=newSViv((ssize_t) image->quality);
5571               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5572               continue;
5573             }
5574           if (LocaleCompare(attribute,"quantum") == 0)
5575             {
5576               if (info)
5577                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5579               continue;
5580             }
5581           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5582             attribute);
5583           break;
5584         }
5585         case 'R':
5586         case 'r':
5587         {
5588           if (LocaleCompare(attribute,"rendering-intent") == 0)
5589             {
5590               s=newSViv(image->rendering_intent);
5591               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5592                 image->rendering_intent));
5593               SvIOK_on(s);
5594               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5595               continue;
5596             }
5597           if (LocaleCompare(attribute,"red-primary") == 0)
5598             {
5599               if (image == (Image *) NULL)
5600                 break;
5601               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5602                 image->chromaticity.red_primary.x,
5603                 image->chromaticity.red_primary.y);
5604               s=newSVpv(color,0);
5605               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5606               continue;
5607             }
5608           if (LocaleCompare(attribute,"rows") == 0)
5609             {
5610               if (image != (Image *) NULL)
5611                 s=newSViv((ssize_t) image->rows);
5612               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5613               continue;
5614             }
5615           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5616             attribute);
5617           break;
5618         }
5619         case 'S':
5620         case 's':
5621         {
5622           if (LocaleCompare(attribute,"sampling-factor") == 0)
5623             {
5624               if (info && info->image_info->sampling_factor)
5625                 s=newSVpv(info->image_info->sampling_factor,0);
5626               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5627               continue;
5628             }
5629           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5630             {
5631               if (info && info->image_info->server_name)
5632                 s=newSVpv(info->image_info->server_name,0);
5633               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5634               continue;
5635             }
5636           if (LocaleCompare(attribute,"size") == 0)
5637             {
5638               if (info && info->image_info->size)
5639                 s=newSVpv(info->image_info->size,0);
5640               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5641               continue;
5642             }
5643           if (LocaleCompare(attribute,"scene") == 0)
5644             {
5645               if (image != (Image *) NULL)
5646                 s=newSViv((ssize_t) image->scene);
5647               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5648               continue;
5649             }
5650           if (LocaleCompare(attribute,"scenes") == 0)
5651             {
5652               if (image != (Image *) NULL)
5653                 s=newSViv((ssize_t) info->image_info->number_scenes);
5654               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5655               continue;
5656             }
5657           if (LocaleCompare(attribute,"signature") == 0)
5658             {
5659               const char
5660                 *value;
5661
5662               if (image == (Image *) NULL)
5663                 break;
5664               (void) SignatureImage(image,exception);
5665               value=GetImageProperty(image,"Signature",exception);
5666               if (value != (const char *) NULL)
5667                 s=newSVpv(value,0);
5668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5669               continue;
5670             }
5671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5672             attribute);
5673           break;
5674         }
5675         case 'T':
5676         case 't':
5677         {
5678           if (LocaleCompare(attribute,"taint") == 0)
5679             {
5680               if (image != (Image *) NULL)
5681                 s=newSViv((ssize_t) IsTaintImage(image));
5682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5683               continue;
5684             }
5685           if (LocaleCompare(attribute,"texture") == 0)
5686             {
5687               if (info && info->image_info->texture)
5688                 s=newSVpv(info->image_info->texture,0);
5689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5690               continue;
5691             }
5692           if (LocaleCompare(attribute,"total-ink-density") == 0)
5693             {
5694               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5695               if (image != (Image *) NULL)
5696                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698               continue;
5699             }
5700           if (LocaleCompare(attribute,"transparent-color") == 0)
5701             {
5702               if (image == (Image *) NULL)
5703                 break;
5704               (void) FormatLocaleString(color,MagickPathExtent,
5705                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5706                 (double) image->transparent_color.green,
5707                 (double) image->transparent_color.blue,
5708                 (double) image->transparent_color.alpha);
5709               s=newSVpv(color,0);
5710               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5711               continue;
5712             }
5713           if (LocaleCompare(attribute,"type") == 0)
5714             {
5715               if (image == (Image *) NULL)
5716                 break;
5717               j=(ssize_t) GetImageType(image);
5718               s=newSViv(j);
5719               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5720               SvIOK_on(s);
5721               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5722               continue;
5723             }
5724           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5725             attribute);
5726           break;
5727         }
5728         case 'U':
5729         case 'u':
5730         {
5731           if (LocaleCompare(attribute,"units") == 0)
5732             {
5733               j=info ? info->image_info->units : image ? image->units :
5734                 UndefinedResolution;
5735               if (info && (info->image_info->units == UndefinedResolution))
5736                 if (image)
5737                   j=image->units;
5738               if (j == UndefinedResolution)
5739                 s=newSVpv("undefined units",0);
5740               else
5741                 if (j == PixelsPerInchResolution)
5742                   s=newSVpv("pixels / inch",0);
5743                 else
5744                   s=newSVpv("pixels / centimeter",0);
5745               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5746               continue;
5747             }
5748           if (LocaleCompare(attribute,"user-time") == 0)
5749             {
5750               if (image != (Image *) NULL)
5751                 s=newSVnv(GetUserTime(&image->timer));
5752               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5753               continue;
5754             }
5755           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5756             attribute);
5757           break;
5758         }
5759         case 'V':
5760         case 'v':
5761         {
5762           if (LocaleCompare(attribute,"verbose") == 0)
5763             {
5764               if (info)
5765                 s=newSViv((ssize_t) info->image_info->verbose);
5766               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5767               continue;
5768             }
5769           if (LocaleCompare(attribute,"version") == 0)
5770             {
5771               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5773               continue;
5774             }
5775           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5776             {
5777               if (image == (Image *) NULL)
5778                 break;
5779               j=(ssize_t) GetImageVirtualPixelMethod(image);
5780               s=newSViv(j);
5781               (void) sv_setpv(s,CommandOptionToMnemonic(
5782                 MagickVirtualPixelOptions,j));
5783               SvIOK_on(s);
5784               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5785               continue;
5786             }
5787           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5788             attribute);
5789           break;
5790         }
5791         case 'W':
5792         case 'w':
5793         {
5794           if (LocaleCompare(attribute,"white-point") == 0)
5795             {
5796               if (image == (Image *) NULL)
5797                 break;
5798               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5799                 image->chromaticity.white_point.x,
5800                 image->chromaticity.white_point.y);
5801               s=newSVpv(color,0);
5802               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5803               continue;
5804             }
5805           if (LocaleCompare(attribute,"width") == 0)
5806             {
5807               if (image != (Image *) NULL)
5808                 s=newSViv((ssize_t) image->columns);
5809               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5810               continue;
5811             }
5812           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5813              attribute);
5814           break;
5815         }
5816         case 'X':
5817         case 'x':
5818         {
5819           if (LocaleCompare(attribute,"xmp") == 0)
5820             {
5821               if (image != (Image *) NULL)
5822                 {
5823                   const StringInfo
5824                     *profile;
5825
5826                   profile=GetImageProfile(image,"xmp");
5827                   if (profile != (StringInfo *) NULL)
5828                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5829                       GetStringInfoLength(profile));
5830                 }
5831               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5832               continue;
5833             }
5834           if (LocaleCompare(attribute,"x-resolution") == 0)
5835             {
5836               if (image != (Image *) NULL)
5837                 s=newSVnv(image->resolution.x);
5838               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5839               continue;
5840             }
5841           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5842             attribute);
5843           break;
5844         }
5845         case 'Y':
5846         case 'y':
5847         {
5848           if (LocaleCompare(attribute,"y-resolution") == 0)
5849             {
5850               if (image != (Image *) NULL)
5851                 s=newSVnv(image->resolution.y);
5852               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5853               continue;
5854             }
5855           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5856             attribute);
5857           break;
5858         }
5859         default:
5860           break;
5861       }
5862       if (image == (Image *) NULL)
5863         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5864           attribute)
5865       else
5866         {
5867           value=GetImageProperty(image,attribute,exception);
5868           if (value != (const char *) NULL)
5869             {
5870               s=newSVpv(value,0);
5871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5872             }
5873           else
5874             if (*attribute != '%')
5875               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5876                 attribute)
5877             else
5878               {
5879                  char
5880                    *meta;
5881
5882                  meta=InterpretImageProperties(info ? info->image_info :
5883                    (ImageInfo *) NULL,image,attribute,exception);
5884                  s=newSVpv(meta,0);
5885                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5886                  meta=(char *) RelinquishMagickMemory(meta);
5887               }
5888         }
5889     }
5890     exception=DestroyExceptionInfo(exception);
5891     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5892   }
5893 \f
5894 #
5895 ###############################################################################
5896 #                                                                             #
5897 #                                                                             #
5898 #                                                                             #
5899 #   G e t A u t h e n t i c P i x e l s                                       #
5900 #                                                                             #
5901 #                                                                             #
5902 #                                                                             #
5903 ###############################################################################
5904 #
5905 #
5906 void *
5907 GetAuthenticPixels(ref,...)
5908   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
5909   ALIAS:
5910     getauthenticpixels = 1
5911     GetImagePixels = 2
5912     getimagepixels = 3
5913   CODE:
5914   {
5915     char
5916       *attribute;
5917
5918     ExceptionInfo
5919       *exception;
5920
5921     Image
5922       *image;
5923
5924     RectangleInfo
5925       region;
5926
5927     ssize_t
5928       i;
5929
5930     struct PackageInfo
5931       *info;
5932
5933     SV
5934       *perl_exception,
5935       *reference;
5936
5937     void
5938       *blob = NULL;
5939
5940     PERL_UNUSED_VAR(ref);
5941     PERL_UNUSED_VAR(ix);
5942     exception=AcquireExceptionInfo();
5943     perl_exception=newSVpv("",0);
5944     if (sv_isobject(ST(0)) == 0)
5945       {
5946         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5947           PackageName);
5948         goto PerlException;
5949       }
5950     reference=SvRV(ST(0));
5951
5952     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5953     if (image == (Image *) NULL)
5954       {
5955         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5956           PackageName);
5957         goto PerlException;
5958       }
5959
5960     region.x=0;
5961     region.y=0;
5962     region.width=image->columns;
5963     region.height=1;
5964     if (items == 1)
5965       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5966     for (i=2; i < items; i+=2)
5967     {
5968       attribute=(char *) SvPV(ST(i-1),na);
5969       switch (*attribute)
5970       {
5971         case 'g':
5972         case 'G':
5973         {
5974           if (LocaleCompare(attribute,"geometry") == 0)
5975             {
5976               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5977               break;
5978             }
5979           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5980             attribute);
5981           break;
5982         }
5983         case 'H':
5984         case 'h':
5985         {
5986           if (LocaleCompare(attribute,"height") == 0)
5987             {
5988               region.height=SvIV(ST(i));
5989               continue;
5990             }
5991           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5992             attribute);
5993           break;
5994         }
5995         case 'X':
5996         case 'x':
5997         {
5998           if (LocaleCompare(attribute,"x") == 0)
5999             {
6000               region.x=SvIV(ST(i));
6001               continue;
6002             }
6003           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6004             attribute);
6005           break;
6006         }
6007         case 'Y':
6008         case 'y':
6009         {
6010           if (LocaleCompare(attribute,"y") == 0)
6011             {
6012               region.y=SvIV(ST(i));
6013               continue;
6014             }
6015           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6016             attribute);
6017           break;
6018         }
6019         case 'W':
6020         case 'w':
6021         {
6022           if (LocaleCompare(attribute,"width") == 0)
6023             {
6024               region.width=SvIV(ST(i));
6025               continue;
6026             }
6027           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6028             attribute);
6029           break;
6030         }
6031       }
6032     }
6033     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
6034       region.height,exception);
6035     if (blob != (void *) NULL)
6036       goto PerlEnd;
6037
6038   PerlException:
6039     InheritPerlException(exception,perl_exception);
6040     exception=DestroyExceptionInfo(exception);
6041     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6042
6043   PerlEnd:
6044     RETVAL = blob;
6045   }
6046   OUTPUT:
6047     RETVAL
6048 \f
6049 #
6050 ###############################################################################
6051 #                                                                             #
6052 #                                                                             #
6053 #                                                                             #
6054 #   G e t V i r t u a l P i x e l s                                           #
6055 #                                                                             #
6056 #                                                                             #
6057 #                                                                             #
6058 ###############################################################################
6059 #
6060 #
6061 void *
6062 GetVirtualPixels(ref,...)
6063   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6064   ALIAS:
6065     getvirtualpixels = 1
6066     AcquireImagePixels = 2
6067     acquireimagepixels = 3
6068   CODE:
6069   {
6070     char
6071       *attribute;
6072
6073     const void
6074       *blob = NULL;
6075
6076     ExceptionInfo
6077       *exception;
6078
6079     Image
6080       *image;
6081
6082     RectangleInfo
6083       region;
6084
6085     ssize_t
6086       i;
6087
6088     struct PackageInfo
6089       *info;
6090
6091     SV
6092       *perl_exception,
6093       *reference;
6094
6095     PERL_UNUSED_VAR(ref);
6096     PERL_UNUSED_VAR(ix);
6097     exception=AcquireExceptionInfo();
6098     perl_exception=newSVpv("",0);
6099     if (sv_isobject(ST(0)) == 0)
6100       {
6101         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6102           PackageName);
6103         goto PerlException;
6104       }
6105     reference=SvRV(ST(0));
6106
6107     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6108     if (image == (Image *) NULL)
6109       {
6110         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6111           PackageName);
6112         goto PerlException;
6113       }
6114
6115     region.x=0;
6116     region.y=0;
6117     region.width=image->columns;
6118     region.height=1;
6119     if (items == 1)
6120       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6121     for (i=2; i < items; i+=2)
6122     {
6123       attribute=(char *) SvPV(ST(i-1),na);
6124       switch (*attribute)
6125       {
6126         case 'g':
6127         case 'G':
6128         {
6129           if (LocaleCompare(attribute,"geometry") == 0)
6130             {
6131               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6132               break;
6133             }
6134           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6135             attribute);
6136           break;
6137         }
6138         case 'H':
6139         case 'h':
6140         {
6141           if (LocaleCompare(attribute,"height") == 0)
6142             {
6143               region.height=SvIV(ST(i));
6144               continue;
6145             }
6146           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6147             attribute);
6148           break;
6149         }
6150         case 'X':
6151         case 'x':
6152         {
6153           if (LocaleCompare(attribute,"x") == 0)
6154             {
6155               region.x=SvIV(ST(i));
6156               continue;
6157             }
6158           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6159             attribute);
6160           break;
6161         }
6162         case 'Y':
6163         case 'y':
6164         {
6165           if (LocaleCompare(attribute,"y") == 0)
6166             {
6167               region.y=SvIV(ST(i));
6168               continue;
6169             }
6170           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6171             attribute);
6172           break;
6173         }
6174         case 'W':
6175         case 'w':
6176         {
6177           if (LocaleCompare(attribute,"width") == 0)
6178             {
6179               region.width=SvIV(ST(i));
6180               continue;
6181             }
6182           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6183             attribute);
6184           break;
6185         }
6186       }
6187     }
6188     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6189       region.height,exception);
6190     if (blob != (void *) NULL)
6191       goto PerlEnd;
6192
6193   PerlException:
6194     InheritPerlException(exception,perl_exception);
6195     exception=DestroyExceptionInfo(exception);
6196     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6197
6198   PerlEnd:
6199     RETVAL = (void *) blob;
6200   }
6201   OUTPUT:
6202     RETVAL
6203 \f
6204 #
6205 ###############################################################################
6206 #                                                                             #
6207 #                                                                             #
6208 #                                                                             #
6209 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6210 #                                                                             #
6211 #                                                                             #
6212 #                                                                             #
6213 ###############################################################################
6214 #
6215 #
6216 void *
6217 GetAuthenticMetacontent(ref,...)
6218   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6219   ALIAS:
6220     getauthenticmetacontent = 1
6221     GetMetacontent = 2
6222     getmetacontent = 3
6223   CODE:
6224   {
6225     ExceptionInfo
6226       *exception;
6227
6228     Image
6229       *image;
6230
6231     struct PackageInfo
6232       *info;
6233
6234     SV
6235       *perl_exception,
6236       *reference;
6237
6238     void
6239       *blob = NULL;
6240
6241     PERL_UNUSED_VAR(ref);
6242     PERL_UNUSED_VAR(ix);
6243     exception=AcquireExceptionInfo();
6244     perl_exception=newSVpv("",0);
6245     if (sv_isobject(ST(0)) == 0)
6246       {
6247         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6248           PackageName);
6249         goto PerlException;
6250       }
6251     reference=SvRV(ST(0));
6252
6253     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6254     if (image == (Image *) NULL)
6255       {
6256         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6257           PackageName);
6258         goto PerlException;
6259       }
6260
6261     blob=(void *) GetAuthenticMetacontent(image);
6262     if (blob != (void *) NULL)
6263       goto PerlEnd;
6264
6265   PerlException:
6266     InheritPerlException(exception,perl_exception);
6267     exception=DestroyExceptionInfo(exception);
6268     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6269
6270   PerlEnd:
6271     RETVAL = blob;
6272   }
6273   OUTPUT:
6274     RETVAL
6275 \f
6276 #
6277 ###############################################################################
6278 #                                                                             #
6279 #                                                                             #
6280 #                                                                             #
6281 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6282 #                                                                             #
6283 #                                                                             #
6284 #                                                                             #
6285 ###############################################################################
6286 #
6287 #
6288 void *
6289 GetVirtualMetacontent(ref,...)
6290   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6291   ALIAS:
6292     getvirtualmetacontent = 1
6293   CODE:
6294   {
6295     ExceptionInfo
6296       *exception;
6297
6298     Image
6299       *image;
6300
6301     struct PackageInfo
6302       *info;
6303
6304     SV
6305       *perl_exception,
6306       *reference;
6307
6308     void
6309       *blob = NULL;
6310
6311     PERL_UNUSED_VAR(ref);
6312     PERL_UNUSED_VAR(ix);
6313     exception=AcquireExceptionInfo();
6314     perl_exception=newSVpv("",0);
6315     if (sv_isobject(ST(0)) == 0)
6316       {
6317         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6318           PackageName);
6319         goto PerlException;
6320       }
6321     reference=SvRV(ST(0));
6322
6323     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6324     if (image == (Image *) NULL)
6325       {
6326         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6327           PackageName);
6328         goto PerlException;
6329       }
6330
6331     blob=(void *) GetVirtualMetacontent(image);
6332     if (blob != (void *) NULL)
6333       goto PerlEnd;
6334
6335   PerlException:
6336     InheritPerlException(exception,perl_exception);
6337     exception=DestroyExceptionInfo(exception);
6338     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6339
6340   PerlEnd:
6341     RETVAL = blob;
6342   }
6343   OUTPUT:
6344     RETVAL
6345 \f
6346 #
6347 ###############################################################################
6348 #                                                                             #
6349 #                                                                             #
6350 #                                                                             #
6351 #   H i s t o g r a m                                                         #
6352 #                                                                             #
6353 #                                                                             #
6354 #                                                                             #
6355 ###############################################################################
6356 #
6357 #
6358 void
6359 Histogram(ref,...)
6360   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6361   ALIAS:
6362     HistogramImage = 1
6363     histogram      = 2
6364     histogramimage = 3
6365   PPCODE:
6366   {
6367     AV
6368       *av;
6369
6370     char
6371       message[MagickPathExtent];
6372
6373     PixelInfo
6374       *histogram;
6375
6376     ExceptionInfo
6377       *exception;
6378
6379     Image
6380       *image;
6381
6382     register ssize_t
6383       i;
6384
6385     ssize_t
6386       count;
6387
6388     struct PackageInfo
6389       *info;
6390
6391     SV
6392       *perl_exception,
6393       *reference;
6394
6395     size_t
6396       number_colors;
6397
6398     PERL_UNUSED_VAR(ref);
6399     PERL_UNUSED_VAR(ix);
6400     exception=AcquireExceptionInfo();
6401     perl_exception=newSVpv("",0);
6402     av=NULL;
6403     if (sv_isobject(ST(0)) == 0)
6404       {
6405         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6406           PackageName);
6407         goto PerlException;
6408       }
6409     reference=SvRV(ST(0));
6410     av=newAV();
6411     SvREFCNT_dec(av);
6412     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6413     if (image == (Image *) NULL)
6414       {
6415         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6416           PackageName);
6417         goto PerlException;
6418       }
6419     count=0;
6420     for ( ; image; image=image->next)
6421     {
6422       histogram=GetImageHistogram(image,&number_colors,exception);
6423       if (histogram == (PixelInfo *) NULL)
6424         continue;
6425       count+=(ssize_t) number_colors;
6426       EXTEND(sp,6*count);
6427       for (i=0; i < (ssize_t) number_colors; i++)
6428       {
6429         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6430           histogram[i].red);
6431         PUSHs(sv_2mortal(newSVpv(message,0)));
6432         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6433           histogram[i].green);
6434         PUSHs(sv_2mortal(newSVpv(message,0)));
6435         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6436           histogram[i].blue);
6437         PUSHs(sv_2mortal(newSVpv(message,0)));
6438         if (image->colorspace == CMYKColorspace)
6439           {
6440             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6441               histogram[i].black);
6442             PUSHs(sv_2mortal(newSVpv(message,0)));
6443           }
6444         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6445           histogram[i].alpha);
6446         PUSHs(sv_2mortal(newSVpv(message,0)));
6447         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6448           histogram[i].count);
6449         PUSHs(sv_2mortal(newSVpv(message,0)));
6450       }
6451       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6452     }
6453
6454   PerlException:
6455     InheritPerlException(exception,perl_exception);
6456     exception=DestroyExceptionInfo(exception);
6457     SvREFCNT_dec(perl_exception);
6458   }
6459 \f
6460 #
6461 ###############################################################################
6462 #                                                                             #
6463 #                                                                             #
6464 #                                                                             #
6465 #   G e t P i x e l                                                           #
6466 #                                                                             #
6467 #                                                                             #
6468 #                                                                             #
6469 ###############################################################################
6470 #
6471 #
6472 void
6473 GetPixel(ref,...)
6474   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6475   ALIAS:
6476     getpixel = 1
6477     getPixel = 2
6478   PPCODE:
6479   {
6480     AV
6481       *av;
6482
6483     char
6484       *attribute;
6485
6486     ExceptionInfo
6487       *exception;
6488
6489     Image
6490       *image;
6491
6492     MagickBooleanType
6493       normalize;
6494
6495     RectangleInfo
6496       region;
6497
6498     register const Quantum
6499       *p;
6500
6501     register ssize_t
6502       i;
6503
6504     ssize_t
6505       option;
6506
6507     struct PackageInfo
6508       *info;
6509
6510     SV
6511       *perl_exception,
6512       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6513
6514     PERL_UNUSED_VAR(ref);
6515     PERL_UNUSED_VAR(ix);
6516     exception=AcquireExceptionInfo();
6517     perl_exception=newSVpv("",0);
6518     reference=SvRV(ST(0));
6519     av=(AV *) reference;
6520     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6521       exception);
6522     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6523     if (image == (Image *) NULL)
6524       {
6525         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6526           PackageName);
6527         goto PerlException;
6528       }
6529     normalize=MagickTrue;
6530     region.x=0;
6531     region.y=0;
6532     region.width=image->columns;
6533     region.height=1;
6534     if (items == 1)
6535       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6536     for (i=2; i < items; i+=2)
6537     {
6538       attribute=(char *) SvPV(ST(i-1),na);
6539       switch (*attribute)
6540       {
6541         case 'C':
6542         case 'c':
6543         {
6544           if (LocaleCompare(attribute,"channel") == 0)
6545             {
6546               ssize_t
6547                 option;
6548
6549               option=ParseChannelOption(SvPV(ST(i),na));
6550               if (option < 0)
6551                 {
6552                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6553                     SvPV(ST(i),na));
6554                   return;
6555                 }
6556               (void) SetPixelChannelMask(image,(ChannelType) option);
6557               break;
6558             }
6559           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6560             attribute);
6561           break;
6562         }
6563         case 'g':
6564         case 'G':
6565         {
6566           if (LocaleCompare(attribute,"geometry") == 0)
6567             {
6568               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6569               break;
6570             }
6571           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6572             attribute);
6573           break;
6574         }
6575         case 'N':
6576         case 'n':
6577         {
6578           if (LocaleCompare(attribute,"normalize") == 0)
6579             {
6580               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6581                 SvPV(ST(i),na));
6582               if (option < 0)
6583                 {
6584                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6585                     SvPV(ST(i),na));
6586                   break;
6587                 }
6588              normalize=option != 0 ? MagickTrue : MagickFalse;
6589              break;
6590             }
6591           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6592             attribute);
6593           break;
6594         }
6595         case 'x':
6596         case 'X':
6597         {
6598           if (LocaleCompare(attribute,"x") == 0)
6599             {
6600               region.x=SvIV(ST(i));
6601               break;
6602             }
6603           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6604             attribute);
6605           break;
6606         }
6607         case 'y':
6608         case 'Y':
6609         {
6610           if (LocaleCompare(attribute,"y") == 0)
6611             {
6612               region.y=SvIV(ST(i));
6613               break;
6614             }
6615           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6616             attribute);
6617           break;
6618         }
6619         default:
6620         {
6621           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6622             attribute);
6623           break;
6624         }
6625       }
6626     }
6627     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6628     if (p == (const Quantum *) NULL)
6629       PUSHs(&sv_undef);
6630     else
6631       {
6632         double
6633           scale;
6634
6635         scale=1.0;
6636         if (normalize != MagickFalse)
6637           scale=1.0/QuantumRange;
6638         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6639           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6640         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6641           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6642         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6643           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6644         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6645             (image->colorspace == CMYKColorspace))
6646           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6647         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6648           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6649       }
6650
6651   PerlException:
6652     InheritPerlException(exception,perl_exception);
6653     exception=DestroyExceptionInfo(exception);
6654     SvREFCNT_dec(perl_exception);
6655   }
6656 \f
6657 #
6658 ###############################################################################
6659 #                                                                             #
6660 #                                                                             #
6661 #                                                                             #
6662 #   G e t P i x e l s                                                         #
6663 #                                                                             #
6664 #                                                                             #
6665 #                                                                             #
6666 ###############################################################################
6667 #
6668 #
6669 void
6670 GetPixels(ref,...)
6671   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6672   ALIAS:
6673     getpixels = 1
6674     getPixels = 2
6675   PPCODE:
6676   {
6677     AV
6678       *av;
6679
6680     char
6681       *attribute;
6682
6683     const char
6684       *map;
6685
6686     ExceptionInfo
6687       *exception;
6688
6689     Image
6690       *image;
6691
6692     MagickBooleanType
6693       normalize,
6694       status;
6695
6696     RectangleInfo
6697       region;
6698
6699     register ssize_t
6700       i;
6701
6702     ssize_t
6703       option;
6704
6705     struct PackageInfo
6706       *info;
6707
6708     SV
6709       *perl_exception,
6710       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6711
6712     PERL_UNUSED_VAR(ref);
6713     PERL_UNUSED_VAR(ix);
6714     exception=AcquireExceptionInfo();
6715     perl_exception=newSVpv("",0);
6716     reference=SvRV(ST(0));
6717     av=(AV *) reference;
6718     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6719       exception);
6720     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6721     if (image == (Image *) NULL)
6722       {
6723         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6724           PackageName);
6725         goto PerlException;
6726       }
6727     map="RGB";
6728     if (image->alpha_trait != UndefinedPixelTrait)
6729       map="RGBA";
6730     if (image->colorspace == CMYKColorspace)
6731       {
6732         map="CMYK";
6733         if (image->alpha_trait != UndefinedPixelTrait)
6734           map="CMYKA";
6735       }
6736     normalize=MagickFalse;
6737     region.x=0;
6738     region.y=0;
6739     region.width=image->columns;
6740     region.height=1;
6741     if (items == 1)
6742       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6743     for (i=2; i < items; i+=2)
6744     {
6745       attribute=(char *) SvPV(ST(i-1),na);
6746       switch (*attribute)
6747       {
6748         case 'g':
6749         case 'G':
6750         {
6751           if (LocaleCompare(attribute,"geometry") == 0)
6752             {
6753               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6754               break;
6755             }
6756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6757             attribute);
6758           break;
6759         }
6760         case 'H':
6761         case 'h':
6762         {
6763           if (LocaleCompare(attribute,"height") == 0)
6764             {
6765               region.height=SvIV(ST(i));
6766               break;
6767             }
6768           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6769             attribute);
6770           break;
6771         }
6772         case 'M':
6773         case 'm':
6774         {
6775           if (LocaleCompare(attribute,"map") == 0)
6776             {
6777               map=SvPV(ST(i),na);
6778               break;
6779             }
6780           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6781             attribute);
6782           break;
6783         }
6784         case 'N':
6785         case 'n':
6786         {
6787           if (LocaleCompare(attribute,"normalize") == 0)
6788             {
6789               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6790                 SvPV(ST(i),na));
6791               if (option < 0)
6792                 {
6793                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6794                     SvPV(ST(i),na));
6795                   break;
6796                 }
6797              normalize=option != 0 ? MagickTrue : MagickFalse;
6798              break;
6799             }
6800           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6801             attribute);
6802           break;
6803         }
6804         case 'W':
6805         case 'w':
6806         {
6807           if (LocaleCompare(attribute,"width") == 0)
6808             {
6809               region.width=SvIV(ST(i));
6810               break;
6811             }
6812           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6813             attribute);
6814           break;
6815         }
6816         case 'x':
6817         case 'X':
6818         {
6819           if (LocaleCompare(attribute,"x") == 0)
6820             {
6821               region.x=SvIV(ST(i));
6822               break;
6823             }
6824           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6825             attribute);
6826           break;
6827         }
6828         case 'y':
6829         case 'Y':
6830         {
6831           if (LocaleCompare(attribute,"y") == 0)
6832             {
6833               region.y=SvIV(ST(i));
6834               break;
6835             }
6836           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6837             attribute);
6838           break;
6839         }
6840         default:
6841         {
6842           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6843             attribute);
6844           break;
6845         }
6846       }
6847     }
6848     if (normalize != MagickFalse)
6849       {
6850         float
6851           *pixels;
6852
6853         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6854           region.height*sizeof(*pixels));
6855         if (pixels == (float *) NULL)
6856           {
6857             ThrowPerlException(exception,ResourceLimitError,
6858               "MemoryAllocationFailed",PackageName);
6859             goto PerlException;
6860           }
6861         status=ExportImagePixels(image,region.x,region.y,region.width,
6862           region.height,map,FloatPixel,pixels,exception);
6863         if (status == MagickFalse)
6864           PUSHs(&sv_undef);
6865         else
6866           {
6867             EXTEND(sp,strlen(map)*region.width*region.height);
6868             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6869               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6870           }
6871         pixels=(float *) RelinquishMagickMemory(pixels);
6872       }
6873     else
6874       {
6875         Quantum
6876           *pixels;
6877
6878         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6879           region.height*sizeof(*pixels));
6880         if (pixels == (Quantum *) NULL)
6881           {
6882             ThrowPerlException(exception,ResourceLimitError,
6883               "MemoryAllocationFailed",PackageName);
6884             goto PerlException;
6885           }
6886         status=ExportImagePixels(image,region.x,region.y,region.width,
6887           region.height,map,QuantumPixel,pixels,exception);
6888         if (status == MagickFalse)
6889           PUSHs(&sv_undef);
6890         else
6891           {
6892             EXTEND(sp,strlen(map)*region.width*region.height);
6893             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6894               PUSHs(sv_2mortal(newSViv(pixels[i])));
6895           }
6896         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6897       }
6898
6899   PerlException:
6900     InheritPerlException(exception,perl_exception);
6901     exception=DestroyExceptionInfo(exception);
6902     SvREFCNT_dec(perl_exception);
6903   }
6904 \f
6905 #
6906 ###############################################################################
6907 #                                                                             #
6908 #                                                                             #
6909 #                                                                             #
6910 #   I m a g e T o B l o b                                                     #
6911 #                                                                             #
6912 #                                                                             #
6913 #                                                                             #
6914 ###############################################################################
6915 #
6916 #
6917 void
6918 ImageToBlob(ref,...)
6919   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
6920   ALIAS:
6921     ImageToBlob  = 1
6922     imagetoblob  = 2
6923     toblob       = 3
6924     blob         = 4
6925   PPCODE:
6926   {
6927     char
6928       filename[MagickPathExtent];
6929
6930     ExceptionInfo
6931       *exception;
6932
6933     Image
6934       *image,
6935       *next;
6936
6937     register ssize_t
6938       i;
6939
6940     struct PackageInfo
6941       *info,
6942       *package_info;
6943
6944     size_t
6945       length;
6946
6947     ssize_t
6948       scene;
6949
6950     SV
6951       *perl_exception,
6952       *reference;
6953
6954     void
6955       *blob;
6956
6957     PERL_UNUSED_VAR(ref);
6958     PERL_UNUSED_VAR(ix);
6959     exception=AcquireExceptionInfo();
6960     perl_exception=newSVpv("",0);
6961     package_info=(struct PackageInfo *) NULL;
6962     if (sv_isobject(ST(0)) == 0)
6963       {
6964         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6965           PackageName);
6966         goto PerlException;
6967       }
6968     reference=SvRV(ST(0));
6969     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6970     if (image == (Image *) NULL)
6971       {
6972         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6973           PackageName);
6974         goto PerlException;
6975       }
6976     package_info=ClonePackageInfo(info,exception);
6977     for (i=2; i < items; i+=2)
6978       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6979     (void) CopyMagickString(filename,package_info->image_info->filename,
6980       MagickPathExtent);
6981     scene=0;
6982     for (next=image; next; next=next->next)
6983     {
6984       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6985       next->scene=scene++;
6986     }
6987     SetImageInfo(package_info->image_info,(unsigned int)
6988       GetImageListLength(image),exception);
6989     EXTEND(sp,(ssize_t) GetImageListLength(image));
6990     for ( ; image; image=image->next)
6991     {
6992       length=0;
6993       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6994       if (blob != (char *) NULL)
6995         {
6996           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6997           blob=(unsigned char *) RelinquishMagickMemory(blob);
6998         }
6999       if (package_info->image_info->adjoin)
7000         break;
7001     }
7002
7003   PerlException:
7004     if (package_info != (struct PackageInfo *) NULL)
7005       DestroyPackageInfo(package_info);
7006     InheritPerlException(exception,perl_exception);
7007     exception=DestroyExceptionInfo(exception);
7008     SvREFCNT_dec(perl_exception);  /* throw away all errors */
7009   }
7010 \f
7011 #
7012 ###############################################################################
7013 #                                                                             #
7014 #                                                                             #
7015 #                                                                             #
7016 #   L a y e r s                                                               #
7017 #                                                                             #
7018 #                                                                             #
7019 #                                                                             #
7020 ###############################################################################
7021 #
7022 #
7023 void
7024 Layers(ref,...)
7025   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7026   ALIAS:
7027     Layers                = 1
7028     layers           = 2
7029     OptimizeImageLayers   = 3
7030     optimizelayers        = 4
7031     optimizeimagelayers   = 5
7032   PPCODE:
7033   {
7034     AV
7035       *av;
7036
7037     char
7038       *attribute;
7039
7040     CompositeOperator
7041       compose;
7042
7043     ExceptionInfo
7044       *exception;
7045
7046     HV
7047       *hv;
7048
7049     Image
7050       *image,
7051       *layers;
7052
7053     LayerMethod
7054       method;
7055
7056     register ssize_t
7057       i;
7058
7059     ssize_t
7060       option,
7061       sp;
7062
7063     struct PackageInfo
7064       *info;
7065
7066     SV
7067       *av_reference,
7068       *perl_exception,
7069       *reference,
7070       *rv,
7071       *sv;
7072
7073     PERL_UNUSED_VAR(ref);
7074     PERL_UNUSED_VAR(ix);
7075     exception=AcquireExceptionInfo();
7076     perl_exception=newSVpv("",0);
7077     sv=NULL;
7078     if (sv_isobject(ST(0)) == 0)
7079       {
7080         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7081           PackageName);
7082         goto PerlException;
7083       }
7084     reference=SvRV(ST(0));
7085     hv=SvSTASH(reference);
7086     av=newAV();
7087     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7088     SvREFCNT_dec(av);
7089     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7090     if (image == (Image *) NULL)
7091       {
7092         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7093           PackageName);
7094         goto PerlException;
7095       }
7096     compose=image->compose;
7097     method=OptimizeLayer;
7098     for (i=2; i < items; i+=2)
7099     {
7100       attribute=(char *) SvPV(ST(i-1),na);
7101       switch (*attribute)
7102       {
7103         case 'C':
7104         case 'c':
7105         {
7106           if (LocaleCompare(attribute,"compose") == 0)
7107             {
7108               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7109                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7110               if (sp < 0)
7111                 {
7112                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7113                     SvPV(ST(i),na));
7114                   break;
7115                 }
7116               compose=(CompositeOperator) sp;
7117               break;
7118             }
7119           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7120             attribute);
7121           break;
7122         }
7123         case 'M':
7124         case 'm':
7125         {
7126           if (LocaleCompare(attribute,"method") == 0)
7127             {
7128               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7129                 SvPV(ST(i),na));
7130               if (option < 0)
7131                 {
7132                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7133                     SvPV(ST(i),na));
7134                   break;
7135                 }
7136               method=(LayerMethod) option;
7137               break;
7138             }
7139           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7140             attribute);
7141           break;
7142         }
7143         default:
7144         {
7145           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7146             attribute);
7147           break;
7148         }
7149       }
7150     }
7151     layers=(Image *) NULL;
7152     switch (method)
7153     {
7154       case CompareAnyLayer:
7155       case CompareClearLayer:
7156       case CompareOverlayLayer:
7157       default:
7158       {
7159         layers=CompareImagesLayers(image,method,exception);
7160         break;
7161       }
7162       case MergeLayer:
7163       case FlattenLayer:
7164       case MosaicLayer:
7165       {
7166         layers=MergeImageLayers(image,method,exception);
7167         break;
7168       }
7169       case DisposeLayer:
7170       {
7171         layers=DisposeImages(image,exception);
7172         break;
7173       }
7174       case OptimizeImageLayer:
7175       {
7176         layers=OptimizeImageLayers(image,exception);
7177         break;
7178       }
7179       case OptimizePlusLayer:
7180       {
7181         layers=OptimizePlusImageLayers(image,exception);
7182         break;
7183       }
7184       case OptimizeTransLayer:
7185       {
7186         OptimizeImageTransparency(image,exception);
7187         break;
7188       }
7189       case RemoveDupsLayer:
7190       {
7191         RemoveDuplicateLayers(&image,exception);
7192         break;
7193       }
7194       case RemoveZeroLayer:
7195       {
7196         RemoveZeroDelayLayers(&image,exception);
7197         break;
7198       }
7199       case OptimizeLayer:
7200       {
7201         QuantizeInfo
7202           *quantize_info;
7203
7204         /*
7205           General Purpose, GIF Animation Optimizer.
7206         */
7207         layers=CoalesceImages(image,exception);
7208         if (layers == (Image *) NULL)
7209           break;
7210         image=layers;
7211         layers=OptimizeImageLayers(image,exception);
7212         if (layers == (Image *) NULL)
7213           break;
7214         image=DestroyImageList(image);
7215         image=layers;
7216         layers=(Image *) NULL;
7217         OptimizeImageTransparency(image,exception);
7218         quantize_info=AcquireQuantizeInfo(info->image_info);
7219         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7220         quantize_info=DestroyQuantizeInfo(quantize_info);
7221         break;
7222       }
7223       case CompositeLayer:
7224       {
7225         Image
7226           *source;
7227
7228         RectangleInfo
7229           geometry;
7230
7231         /*
7232           Split image sequence at the first 'NULL:' image.
7233         */
7234         source=image;
7235         while (source != (Image *) NULL)
7236         {
7237           source=GetNextImageInList(source);
7238           if ((source != (Image *) NULL) &&
7239               (LocaleCompare(source->magick,"NULL") == 0))
7240             break;
7241         }
7242         if (source != (Image *) NULL)
7243           {
7244             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7245                 (GetNextImageInList(source) == (Image *) NULL))
7246               source=(Image *) NULL;
7247             else
7248               {
7249                 /*
7250                   Separate the two lists, junk the null: image.
7251                 */
7252                 source=SplitImageList(source->previous);
7253                 DeleteImageFromList(&source);
7254               }
7255           }
7256         if (source == (Image *) NULL)
7257           {
7258             (void) ThrowMagickException(exception,GetMagickModule(),
7259               OptionError,"MissingNullSeparator","layers Composite");
7260             break;
7261           }
7262         /*
7263           Adjust offset with gravity and virtual canvas.
7264         */
7265         SetGeometry(image,&geometry);
7266         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7267         geometry.width=source->page.width != 0 ? source->page.width :
7268           source->columns;
7269         geometry.height=source->page.height != 0 ? source->page.height :
7270           source->rows;
7271         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7272           image->columns,image->page.height != 0 ? image->page.height :
7273           image->rows,image->gravity,&geometry);
7274         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7275         source=DestroyImageList(source);
7276         break;
7277       }
7278     }
7279     if (layers != (Image *) NULL)
7280       image=layers;
7281     else
7282       image=CloneImage(image,0,0,MagickTrue,exception);
7283     if (image == (Image *) NULL)
7284       goto PerlException;
7285     for ( ; image; image=image->next)
7286     {
7287       AddImageToRegistry(sv,image);
7288       rv=newRV(sv);
7289       av_push(av,sv_bless(rv,hv));
7290       SvREFCNT_dec(sv);
7291     }
7292     exception=DestroyExceptionInfo(exception);
7293     ST(0)=av_reference;
7294     SvREFCNT_dec(perl_exception);
7295     XSRETURN(1);
7296
7297   PerlException:
7298     InheritPerlException(exception,perl_exception);
7299     exception=DestroyExceptionInfo(exception);
7300     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7301     SvPOK_on(perl_exception);
7302     ST(0)=sv_2mortal(perl_exception);
7303     XSRETURN(1);
7304   }
7305 \f
7306 #
7307 ###############################################################################
7308 #                                                                             #
7309 #                                                                             #
7310 #                                                                             #
7311 #   M a g i c k T o M i m e                                                   #
7312 #                                                                             #
7313 #                                                                             #
7314 #                                                                             #
7315 ###############################################################################
7316 #
7317 #
7318 SV *
7319 MagickToMime(ref,name)
7320   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7321   char *name
7322   ALIAS:
7323     magicktomime = 1
7324   CODE:
7325   {
7326     char
7327       *mime;
7328
7329     PERL_UNUSED_VAR(ref);
7330     PERL_UNUSED_VAR(ix);
7331     mime=MagickToMime(name);
7332     RETVAL=newSVpv(mime,0);
7333     mime=(char *) RelinquishMagickMemory(mime);
7334   }
7335   OUTPUT:
7336     RETVAL
7337 \f
7338 #
7339 ###############################################################################
7340 #                                                                             #
7341 #                                                                             #
7342 #                                                                             #
7343 #   M o g r i f y                                                             #
7344 #                                                                             #
7345 #                                                                             #
7346 #                                                                             #
7347 ###############################################################################
7348 #
7349 #
7350 void
7351 Mogrify(ref,...)
7352   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
7353   ALIAS:
7354     Comment            =   1
7355     CommentImage       =   2
7356     Label              =   3
7357     LabelImage         =   4
7358     AddNoise           =   5
7359     AddNoiseImage      =   6
7360     Colorize           =   7
7361     ColorizeImage      =   8
7362     Border             =   9
7363     BorderImage        =  10
7364     Blur               =  11
7365     BlurImage          =  12
7366     Chop               =  13
7367     ChopImage          =  14
7368     Crop               =  15
7369     CropImage          =  16
7370     Despeckle          =  17
7371     DespeckleImage     =  18
7372     Edge               =  19
7373     EdgeImage          =  20
7374     Emboss             =  21
7375     EmbossImage        =  22
7376     Enhance            =  23
7377     EnhanceImage       =  24
7378     Flip               =  25
7379     FlipImage          =  26
7380     Flop               =  27
7381     FlopImage          =  28
7382     Frame              =  29
7383     FrameImage         =  30
7384     Implode            =  31
7385     ImplodeImage       =  32
7386     Magnify            =  33
7387     MagnifyImage       =  34
7388     MedianFilter       =  35
7389     MedianConvolveImage  =  36
7390     Minify             =  37
7391     MinifyImage        =  38
7392     OilPaint           =  39
7393     OilPaintImage      =  40
7394     ReduceNoise        =  41
7395     ReduceNoiseImage   =  42
7396     Roll               =  43
7397     RollImage          =  44
7398     Rotate             =  45
7399     RotateImage        =  46
7400     Sample             =  47
7401     SampleImage        =  48
7402     Scale              =  49
7403     ScaleImage         =  50
7404     Shade              =  51
7405     ShadeImage         =  52
7406     Sharpen            =  53
7407     SharpenImage       =  54
7408     Shear              =  55
7409     ShearImage         =  56
7410     Spread             =  57
7411     SpreadImage        =  58
7412     Swirl              =  59
7413     SwirlImage         =  60
7414     Resize             =  61
7415     ResizeImage        =  62
7416     Zoom               =  63
7417     ZoomImage          =  64
7418     Annotate           =  65
7419     AnnotateImage      =  66
7420     ColorFloodfill     =  67
7421     ColorFloodfillImage=  68
7422     Composite          =  69
7423     CompositeImage     =  70
7424     Contrast           =  71
7425     ContrastImage      =  72
7426     CycleColormap      =  73
7427     CycleColormapImage =  74
7428     Draw               =  75
7429     DrawImage          =  76
7430     Equalize           =  77
7431     EqualizeImage      =  78
7432     Gamma              =  79
7433     GammaImage         =  80
7434     Map                =  81
7435     MapImage           =  82
7436     MatteFloodfill     =  83
7437     MatteFloodfillImage=  84
7438     Modulate           =  85
7439     ModulateImage      =  86
7440     Negate             =  87
7441     NegateImage        =  88
7442     Normalize          =  89
7443     NormalizeImage     =  90
7444     NumberColors       =  91
7445     NumberColorsImage  =  92
7446     Opaque             =  93
7447     OpaqueImage        =  94
7448     Quantize           =  95
7449     QuantizeImage      =  96
7450     Raise              =  97
7451     RaiseImage         =  98
7452     Segment            =  99
7453     SegmentImage       = 100
7454     Signature          = 101
7455     SignatureImage     = 102
7456     Solarize           = 103
7457     SolarizeImage      = 104
7458     Sync               = 105
7459     SyncImage          = 106
7460     Texture            = 107
7461     TextureImage       = 108
7462     Evaluate           = 109
7463     EvaluateImage      = 110
7464     Transparent        = 111
7465     TransparentImage   = 112
7466     Threshold          = 113
7467     ThresholdImage     = 114
7468     Charcoal           = 115
7469     CharcoalImage      = 116
7470     Trim               = 117
7471     TrimImage          = 118
7472     Wave               = 119
7473     WaveImage          = 120
7474     Separate           = 121
7475     SeparateImage      = 122
7476     Stereo             = 125
7477     StereoImage        = 126
7478     Stegano            = 127
7479     SteganoImage       = 128
7480     Deconstruct        = 129
7481     DeconstructImage   = 130
7482     GaussianBlur       = 131
7483     GaussianBlurImage  = 132
7484     Convolve           = 133
7485     ConvolveImage      = 134
7486     Profile            = 135
7487     ProfileImage       = 136
7488     UnsharpMask        = 137
7489     UnsharpMaskImage   = 138
7490     MotionBlur         = 139
7491     MotionBlurImage    = 140
7492     OrderedDither      = 141
7493     OrderedDitherImage = 142
7494     Shave              = 143
7495     ShaveImage         = 144
7496     Level              = 145
7497     LevelImage         = 146
7498     Clip               = 147
7499     ClipImage          = 148
7500     AffineTransform    = 149
7501     AffineTransformImage = 150
7502     Difference         = 151
7503     DifferenceImage    = 152
7504     AdaptiveThreshold  = 153
7505     AdaptiveThresholdImage = 154
7506     Resample           = 155
7507     ResampleImage      = 156
7508     Describe           = 157
7509     DescribeImage      = 158
7510     BlackThreshold     = 159
7511     BlackThresholdImage= 160
7512     WhiteThreshold     = 161
7513     WhiteThresholdImage= 162
7514     RotationalBlur     = 163
7515     RotationalBlurImage= 164
7516     Thumbnail          = 165
7517     ThumbnailImage     = 166
7518     Strip              = 167
7519     StripImage         = 168
7520     Tint               = 169
7521     TintImage          = 170
7522     Channel            = 171
7523     ChannelImage       = 172
7524     Splice             = 173
7525     SpliceImage        = 174
7526     Posterize          = 175
7527     PosterizeImage     = 176
7528     Shadow             = 177
7529     ShadowImage        = 178
7530     Identify           = 179
7531     IdentifyImage      = 180
7532     SepiaTone          = 181
7533     SepiaToneImage     = 182
7534     SigmoidalContrast  = 183
7535     SigmoidalContrastImage = 184
7536     Extent             = 185
7537     ExtentImage        = 186
7538     Vignette           = 187
7539     VignetteImage      = 188
7540     ContrastStretch    = 189
7541     ContrastStretchImage = 190
7542     Sans0              = 191
7543     Sans0Image         = 192
7544     Sans1              = 193
7545     Sans1Image         = 194
7546     AdaptiveSharpen    = 195
7547     AdaptiveSharpenImage = 196
7548     Transpose          = 197
7549     TransposeImage     = 198
7550     Transverse         = 199
7551     TransverseImage    = 200
7552     AutoOrient         = 201
7553     AutoOrientImage    = 202
7554     AdaptiveBlur       = 203
7555     AdaptiveBlurImage  = 204
7556     Sketch             = 205
7557     SketchImage        = 206
7558     UniqueColors       = 207
7559     UniqueColorsImage  = 208
7560     AdaptiveResize     = 209
7561     AdaptiveResizeImage= 210
7562     ClipMask           = 211
7563     ClipMaskImage      = 212
7564     LinearStretch      = 213
7565     LinearStretchImage = 214
7566     ColorMatrix        = 215
7567     ColorMatrixImage   = 216
7568     Mask               = 217
7569     MaskImage          = 218
7570     Polaroid           = 219
7571     PolaroidImage      = 220
7572     FloodfillPaint     = 221
7573     FloodfillPaintImage= 222
7574     Distort            = 223
7575     DistortImage       = 224
7576     Clut               = 225
7577     ClutImage          = 226
7578     LiquidRescale      = 227
7579     LiquidRescaleImage = 228
7580     Encipher           = 229
7581     EncipherImage      = 230
7582     Decipher           = 231
7583     DecipherImage      = 232
7584     Deskew             = 233
7585     DeskewImage        = 234
7586     Remap              = 235
7587     RemapImage         = 236
7588     SparseColor        = 237
7589     SparseColorImage   = 238
7590     Function           = 239
7591     FunctionImage      = 240
7592     SelectiveBlur      = 241
7593     SelectiveBlurImage = 242
7594     HaldClut           = 243
7595     HaldClutImage      = 244
7596     BlueShift          = 245
7597     BlueShiftImage     = 246
7598     ForwardFourierTransform  = 247
7599     ForwardFourierTransformImage = 248
7600     InverseFourierTransform = 249
7601     InverseFourierTransformImage = 250
7602     ColorDecisionList  = 251
7603     ColorDecisionListImage = 252
7604     AutoGamma          = 253
7605     AutoGammaImage     = 254
7606     AutoLevel          = 255
7607     AutoLevelImage     = 256
7608     LevelColors        = 257
7609     LevelImageColors   = 258
7610     Clamp              = 259
7611     ClampImage         = 260
7612     BrightnessContrast = 261
7613     BrightnessContrastImage = 262
7614     Morphology         = 263
7615     MorphologyImage    = 264
7616     Mode               = 265
7617     ModeImage          = 266
7618     Statistic          = 267
7619     StatisticImage     = 268
7620     Perceptible        = 269
7621     PerceptibleImage   = 270
7622     Poly               = 271
7623     PolyImage          = 272
7624     Grayscale          = 273
7625     GrayscaleImage     = 274
7626     CannyEdge          = 275
7627     CannyEdgeImage     = 276
7628     HoughLine          = 277
7629     HoughLineImage     = 278
7630     MeanShift          = 279
7631     MeanShiftImage     = 280
7632     Kuwahara           = 281
7633     KuwaharaImage      = 282
7634     ConnectedComponents = 283
7635     ConnectedComponentsImage = 284
7636     CopyPixels         = 285
7637     CopyImagePixels    = 286
7638     Color              = 287
7639     ColorImage         = 288
7640     WaveletDenoise     = 289
7641     WaveletDenoiseImage= 290
7642     Colorspace         = 291
7643     ColorspaceImage    = 292
7644     AutoThreshold      = 293
7645     AutoThresholdImage = 294
7646     RangeThreshold     = 295
7647     RangeThresholdImage= 296
7648     CLAHE              = 297
7649     CLAHEImage         = 298
7650     OTSUThreshold      = 299
7651     OTSUThresholdImage = 300
7652     MogrifyRegion      = 666
7653   PPCODE:
7654   {
7655     AffineMatrix
7656       affine,
7657       current;
7658
7659     char
7660       attribute_flag[MaxArguments],
7661       message[MagickPathExtent];
7662
7663     ChannelType
7664       channel,
7665       channel_mask;
7666
7667     CompositeOperator
7668       compose;
7669
7670     const char
7671       *attribute,
7672       *value;
7673
7674     double
7675       angle;
7676
7677     ExceptionInfo
7678       *exception;
7679
7680     GeometryInfo
7681       geometry_info;
7682
7683     Image
7684       *image,
7685       *next;
7686
7687     MagickStatusType
7688       flags;
7689
7690     PixelInfo
7691       fill_color;
7692
7693     RectangleInfo
7694       geometry,
7695       region_info;
7696
7697     register ssize_t
7698       i;
7699
7700     ssize_t
7701       base,
7702       j,
7703       number_images;
7704
7705     struct Methods
7706       *rp;
7707
7708     struct PackageInfo
7709       *info;
7710
7711     SV
7712       *perl_exception,
7713       **pv,
7714       *reference,
7715       **reference_vector;
7716
7717     struct ArgumentList
7718       argument_list[MaxArguments];
7719
7720     PERL_UNUSED_VAR(ref);
7721     PERL_UNUSED_VAR(ix);
7722     exception=AcquireExceptionInfo();
7723     perl_exception=newSVpv("",0);
7724     reference_vector=NULL;
7725     number_images=0;
7726     base=2;
7727     if (sv_isobject(ST(0)) == 0)
7728       {
7729         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7730           PackageName);
7731         goto PerlException;
7732       }
7733     reference=SvRV(ST(0));
7734     region_info.width=0;
7735     region_info.height=0;
7736     region_info.x=0;
7737     region_info.y=0;
7738     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7739     if (ix && (ix != 666))
7740       {
7741         /*
7742           Called as Method(...)
7743         */
7744         ix=(ix+1)/2;
7745         rp=(&Methods[ix-1]);
7746         attribute=rp->name;
7747       }
7748     else
7749       {
7750         /*
7751           Called as Mogrify("Method",...)
7752         */
7753         attribute=(char *) SvPV(ST(1),na);
7754         if (ix)
7755           {
7756             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7757             attribute=(char *) SvPV(ST(2),na);
7758             base++;
7759           }
7760         for (rp=Methods; ; rp++)
7761         {
7762           if (rp >= EndOf(Methods))
7763             {
7764               ThrowPerlException(exception,OptionError,
7765                 "UnrecognizedPerlMagickMethod",attribute);
7766               goto PerlException;
7767             }
7768           if (strEQcase(attribute,rp->name))
7769             break;
7770         }
7771         ix=rp-Methods+1;
7772         base++;
7773       }
7774     if (image == (Image *) NULL)
7775       {
7776         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7777         goto PerlException;
7778       }
7779     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7780     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7781     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7782     {
7783       Arguments
7784         *pp,
7785         *qq;
7786
7787       ssize_t
7788         ssize_test;
7789
7790       struct ArgumentList
7791         *al;
7792
7793       SV
7794         *sv;
7795
7796       sv=NULL;
7797       ssize_test=0;
7798       pp=(Arguments *) NULL;
7799       qq=rp->arguments;
7800       if (i == items)
7801         {
7802           pp=rp->arguments,
7803           sv=ST(i-1);
7804         }
7805       else
7806         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7807         {
7808           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7809             break;
7810           if (strEQcase(attribute,qq->method) > ssize_test)
7811             {
7812               pp=qq;
7813               ssize_test=strEQcase(attribute,qq->method);
7814             }
7815         }
7816       if (pp == (Arguments *) NULL)
7817         {
7818           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7819             attribute);
7820           goto continue_outer_loop;
7821         }
7822       al=(&argument_list[pp-rp->arguments]);
7823       switch (pp->type)
7824       {
7825         case ArrayReference:
7826         {
7827           if (SvTYPE(sv) != SVt_RV)
7828             {
7829               (void) FormatLocaleString(message,MagickPathExtent,
7830                 "invalid %.60s value",pp->method);
7831               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7832               goto continue_outer_loop;
7833             }
7834           al->array_reference=SvRV(sv);
7835           break;
7836         }
7837         case RealReference:
7838         {
7839           al->real_reference=SvNV(sv);
7840           break;
7841         }
7842         case FileReference:
7843         {
7844           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7845           break;
7846         }
7847         case ImageReference:
7848         {
7849           if (!sv_isobject(sv) ||
7850               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7851                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7852             {
7853               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7854                 PackageName);
7855               goto PerlException;
7856             }
7857           break;
7858         }
7859         case IntegerReference:
7860         {
7861           al->integer_reference=SvIV(sv);
7862           break;
7863         }
7864         case StringReference:
7865         {
7866           al->string_reference=(char *) SvPV(sv,al->length);
7867           if (sv_isobject(sv))
7868             al->image_reference=SetupList(aTHX_ SvRV(sv),
7869               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7870           break;
7871         }
7872         default:
7873         {
7874           /*
7875             Is a string; look up name.
7876           */
7877           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7878             {
7879               al->string_reference=(char *) SvPV(sv,al->length);
7880               al->integer_reference=(-1);
7881               break;
7882             }
7883           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7884             MagickFalse,SvPV(sv,na));
7885           if (pp->type == MagickChannelOptions)
7886             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7887           if ((al->integer_reference < 0) &&
7888               ((al->integer_reference=SvIV(sv)) <= 0))
7889             {
7890               (void) FormatLocaleString(message,MagickPathExtent,
7891                 "invalid %.60s value",pp->method);
7892               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7893               goto continue_outer_loop;
7894             }
7895           break;
7896         }
7897       }
7898       attribute_flag[pp-rp->arguments]++;
7899       continue_outer_loop: ;
7900     }
7901     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7902     pv=reference_vector;
7903     SetGeometryInfo(&geometry_info);
7904     channel=DefaultChannels;
7905     for (next=image; next; next=next->next)
7906     {
7907       image=next;
7908       SetGeometry(image,&geometry);
7909       if ((region_info.width*region_info.height) != 0)
7910         (void) SetImageRegionMask(image,WritePixelMask,&region_info,exception);
7911       switch (ix)
7912       {
7913         default:
7914         {
7915           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
7916             ix);
7917           ThrowPerlException(exception,OptionError,
7918             "UnrecognizedPerlMagickMethod",message);
7919           goto PerlException;
7920         }
7921         case 1:  /* Comment */
7922         {
7923           if (attribute_flag[0] == 0)
7924             argument_list[0].string_reference=(char *) NULL;
7925           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7926             info ? info->image_info : (ImageInfo *) NULL,image,
7927             argument_list[0].string_reference,exception),exception);
7928           break;
7929         }
7930         case 2:  /* Label */
7931         {
7932           if (attribute_flag[0] == 0)
7933             argument_list[0].string_reference=(char *) NULL;
7934           (void) SetImageProperty(image,"label",InterpretImageProperties(
7935             info ? info->image_info : (ImageInfo *) NULL,image,
7936             argument_list[0].string_reference,exception),exception);
7937           break;
7938         }
7939         case 3:  /* AddNoise */
7940         {
7941           double
7942             attenuate;
7943
7944           if (attribute_flag[0] == 0)
7945             argument_list[0].integer_reference=UniformNoise;
7946           attenuate=1.0;
7947           if (attribute_flag[1] != 0)
7948             attenuate=argument_list[1].real_reference;
7949           if (attribute_flag[2] != 0)
7950             channel=(ChannelType) argument_list[2].integer_reference;
7951           channel_mask=SetImageChannelMask(image,channel);
7952           image=AddNoiseImage(image,(NoiseType)
7953             argument_list[0].integer_reference,attenuate,exception);
7954           if (image != (Image *) NULL)
7955             (void) SetImageChannelMask(image,channel_mask);
7956           break;
7957         }
7958         case 4:  /* Colorize */
7959         {
7960           PixelInfo
7961             target;
7962
7963           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,0,0,
7964             &target,exception);
7965           if (attribute_flag[0] != 0)
7966             (void) QueryColorCompliance(argument_list[0].string_reference,
7967               AllCompliance,&target,exception);
7968           if (attribute_flag[1] == 0)
7969             argument_list[1].string_reference="100%";
7970           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7971             exception);
7972           break;
7973         }
7974         case 5:  /* Border */
7975         {
7976           CompositeOperator
7977             compose;
7978
7979           geometry.width=0;
7980           geometry.height=0;
7981           if (attribute_flag[0] != 0)
7982             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7983               &geometry,exception);
7984           if (attribute_flag[1] != 0)
7985             geometry.width=argument_list[1].integer_reference;
7986           if (attribute_flag[2] != 0)
7987             geometry.height=argument_list[2].integer_reference;
7988           if (attribute_flag[3] != 0)
7989             QueryColorCompliance(argument_list[3].string_reference,
7990               AllCompliance,&image->border_color,exception);
7991           if (attribute_flag[4] != 0)
7992             QueryColorCompliance(argument_list[4].string_reference,
7993               AllCompliance,&image->border_color,exception);
7994           if (attribute_flag[5] != 0)
7995             QueryColorCompliance(argument_list[5].string_reference,
7996               AllCompliance,&image->border_color,exception);
7997           compose=image->compose;
7998           if (attribute_flag[6] != 0)
7999             compose=(CompositeOperator) argument_list[6].integer_reference;
8000           image=BorderImage(image,&geometry,compose,exception);
8001           break;
8002         }
8003         case 6:  /* Blur */
8004         {
8005           if (attribute_flag[0] != 0)
8006             {
8007               flags=ParseGeometry(argument_list[0].string_reference,
8008                 &geometry_info);
8009               if ((flags & SigmaValue) == 0)
8010                 geometry_info.sigma=1.0;
8011             }
8012           if (attribute_flag[1] != 0)
8013             geometry_info.rho=argument_list[1].real_reference;
8014           if (attribute_flag[2] != 0)
8015             geometry_info.sigma=argument_list[2].real_reference;
8016           if (attribute_flag[3] != 0)
8017             channel=(ChannelType) argument_list[3].integer_reference;
8018           channel_mask=SetImageChannelMask(image,channel);
8019           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
8020             exception);
8021           if (image != (Image *) NULL)
8022             (void) SetImageChannelMask(image,channel_mask);
8023           break;
8024         }
8025         case 7:  /* Chop */
8026         {
8027           if (attribute_flag[5] != 0)
8028             image->gravity=(GravityType) argument_list[5].integer_reference;
8029           if (attribute_flag[0] != 0)
8030             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8031               &geometry,exception);
8032           if (attribute_flag[1] != 0)
8033             geometry.width=argument_list[1].integer_reference;
8034           if (attribute_flag[2] != 0)
8035             geometry.height=argument_list[2].integer_reference;
8036           if (attribute_flag[3] != 0)
8037             geometry.x=argument_list[3].integer_reference;
8038           if (attribute_flag[4] != 0)
8039             geometry.y=argument_list[4].integer_reference;
8040           image=ChopImage(image,&geometry,exception);
8041           break;
8042         }
8043         case 8:  /* Crop */
8044         {
8045           if (attribute_flag[6] != 0)
8046             image->gravity=(GravityType) argument_list[6].integer_reference;
8047           if (attribute_flag[0] != 0)
8048             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
8049               &geometry,exception);
8050           if (attribute_flag[1] != 0)
8051             geometry.width=argument_list[1].integer_reference;
8052           if (attribute_flag[2] != 0)
8053             geometry.height=argument_list[2].integer_reference;
8054           if (attribute_flag[3] != 0)
8055             geometry.x=argument_list[3].integer_reference;
8056           if (attribute_flag[4] != 0)
8057             geometry.y=argument_list[4].integer_reference;
8058           if (attribute_flag[5] != 0)
8059             image->fuzz=StringToDoubleInterval(
8060               argument_list[5].string_reference,(double) QuantumRange+1.0);
8061           image=CropImage(image,&geometry,exception);
8062           break;
8063         }
8064         case 9:  /* Despeckle */
8065         {
8066           image=DespeckleImage(image,exception);
8067           break;
8068         }
8069         case 10:  /* Edge */
8070         {
8071           if (attribute_flag[0] != 0)
8072             geometry_info.rho=argument_list[0].real_reference;
8073           image=EdgeImage(image,geometry_info.rho,exception);
8074           break;
8075         }
8076         case 11:  /* Emboss */
8077         {
8078           if (attribute_flag[0] != 0)
8079             {
8080               flags=ParseGeometry(argument_list[0].string_reference,
8081                 &geometry_info);
8082               if ((flags & SigmaValue) == 0)
8083                 geometry_info.sigma=1.0;
8084             }
8085           if (attribute_flag[1] != 0)
8086             geometry_info.rho=argument_list[1].real_reference;
8087           if (attribute_flag[2] != 0)
8088             geometry_info.sigma=argument_list[2].real_reference;
8089           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8090             exception);
8091           break;
8092         }
8093         case 12:  /* Enhance */
8094         {
8095           image=EnhanceImage(image,exception);
8096           break;
8097         }
8098         case 13:  /* Flip */
8099         {
8100           image=FlipImage(image,exception);
8101           break;
8102         }
8103         case 14:  /* Flop */
8104         {
8105           image=FlopImage(image,exception);
8106           break;
8107         }
8108         case 15:  /* Frame */
8109         {
8110           CompositeOperator
8111             compose;
8112
8113           FrameInfo
8114             frame_info;
8115
8116           if (attribute_flag[0] != 0)
8117             {
8118               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8119                 &geometry,exception);
8120               frame_info.width=geometry.width;
8121               frame_info.height=geometry.height;
8122               frame_info.outer_bevel=geometry.x;
8123               frame_info.inner_bevel=geometry.y;
8124             }
8125           if (attribute_flag[1] != 0)
8126             frame_info.width=argument_list[1].integer_reference;
8127           if (attribute_flag[2] != 0)
8128             frame_info.height=argument_list[2].integer_reference;
8129           if (attribute_flag[3] != 0)
8130             frame_info.inner_bevel=argument_list[3].integer_reference;
8131           if (attribute_flag[4] != 0)
8132             frame_info.outer_bevel=argument_list[4].integer_reference;
8133           if (attribute_flag[5] != 0)
8134             QueryColorCompliance(argument_list[5].string_reference,
8135               AllCompliance,&fill_color,exception);
8136           if (attribute_flag[6] != 0)
8137             QueryColorCompliance(argument_list[6].string_reference,
8138               AllCompliance,&fill_color,exception);
8139           frame_info.x=(ssize_t) frame_info.width;
8140           frame_info.y=(ssize_t) frame_info.height;
8141           frame_info.width=image->columns+2*frame_info.x;
8142           frame_info.height=image->rows+2*frame_info.y;
8143           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8144             image->alpha_color=fill_color;
8145           compose=image->compose;
8146           if (attribute_flag[7] != 0)
8147             compose=(CompositeOperator) argument_list[7].integer_reference;
8148           image=FrameImage(image,&frame_info,compose,exception);
8149           break;
8150         }
8151         case 16:  /* Implode */
8152         {
8153           PixelInterpolateMethod
8154             method;
8155
8156           if (attribute_flag[0] == 0)
8157             argument_list[0].real_reference=0.5;
8158           method=UndefinedInterpolatePixel;
8159           if (attribute_flag[1] != 0)
8160             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8161           image=ImplodeImage(image,argument_list[0].real_reference,
8162             method,exception);
8163           break;
8164         }
8165         case 17:  /* Magnify */
8166         {
8167           image=MagnifyImage(image,exception);
8168           break;
8169         }
8170         case 18:  /* MedianFilter */
8171         {
8172           if (attribute_flag[0] != 0)
8173             {
8174               flags=ParseGeometry(argument_list[0].string_reference,
8175                 &geometry_info);
8176               if ((flags & SigmaValue) == 0)
8177                 geometry_info.sigma=geometry_info.rho;
8178             }
8179           if (attribute_flag[1] != 0)
8180             geometry_info.rho=argument_list[1].real_reference;
8181           if (attribute_flag[2] != 0)
8182             geometry_info.sigma=argument_list[2].real_reference;
8183           if (attribute_flag[3] != 0)
8184             channel=(ChannelType) argument_list[3].integer_reference;
8185           channel_mask=SetImageChannelMask(image,channel);
8186           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8187             (size_t) geometry_info.sigma,exception);
8188           if (image != (Image *) NULL)
8189             (void) SetImageChannelMask(image,channel_mask);
8190           break;
8191         }
8192         case 19:  /* Minify */
8193         {
8194           image=MinifyImage(image,exception);
8195           break;
8196         }
8197         case 20:  /* OilPaint */
8198         {
8199           if (attribute_flag[0] == 0)
8200             argument_list[0].real_reference=0.0;
8201           if (attribute_flag[1] == 0)
8202             argument_list[1].real_reference=1.0;
8203           image=OilPaintImage(image,argument_list[0].real_reference,
8204             argument_list[1].real_reference,exception);
8205           break;
8206         }
8207         case 21:  /* ReduceNoise */
8208         {
8209           if (attribute_flag[0] != 0)
8210             {
8211               flags=ParseGeometry(argument_list[0].string_reference,
8212                 &geometry_info);
8213               if ((flags & SigmaValue) == 0)
8214                 geometry_info.sigma=1.0;
8215             }
8216           if (attribute_flag[1] != 0)
8217             geometry_info.rho=argument_list[1].real_reference;
8218           if (attribute_flag[2] != 0)
8219             geometry_info.sigma=argument_list[2].real_reference;
8220           if (attribute_flag[3] != 0)
8221             channel=(ChannelType) argument_list[3].integer_reference;
8222           channel_mask=SetImageChannelMask(image,channel);
8223           image=StatisticImage(image,NonpeakStatistic,(size_t)
8224             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8225           if (image != (Image *) NULL)
8226             (void) SetImageChannelMask(image,channel_mask);
8227           break;
8228         }
8229         case 22:  /* Roll */
8230         {
8231           if (attribute_flag[0] != 0)
8232             {
8233               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8234                 &geometry,exception);
8235               if ((flags & PercentValue) != 0)
8236                 {
8237                   geometry.x*=(double) image->columns/100.0;
8238                   geometry.y*=(double) image->rows/100.0;
8239                 }
8240             }
8241           if (attribute_flag[1] != 0)
8242             geometry.x=argument_list[1].integer_reference;
8243           if (attribute_flag[2] != 0)
8244             geometry.y=argument_list[2].integer_reference;
8245           image=RollImage(image,geometry.x,geometry.y,exception);
8246           break;
8247         }
8248         case 23:  /* Rotate */
8249         {
8250           if (attribute_flag[0] == 0)
8251             argument_list[0].real_reference=90.0;
8252           if (attribute_flag[1] != 0)
8253             {
8254               QueryColorCompliance(argument_list[1].string_reference,
8255                 AllCompliance,&image->background_color,exception);
8256               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8257                   (image->alpha_trait == UndefinedPixelTrait))
8258                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8259             }
8260           image=RotateImage(image,argument_list[0].real_reference,exception);
8261           break;
8262         }
8263         case 24:  /* Sample */
8264         {
8265           if (attribute_flag[0] != 0)
8266             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8267               &geometry,exception);
8268           if (attribute_flag[1] != 0)
8269             geometry.width=argument_list[1].integer_reference;
8270           if (attribute_flag[2] != 0)
8271             geometry.height=argument_list[2].integer_reference;
8272           image=SampleImage(image,geometry.width,geometry.height,exception);
8273           break;
8274         }
8275         case 25:  /* Scale */
8276         {
8277           if (attribute_flag[0] != 0)
8278             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8279               &geometry,exception);
8280           if (attribute_flag[1] != 0)
8281             geometry.width=argument_list[1].integer_reference;
8282           if (attribute_flag[2] != 0)
8283             geometry.height=argument_list[2].integer_reference;
8284           image=ScaleImage(image,geometry.width,geometry.height,exception);
8285           break;
8286         }
8287         case 26:  /* Shade */
8288         {
8289           if (attribute_flag[0] != 0)
8290             {
8291               flags=ParseGeometry(argument_list[0].string_reference,
8292                 &geometry_info);
8293               if ((flags & SigmaValue) == 0)
8294                 geometry_info.sigma=0.0;
8295             }
8296           if (attribute_flag[1] != 0)
8297             geometry_info.rho=argument_list[1].real_reference;
8298           if (attribute_flag[2] != 0)
8299             geometry_info.sigma=argument_list[2].real_reference;
8300           image=ShadeImage(image,
8301             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8302             geometry_info.rho,geometry_info.sigma,exception);
8303           break;
8304         }
8305         case 27:  /* Sharpen */
8306         {
8307           if (attribute_flag[0] != 0)
8308             {
8309               flags=ParseGeometry(argument_list[0].string_reference,
8310                 &geometry_info);
8311               if ((flags & SigmaValue) == 0)
8312                 geometry_info.sigma=1.0;
8313             }
8314           if (attribute_flag[1] != 0)
8315             geometry_info.rho=argument_list[1].real_reference;
8316           if (attribute_flag[2] != 0)
8317             geometry_info.sigma=argument_list[2].real_reference;
8318           if (attribute_flag[3] != 0)
8319             channel=(ChannelType) argument_list[3].integer_reference;
8320           channel_mask=SetImageChannelMask(image,channel);
8321           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8322             exception);
8323           if (image != (Image *) NULL)
8324             (void) SetImageChannelMask(image,channel_mask);
8325           break;
8326         }
8327         case 28:  /* Shear */
8328         {
8329           if (attribute_flag[0] != 0)
8330             {
8331               flags=ParseGeometry(argument_list[0].string_reference,
8332                 &geometry_info);
8333               if ((flags & SigmaValue) == 0)
8334                 geometry_info.sigma=geometry_info.rho;
8335             }
8336           if (attribute_flag[1] != 0)
8337             geometry_info.rho=argument_list[1].real_reference;
8338           if (attribute_flag[2] != 0)
8339             geometry_info.sigma=argument_list[2].real_reference;
8340           if (attribute_flag[3] != 0)
8341             QueryColorCompliance(argument_list[3].string_reference,
8342               AllCompliance,&image->background_color,exception);
8343           if (attribute_flag[4] != 0)
8344             QueryColorCompliance(argument_list[4].string_reference,
8345               AllCompliance,&image->background_color,exception);
8346           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8347             exception);
8348           break;
8349         }
8350         case 29:  /* Spread */
8351         {
8352           PixelInterpolateMethod
8353             method;
8354
8355           if (attribute_flag[0] == 0)
8356             argument_list[0].real_reference=1.0;
8357           method=UndefinedInterpolatePixel;
8358           if (attribute_flag[1] != 0)
8359             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8360           image=SpreadImage(image,method,argument_list[0].real_reference,
8361             exception);
8362           break;
8363         }
8364         case 30:  /* Swirl */
8365         {
8366           PixelInterpolateMethod
8367             method;
8368
8369           if (attribute_flag[0] == 0)
8370             argument_list[0].real_reference=50.0;
8371           method=UndefinedInterpolatePixel;
8372           if (attribute_flag[1] != 0)
8373             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8374           image=SwirlImage(image,argument_list[0].real_reference,
8375             method,exception);
8376           break;
8377         }
8378         case 31:  /* Resize */
8379         case 32:  /* Zoom */
8380         {
8381           if (attribute_flag[0] != 0)
8382             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8383               &geometry,exception);
8384           if (attribute_flag[1] != 0)
8385             geometry.width=argument_list[1].integer_reference;
8386           if (attribute_flag[2] != 0)
8387             geometry.height=argument_list[2].integer_reference;
8388           if (attribute_flag[3] == 0)
8389             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8390           if (attribute_flag[4] != 0)
8391             SetImageArtifact(image,"filter:support",
8392               argument_list[4].string_reference);
8393           image=ResizeImage(image,geometry.width,geometry.height,
8394             (FilterType) argument_list[3].integer_reference,
8395             exception);
8396           break;
8397         }
8398         case 33:  /* Annotate */
8399         {
8400           DrawInfo
8401             *draw_info;
8402
8403           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8404             (DrawInfo *) NULL);
8405           if (attribute_flag[0] != 0)
8406             {
8407               char
8408                 *text;
8409
8410               text=InterpretImageProperties(info ? info->image_info :
8411                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8412                 exception);
8413               (void) CloneString(&draw_info->text,text);
8414               text=DestroyString(text);
8415             }
8416           if (attribute_flag[1] != 0)
8417             (void) CloneString(&draw_info->font,
8418               argument_list[1].string_reference);
8419           if (attribute_flag[2] != 0)
8420             draw_info->pointsize=argument_list[2].real_reference;
8421           if (attribute_flag[3] != 0)
8422             (void) CloneString(&draw_info->density,
8423               argument_list[3].string_reference);
8424           if (attribute_flag[4] != 0)
8425             (void) QueryColorCompliance(argument_list[4].string_reference,
8426               AllCompliance,&draw_info->undercolor,exception);
8427           if (attribute_flag[5] != 0)
8428             {
8429               (void) QueryColorCompliance(argument_list[5].string_reference,
8430                 AllCompliance,&draw_info->stroke,exception);
8431               if (argument_list[5].image_reference != (Image *) NULL)
8432                 draw_info->stroke_pattern=CloneImage(
8433                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8434             }
8435           if (attribute_flag[6] != 0)
8436             {
8437               (void) QueryColorCompliance(argument_list[6].string_reference,
8438                 AllCompliance,&draw_info->fill,exception);
8439               if (argument_list[6].image_reference != (Image *) NULL)
8440                 draw_info->fill_pattern=CloneImage(
8441                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8442             }
8443           if (attribute_flag[7] != 0)
8444             {
8445               (void) CloneString(&draw_info->geometry,
8446                 argument_list[7].string_reference);
8447               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8448                 &geometry,exception);
8449               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8450                 geometry_info.sigma=geometry_info.xi;
8451             }
8452           if (attribute_flag[8] != 0)
8453             (void) QueryColorCompliance(argument_list[8].string_reference,
8454               AllCompliance,&draw_info->fill,exception);
8455           if (attribute_flag[11] != 0)
8456             draw_info->gravity=(GravityType)
8457               argument_list[11].integer_reference;
8458           if (attribute_flag[25] != 0)
8459             {
8460               AV
8461                 *av;
8462
8463               av=(AV *) argument_list[25].array_reference;
8464               if ((av_len(av) != 3) && (av_len(av) != 5))
8465                 {
8466                   ThrowPerlException(exception,OptionError,
8467                     "affine matrix must have 4 or 6 elements",PackageName);
8468                   goto PerlException;
8469                 }
8470               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8471               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8472               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8473               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8474               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8475                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8476                 {
8477                   ThrowPerlException(exception,OptionError,
8478                     "affine matrix is singular",PackageName);
8479                    goto PerlException;
8480                 }
8481               if (av_len(av) == 5)
8482                 {
8483                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8484                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8485                 }
8486             }
8487           for (j=12; j < 17; j++)
8488           {
8489             if (attribute_flag[j] == 0)
8490               continue;
8491             value=argument_list[j].string_reference;
8492             angle=argument_list[j].real_reference;
8493             current=draw_info->affine;
8494             GetAffineMatrix(&affine);
8495             switch (j)
8496             {
8497               case 12:
8498               {
8499                 /*
8500                   Translate.
8501                 */
8502                 flags=ParseGeometry(value,&geometry_info);
8503                 affine.tx=geometry_info.xi;
8504                 affine.ty=geometry_info.psi;
8505                 if ((flags & PsiValue) == 0)
8506                   affine.ty=affine.tx;
8507                 break;
8508               }
8509               case 13:
8510               {
8511                 /*
8512                   Scale.
8513                 */
8514                 flags=ParseGeometry(value,&geometry_info);
8515                 affine.sx=geometry_info.rho;
8516                 affine.sy=geometry_info.sigma;
8517                 if ((flags & SigmaValue) == 0)
8518                   affine.sy=affine.sx;
8519                 break;
8520               }
8521               case 14:
8522               {
8523                 /*
8524                   Rotate.
8525                 */
8526                 if (angle == 0.0)
8527                   break;
8528                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8529                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8530                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8531                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8532                 break;
8533               }
8534               case 15:
8535               {
8536                 /*
8537                   SkewX.
8538                 */
8539                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8540                 break;
8541               }
8542               case 16:
8543               {
8544                 /*
8545                   SkewY.
8546                 */
8547                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8548                 break;
8549               }
8550             }
8551             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8552             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8553             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8554             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8555             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8556               current.tx;
8557             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8558               current.ty;
8559           }
8560           if (attribute_flag[9] == 0)
8561             argument_list[9].real_reference=0.0;
8562           if (attribute_flag[10] == 0)
8563             argument_list[10].real_reference=0.0;
8564           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8565             {
8566               char
8567                 geometry[MagickPathExtent];
8568
8569               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8570                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8571                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8572               (void) CloneString(&draw_info->geometry,geometry);
8573             }
8574           if (attribute_flag[17] != 0)
8575             draw_info->stroke_width=argument_list[17].real_reference;
8576           if (attribute_flag[18] != 0)
8577             {
8578               draw_info->text_antialias=
8579                 argument_list[18].integer_reference != 0 ? MagickTrue :
8580                 MagickFalse;
8581               draw_info->stroke_antialias=draw_info->text_antialias;
8582             }
8583           if (attribute_flag[19] != 0)
8584             (void) CloneString(&draw_info->family,
8585               argument_list[19].string_reference);
8586           if (attribute_flag[20] != 0)
8587             draw_info->style=(StyleType) argument_list[20].integer_reference;
8588           if (attribute_flag[21] != 0)
8589             draw_info->stretch=(StretchType)
8590               argument_list[21].integer_reference;
8591           if (attribute_flag[22] != 0)
8592             draw_info->weight=argument_list[22].integer_reference;
8593           if (attribute_flag[23] != 0)
8594             draw_info->align=(AlignType) argument_list[23].integer_reference;
8595           if (attribute_flag[24] != 0)
8596             (void) CloneString(&draw_info->encoding,
8597               argument_list[24].string_reference);
8598           if (attribute_flag[25] != 0)
8599             draw_info->fill_pattern=CloneImage(
8600               argument_list[25].image_reference,0,0,MagickTrue,exception);
8601           if (attribute_flag[26] != 0)
8602             draw_info->fill_pattern=CloneImage(
8603               argument_list[26].image_reference,0,0,MagickTrue,exception);
8604           if (attribute_flag[27] != 0)
8605             draw_info->stroke_pattern=CloneImage(
8606               argument_list[27].image_reference,0,0,MagickTrue,exception);
8607           if (attribute_flag[29] != 0)
8608             draw_info->kerning=argument_list[29].real_reference;
8609           if (attribute_flag[30] != 0)
8610             draw_info->interline_spacing=argument_list[30].real_reference;
8611           if (attribute_flag[31] != 0)
8612             draw_info->interword_spacing=argument_list[31].real_reference;
8613           if (attribute_flag[32] != 0)
8614             draw_info->direction=(DirectionType)
8615               argument_list[32].integer_reference;
8616           if (attribute_flag[33] != 0)
8617             draw_info->decorate=(DecorationType)
8618               argument_list[33].integer_reference;
8619           (void) AnnotateImage(image,draw_info,exception);
8620           draw_info=DestroyDrawInfo(draw_info);
8621           break;
8622         }
8623         case 34:  /* ColorFloodfill */
8624         {
8625           DrawInfo
8626             *draw_info;
8627
8628           MagickBooleanType
8629             invert;
8630
8631           PixelInfo
8632             target;
8633
8634           draw_info=CloneDrawInfo(info ? info->image_info :
8635             (ImageInfo *) NULL,(DrawInfo *) NULL);
8636           if (attribute_flag[0] != 0)
8637             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8638               &geometry,exception);
8639           if (attribute_flag[1] != 0)
8640             geometry.x=argument_list[1].integer_reference;
8641           if (attribute_flag[2] != 0)
8642             geometry.y=argument_list[2].integer_reference;
8643           if (attribute_flag[3] != 0)
8644             (void) QueryColorCompliance(argument_list[3].string_reference,
8645               AllCompliance,&draw_info->fill,exception);
8646           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8647             geometry.x,geometry.y,&target,exception);
8648           invert=MagickFalse;
8649           if (attribute_flag[4] != 0)
8650             {
8651               QueryColorCompliance(argument_list[4].string_reference,
8652                 AllCompliance,&target,exception);
8653               invert=MagickTrue;
8654             }
8655           if (attribute_flag[5] != 0)
8656             image->fuzz=StringToDoubleInterval(
8657               argument_list[5].string_reference,(double) QuantumRange+1.0);
8658           if (attribute_flag[6] != 0)
8659             invert=(MagickBooleanType) argument_list[6].integer_reference;
8660           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8661             geometry.y,invert,exception);
8662           draw_info=DestroyDrawInfo(draw_info);
8663           break;
8664         }
8665         case 35:  /* Composite */
8666         {
8667           char
8668             composite_geometry[MagickPathExtent];
8669
8670           Image
8671             *composite_image,
8672             *rotate_image;
8673
8674           MagickBooleanType
8675             clip_to_self;
8676
8677           compose=OverCompositeOp;
8678           if (attribute_flag[0] != 0)
8679             composite_image=argument_list[0].image_reference;
8680           else
8681             {
8682               ThrowPerlException(exception,OptionError,
8683                 "CompositeImageRequired",PackageName);
8684               goto PerlException;
8685             }
8686           /*
8687             Parameter Handling used for BOTH normal and tiled composition.
8688           */
8689           if (attribute_flag[1] != 0) /* compose */
8690             compose=(CompositeOperator) argument_list[1].integer_reference;
8691           if (attribute_flag[6] != 0) /* opacity  */
8692             {
8693               if (compose != DissolveCompositeOp)
8694                 (void) SetImageAlpha(composite_image,(Quantum)
8695                   StringToDoubleInterval(argument_list[6].string_reference,
8696                   (double) QuantumRange+1.0),exception);
8697               else
8698                 {
8699                   CacheView
8700                     *composite_view;
8701
8702                   double
8703                     opacity;
8704
8705                   MagickBooleanType
8706                     sync;
8707
8708                   register ssize_t
8709                     x;
8710
8711                   register Quantum
8712                     *q;
8713
8714                   ssize_t
8715                     y;
8716
8717                   /*
8718                     Handle dissolve composite operator (patch by
8719                     Kevin A. McGrail).
8720                   */
8721                   (void) CloneString(&image->geometry,
8722                     argument_list[6].string_reference);
8723                   opacity=(Quantum) StringToDoubleInterval(
8724                     argument_list[6].string_reference,(double) QuantumRange+
8725                     1.0);
8726                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8727                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8728                   composite_view=AcquireAuthenticCacheView(composite_image,
8729                     exception);
8730                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8731                   {
8732                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8733                       composite_image->columns,1,exception);
8734                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8735                     {
8736                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8737                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8738                           q);
8739                       q+=GetPixelChannels(composite_image);
8740                     }
8741                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8742                     if (sync == MagickFalse)
8743                       break;
8744                   }
8745                   composite_view=DestroyCacheView(composite_view);
8746                 }
8747             }
8748           if (attribute_flag[9] != 0)    /* "color=>" */
8749             QueryColorCompliance(argument_list[9].string_reference,
8750               AllCompliance,&composite_image->background_color,exception);
8751           if (attribute_flag[12] != 0) /* "interpolate=>" */
8752             image->interpolate=(PixelInterpolateMethod)
8753               argument_list[12].integer_reference;
8754           if (attribute_flag[13] != 0)   /* "args=>" */
8755             (void) SetImageArtifact(composite_image,"compose:args",
8756               argument_list[13].string_reference);
8757           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8758             (void) SetImageArtifact(composite_image,"compose:args",
8759               argument_list[14].string_reference);
8760           clip_to_self=MagickTrue;
8761           switch (compose)
8762           {
8763             case ClearCompositeOp:
8764             case SrcCompositeOp:
8765             case InCompositeOp:
8766             case SrcInCompositeOp:
8767             case OutCompositeOp:
8768             case SrcOutCompositeOp:
8769             case DstInCompositeOp:
8770             case DstAtopCompositeOp:
8771             case CopyAlphaCompositeOp:
8772             case ChangeMaskCompositeOp:
8773             case DissolveCompositeOp:
8774             case BlendCompositeOp:
8775             {
8776               clip_to_self=MagickFalse;
8777               break;
8778             }
8779             default:
8780               break;
8781           }
8782           if (attribute_flag[15] != 0)
8783             clip_to_self=(MagickBooleanType)
8784               argument_list[15].integer_reference;
8785           /*
8786             Tiling Composition (with orthogonal rotate).
8787           */
8788           rotate_image=(Image *) NULL;
8789           if (attribute_flag[8] != 0)   /* "rotate=>" */
8790             {
8791                /*
8792                  Rotate image.
8793                */
8794                rotate_image=RotateImage(composite_image,
8795                  argument_list[8].real_reference,exception);
8796                if (rotate_image == (Image *) NULL)
8797                  break;
8798             }
8799           if ((attribute_flag[7] != 0) &&
8800               (argument_list[7].integer_reference != 0)) /* tile */
8801             {
8802               ssize_t
8803                 x,
8804                 y;
8805
8806               /*
8807                 Tile the composite image.
8808               */
8809              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8810                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8811                 {
8812                   if (attribute_flag[8] != 0) /* rotate */
8813                     (void) CompositeImage(image,rotate_image,compose,
8814                       MagickTrue,x,y,exception);
8815                   else
8816                     (void) CompositeImage(image,composite_image,compose,
8817                       MagickTrue,x,y,exception);
8818                 }
8819               if (attribute_flag[8] != 0) /* rotate */
8820                 rotate_image=DestroyImage(rotate_image);
8821               break;
8822             }
8823           /*
8824             Parameter Handling used used ONLY for normal composition.
8825           */
8826           if (attribute_flag[5] != 0) /* gravity */
8827             image->gravity=(GravityType) argument_list[5].integer_reference;
8828           if (attribute_flag[2] != 0) /* geometry offset */
8829             {
8830               SetGeometry(image,&geometry);
8831               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8832                 &geometry);
8833               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8834                 &geometry);
8835             }
8836           if (attribute_flag[3] != 0) /* x offset */
8837             geometry.x=argument_list[3].integer_reference;
8838           if (attribute_flag[4] != 0) /* y offset */
8839             geometry.y=argument_list[4].integer_reference;
8840           if (attribute_flag[10] != 0) /* mask */
8841             {
8842               if ((image->compose == DisplaceCompositeOp) ||
8843                   (image->compose == DistortCompositeOp))
8844                 {
8845                   /*
8846                     Merge Y displacement into X displacement image.
8847                   */
8848                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8849                     exception);
8850                   (void) CompositeImage(composite_image,
8851                     argument_list[10].image_reference,CopyGreenCompositeOp,
8852                     clip_to_self,0,0,exception);
8853                 }
8854               else
8855                 {
8856                   Image
8857                     *mask_image;
8858
8859                   /*
8860                     Set a blending mask for the composition.
8861                   */
8862                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8863                     MagickTrue,exception);
8864                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8865                     exception);
8866                   mask_image=DestroyImage(mask_image);
8867                 }
8868             }
8869           if (attribute_flag[11] != 0) /* channel */
8870             channel=(ChannelType) argument_list[11].integer_reference;
8871           /*
8872             Composite two images (normal composition).
8873           */
8874           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8875             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8876             (double) composite_image->rows,(double) geometry.x,(double)
8877             geometry.y);
8878           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8879             exception);
8880           channel_mask=SetImageChannelMask(image,channel);
8881           if (attribute_flag[8] == 0) /* no rotate */
8882             CompositeImage(image,composite_image,compose,clip_to_self,
8883               geometry.x,geometry.y,exception);
8884           else
8885             {
8886               /*
8887                 Position adjust rotated image then composite.
8888               */
8889               geometry.x-=(ssize_t) (rotate_image->columns-
8890                 composite_image->columns)/2;
8891               geometry.y-=(ssize_t) (rotate_image->rows-
8892                 composite_image->rows)/2;
8893               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8894                 geometry.y,exception);
8895               rotate_image=DestroyImage(rotate_image);
8896             }
8897           if (attribute_flag[10] != 0) /* mask */
8898             {
8899               if ((image->compose == DisplaceCompositeOp) ||
8900                   (image->compose == DistortCompositeOp))
8901                 composite_image=DestroyImage(composite_image);
8902               else
8903                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8904                   exception);
8905             }
8906           (void) SetImageChannelMask(image,channel_mask);
8907           break;
8908         }
8909         case 36:  /* Contrast */
8910         {
8911           if (attribute_flag[0] == 0)
8912             argument_list[0].integer_reference=0;
8913           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8914             MagickTrue : MagickFalse,exception);
8915           break;
8916         }
8917         case 37:  /* CycleColormap */
8918         {
8919           if (attribute_flag[0] == 0)
8920             argument_list[0].integer_reference=6;
8921           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8922             exception);
8923           break;
8924         }
8925         case 38:  /* Draw */
8926         {
8927           DrawInfo
8928             *draw_info;
8929
8930           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8931             (DrawInfo *) NULL);
8932           (void) CloneString(&draw_info->primitive,"point");
8933           if (attribute_flag[0] != 0)
8934             {
8935               if (argument_list[0].integer_reference < 0)
8936                 (void) CloneString(&draw_info->primitive,
8937                   argument_list[0].string_reference);
8938               else
8939                 (void) CloneString(&draw_info->primitive,
8940                   CommandOptionToMnemonic(MagickPrimitiveOptions,
8941                   argument_list[0].integer_reference));
8942             }
8943           if (attribute_flag[1] != 0)
8944             {
8945               if (LocaleCompare(draw_info->primitive,"path") == 0)
8946                 {
8947                   (void) ConcatenateString(&draw_info->primitive," '");
8948                   ConcatenateString(&draw_info->primitive,
8949                     argument_list[1].string_reference);
8950                   (void) ConcatenateString(&draw_info->primitive,"'");
8951                 }
8952               else
8953                 {
8954                   (void) ConcatenateString(&draw_info->primitive," ");
8955                   ConcatenateString(&draw_info->primitive,
8956                     argument_list[1].string_reference);
8957                 }
8958             }
8959           if (attribute_flag[2] != 0)
8960             {
8961               (void) ConcatenateString(&draw_info->primitive," ");
8962               (void) ConcatenateString(&draw_info->primitive,
8963                 CommandOptionToMnemonic(MagickMethodOptions,
8964                 argument_list[2].integer_reference));
8965             }
8966           if (attribute_flag[3] != 0)
8967             {
8968               (void) QueryColorCompliance(argument_list[3].string_reference,
8969                 AllCompliance,&draw_info->stroke,exception);
8970               if (argument_list[3].image_reference != (Image *) NULL)
8971                 draw_info->stroke_pattern=CloneImage(
8972                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8973             }
8974           if (attribute_flag[4] != 0)
8975             {
8976               (void) QueryColorCompliance(argument_list[4].string_reference,
8977                 AllCompliance,&draw_info->fill,exception);
8978               if (argument_list[4].image_reference != (Image *) NULL)
8979                 draw_info->fill_pattern=CloneImage(
8980                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8981             }
8982           if (attribute_flag[5] != 0)
8983             draw_info->stroke_width=argument_list[5].real_reference;
8984           if (attribute_flag[6] != 0)
8985             (void) CloneString(&draw_info->font,
8986               argument_list[6].string_reference);
8987           if (attribute_flag[7] != 0)
8988             (void) QueryColorCompliance(argument_list[7].string_reference,
8989               AllCompliance,&draw_info->border_color,exception);
8990           if (attribute_flag[8] != 0)
8991             draw_info->affine.tx=argument_list[8].real_reference;
8992           if (attribute_flag[9] != 0)
8993             draw_info->affine.ty=argument_list[9].real_reference;
8994           if (attribute_flag[20] != 0)
8995             {
8996               AV
8997                 *av;
8998
8999               av=(AV *) argument_list[20].array_reference;
9000               if ((av_len(av) != 3) && (av_len(av) != 5))
9001                 {
9002                   ThrowPerlException(exception,OptionError,
9003                     "affine matrix must have 4 or 6 elements",PackageName);
9004                   goto PerlException;
9005                 }
9006               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9007               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9008               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9009               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9010               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9011                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9012                 {
9013                   ThrowPerlException(exception,OptionError,
9014                     "affine matrix is singular",PackageName);
9015                    goto PerlException;
9016                 }
9017               if (av_len(av) == 5)
9018                 {
9019                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9020                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9021                 }
9022             }
9023           for (j=10; j < 15; j++)
9024           {
9025             if (attribute_flag[j] == 0)
9026               continue;
9027             value=argument_list[j].string_reference;
9028             angle=argument_list[j].real_reference;
9029             current=draw_info->affine;
9030             GetAffineMatrix(&affine);
9031             switch (j)
9032             {
9033               case 10:
9034               {
9035                 /*
9036                   Translate.
9037                 */
9038                 flags=ParseGeometry(value,&geometry_info);
9039                 affine.tx=geometry_info.xi;
9040                 affine.ty=geometry_info.psi;
9041                 if ((flags & PsiValue) == 0)
9042                   affine.ty=affine.tx;
9043                 break;
9044               }
9045               case 11:
9046               {
9047                 /*
9048                   Scale.
9049                 */
9050                 flags=ParseGeometry(value,&geometry_info);
9051                 affine.sx=geometry_info.rho;
9052                 affine.sy=geometry_info.sigma;
9053                 if ((flags & SigmaValue) == 0)
9054                   affine.sy=affine.sx;
9055                 break;
9056               }
9057               case 12:
9058               {
9059                 /*
9060                   Rotate.
9061                 */
9062                 if (angle == 0.0)
9063                   break;
9064                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9065                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9066                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9067                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9068                 break;
9069               }
9070               case 13:
9071               {
9072                 /*
9073                   SkewX.
9074                 */
9075                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9076                 break;
9077               }
9078               case 14:
9079               {
9080                 /*
9081                   SkewY.
9082                 */
9083                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9084                 break;
9085               }
9086             }
9087             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9088             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9089             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9090             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9091             draw_info->affine.tx=
9092               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9093             draw_info->affine.ty=
9094               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9095           }
9096           if (attribute_flag[15] != 0)
9097             draw_info->fill_pattern=CloneImage(
9098               argument_list[15].image_reference,0,0,MagickTrue,exception);
9099           if (attribute_flag[16] != 0)
9100             draw_info->pointsize=argument_list[16].real_reference;
9101           if (attribute_flag[17] != 0)
9102             {
9103               draw_info->stroke_antialias=
9104                 argument_list[17].integer_reference != 0 ? MagickTrue :
9105                 MagickFalse;
9106               draw_info->text_antialias=draw_info->stroke_antialias;
9107             }
9108           if (attribute_flag[18] != 0)
9109             (void) CloneString(&draw_info->density,
9110               argument_list[18].string_reference);
9111           if (attribute_flag[19] != 0)
9112             draw_info->stroke_width=argument_list[19].real_reference;
9113           if (attribute_flag[21] != 0)
9114             draw_info->dash_offset=argument_list[21].real_reference;
9115           if (attribute_flag[22] != 0)
9116             {
9117               AV
9118                 *av;
9119
9120               av=(AV *) argument_list[22].array_reference;
9121               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9122                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9123               if (draw_info->dash_pattern != (double *) NULL)
9124                 {
9125                   for (i=0; i <= av_len(av); i++)
9126                     draw_info->dash_pattern[i]=(double)
9127                       SvNV(*(av_fetch(av,i,0)));
9128                   draw_info->dash_pattern[i]=0.0;
9129                 }
9130             }
9131           if (attribute_flag[23] != 0)
9132             image->interpolate=(PixelInterpolateMethod)
9133               argument_list[23].integer_reference;
9134           if ((attribute_flag[24] != 0) &&
9135               (draw_info->fill_pattern != (Image *) NULL))
9136             flags=ParsePageGeometry(draw_info->fill_pattern,
9137               argument_list[24].string_reference,
9138               &draw_info->fill_pattern->tile_offset,exception);
9139           if (attribute_flag[25] != 0)
9140             {
9141               (void) ConcatenateString(&draw_info->primitive," '");
9142               (void) ConcatenateString(&draw_info->primitive,
9143                 argument_list[25].string_reference);
9144               (void) ConcatenateString(&draw_info->primitive,"'");
9145             }
9146           if (attribute_flag[26] != 0)
9147             draw_info->fill_pattern=CloneImage(
9148               argument_list[26].image_reference,0,0,MagickTrue,exception);
9149           if (attribute_flag[27] != 0)
9150             draw_info->stroke_pattern=CloneImage(
9151               argument_list[27].image_reference,0,0,MagickTrue,exception);
9152           if (attribute_flag[28] != 0)
9153             (void) CloneString(&draw_info->primitive,
9154               argument_list[28].string_reference);
9155           if (attribute_flag[29] != 0)
9156             draw_info->kerning=argument_list[29].real_reference;
9157           if (attribute_flag[30] != 0)
9158             draw_info->interline_spacing=argument_list[30].real_reference;
9159           if (attribute_flag[31] != 0)
9160             draw_info->interword_spacing=argument_list[31].real_reference;
9161           if (attribute_flag[32] != 0)
9162             draw_info->direction=(DirectionType)
9163               argument_list[32].integer_reference;
9164           DrawImage(image,draw_info,exception);
9165           draw_info=DestroyDrawInfo(draw_info);
9166           break;
9167         }
9168         case 39:  /* Equalize */
9169         {
9170           if (attribute_flag[0] != 0)
9171             channel=(ChannelType) argument_list[0].integer_reference;
9172           channel_mask=SetImageChannelMask(image,channel);
9173           (void) EqualizeImage(image,exception);
9174           (void) SetImageChannelMask(image,channel_mask);
9175           break;
9176         }
9177         case 40:  /* Gamma */
9178         {
9179           if (attribute_flag[1] != 0)
9180             channel=(ChannelType) argument_list[1].integer_reference;
9181           if (attribute_flag[2] == 0)
9182             argument_list[2].real_reference=1.0;
9183           if (attribute_flag[3] == 0)
9184             argument_list[3].real_reference=1.0;
9185           if (attribute_flag[4] == 0)
9186             argument_list[4].real_reference=1.0;
9187           if (attribute_flag[0] == 0)
9188             {
9189               (void) FormatLocaleString(message,MagickPathExtent,
9190                 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
9191                 (double) argument_list[3].real_reference,
9192                 (double) argument_list[4].real_reference);
9193               argument_list[0].string_reference=message;
9194             }
9195           (void) GammaImage(image,StringToDouble(
9196             argument_list[0].string_reference,(char **) NULL),exception);
9197           break;
9198         }
9199         case 41:  /* Map */
9200         {
9201           QuantizeInfo
9202             *quantize_info;
9203
9204           if (attribute_flag[0] == 0)
9205             {
9206               ThrowPerlException(exception,OptionError,"MapImageRequired",
9207                 PackageName);
9208               goto PerlException;
9209             }
9210           quantize_info=AcquireQuantizeInfo(info->image_info);
9211           if (attribute_flag[1] != 0)
9212             quantize_info->dither_method=(DitherMethod)
9213               argument_list[1].integer_reference;
9214           (void) RemapImages(quantize_info,image,
9215             argument_list[0].image_reference,exception);
9216           quantize_info=DestroyQuantizeInfo(quantize_info);
9217           break;
9218         }
9219         case 42:  /* MatteFloodfill */
9220         {
9221           DrawInfo
9222             *draw_info;
9223
9224           MagickBooleanType
9225             invert;
9226
9227           PixelInfo
9228             target;
9229
9230           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9231             (DrawInfo *) NULL);
9232           if (attribute_flag[0] != 0)
9233             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9234               &geometry,exception);
9235           if (attribute_flag[1] != 0)
9236             geometry.x=argument_list[1].integer_reference;
9237           if (attribute_flag[2] != 0)
9238             geometry.y=argument_list[2].integer_reference;
9239           if (image->alpha_trait == UndefinedPixelTrait)
9240             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9241           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9242             geometry.x,geometry.y,&target,exception);
9243           if (attribute_flag[4] != 0)
9244             QueryColorCompliance(argument_list[4].string_reference,
9245               AllCompliance,&target,exception);
9246           if (attribute_flag[3] != 0)
9247             target.alpha=StringToDoubleInterval(
9248               argument_list[3].string_reference,(double) (double) QuantumRange+
9249               1.0);
9250           if (attribute_flag[5] != 0)
9251             image->fuzz=StringToDoubleInterval(
9252               argument_list[5].string_reference,(double) QuantumRange+1.0);
9253           invert=MagickFalse;
9254           if (attribute_flag[6] != 0)
9255             invert=(MagickBooleanType) argument_list[6].integer_reference;
9256           channel_mask=SetImageChannelMask(image,AlphaChannel);
9257           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9258             geometry.y,invert,exception);
9259           (void) SetImageChannelMask(image,channel_mask);
9260           draw_info=DestroyDrawInfo(draw_info);
9261           break;
9262         }
9263         case 43:  /* Modulate */
9264         {
9265           char
9266             modulate[MagickPathExtent];
9267
9268           geometry_info.rho=100.0;
9269           geometry_info.sigma=100.0;
9270           geometry_info.xi=100.0;
9271           if (attribute_flag[0] != 0)
9272             (void)ParseGeometry(argument_list[0].string_reference,
9273               &geometry_info);
9274           if (attribute_flag[1] != 0)
9275             geometry_info.xi=argument_list[1].real_reference;
9276           if (attribute_flag[2] != 0)
9277             geometry_info.sigma=argument_list[2].real_reference;
9278           if (attribute_flag[3] != 0)
9279             {
9280               geometry_info.sigma=argument_list[3].real_reference;
9281               SetImageArtifact(image,"modulate:colorspace","HWB");
9282             }
9283           if (attribute_flag[4] != 0)
9284             {
9285               geometry_info.rho=argument_list[4].real_reference;
9286               SetImageArtifact(image,"modulate:colorspace","HSB");
9287             }
9288           if (attribute_flag[5] != 0)
9289             {
9290               geometry_info.sigma=argument_list[5].real_reference;
9291               SetImageArtifact(image,"modulate:colorspace","HSL");
9292             }
9293           if (attribute_flag[6] != 0)
9294             {
9295               geometry_info.rho=argument_list[6].real_reference;
9296               SetImageArtifact(image,"modulate:colorspace","HWB");
9297             }
9298           (void) FormatLocaleString(modulate,MagickPathExtent,
9299             "%.20g,%.20g,%.20g",geometry_info.rho,geometry_info.sigma,
9300             geometry_info.xi);
9301           (void) ModulateImage(image,modulate,exception);
9302           break;
9303         }
9304         case 44:  /* Negate */
9305         {
9306           if (attribute_flag[0] == 0)
9307             argument_list[0].integer_reference=0;
9308           if (attribute_flag[1] != 0)
9309             channel=(ChannelType) argument_list[1].integer_reference;
9310           channel_mask=SetImageChannelMask(image,channel);
9311           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9312             MagickTrue : MagickFalse,exception);
9313           (void) SetImageChannelMask(image,channel_mask);
9314           break;
9315         }
9316         case 45:  /* Normalize */
9317         {
9318           if (attribute_flag[0] != 0)
9319             channel=(ChannelType) argument_list[0].integer_reference;
9320           channel_mask=SetImageChannelMask(image,channel);
9321           NormalizeImage(image,exception);
9322           (void) SetImageChannelMask(image,channel_mask);
9323           break;
9324         }
9325         case 46:  /* NumberColors */
9326           break;
9327         case 47:  /* Opaque */
9328         {
9329           MagickBooleanType
9330             invert;
9331
9332           PixelInfo
9333             fill_color,
9334             target;
9335
9336           (void) QueryColorCompliance("none",AllCompliance,&target,
9337              exception);
9338           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9339             exception);
9340           if (attribute_flag[0] != 0)
9341             (void) QueryColorCompliance(argument_list[0].string_reference,
9342               AllCompliance,&target,exception);
9343           if (attribute_flag[1] != 0)
9344             (void) QueryColorCompliance(argument_list[1].string_reference,
9345               AllCompliance,&fill_color,exception);
9346           if (attribute_flag[2] != 0)
9347             image->fuzz=StringToDoubleInterval(
9348               argument_list[2].string_reference,(double) QuantumRange+1.0);
9349           if (attribute_flag[3] != 0)
9350             channel=(ChannelType) argument_list[3].integer_reference;
9351           invert=MagickFalse;
9352           if (attribute_flag[4] != 0)
9353             invert=(MagickBooleanType) argument_list[4].integer_reference;
9354           channel_mask=SetImageChannelMask(image,channel);
9355           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9356           (void) SetImageChannelMask(image,channel_mask);
9357           break;
9358         }
9359         case 48:  /* Quantize */
9360         {
9361           QuantizeInfo
9362             *quantize_info;
9363
9364           quantize_info=AcquireQuantizeInfo(info->image_info);
9365           if (attribute_flag[0] != 0)
9366             quantize_info->number_colors=(size_t)
9367               argument_list[0].integer_reference;
9368           if (attribute_flag[1] != 0)
9369             quantize_info->tree_depth=(size_t)
9370               argument_list[1].integer_reference;
9371           if (attribute_flag[2] != 0)
9372             quantize_info->colorspace=(ColorspaceType)
9373               argument_list[2].integer_reference;
9374           if (attribute_flag[3] != 0)
9375             quantize_info->dither_method=(DitherMethod)
9376               argument_list[3].integer_reference;
9377           if (attribute_flag[4] != 0)
9378             quantize_info->measure_error=
9379               argument_list[4].integer_reference != 0 ? MagickTrue :
9380               MagickFalse;
9381           if (attribute_flag[6] != 0)
9382             (void) QueryColorCompliance(argument_list[6].string_reference,
9383               AllCompliance,&image->transparent_color,exception);
9384           if (attribute_flag[7] != 0)
9385             quantize_info->dither_method=(DitherMethod)
9386               argument_list[7].integer_reference;
9387           if (attribute_flag[5] && argument_list[5].integer_reference)
9388             (void) QuantizeImages(quantize_info,image,exception);
9389           else
9390             if ((image->storage_class == DirectClass) ||
9391                (image->colors > quantize_info->number_colors) ||
9392                (quantize_info->colorspace == GRAYColorspace))
9393              (void) QuantizeImage(quantize_info,image,exception);
9394            else
9395              CompressImageColormap(image,exception);
9396           quantize_info=DestroyQuantizeInfo(quantize_info);
9397           break;
9398         }
9399         case 49:  /* Raise */
9400         {
9401           if (attribute_flag[0] != 0)
9402             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9403               &geometry,exception);
9404           if (attribute_flag[1] != 0)
9405             geometry.width=argument_list[1].integer_reference;
9406           if (attribute_flag[2] != 0)
9407             geometry.height=argument_list[2].integer_reference;
9408           if (attribute_flag[3] == 0)
9409             argument_list[3].integer_reference=1;
9410           (void) RaiseImage(image,&geometry,
9411             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9412             exception);
9413           break;
9414         }
9415         case 50:  /* Segment */
9416         {
9417           ColorspaceType
9418             colorspace;
9419
9420           double
9421             cluster_threshold,
9422             smoothing_threshold;
9423
9424           MagickBooleanType
9425             verbose;
9426
9427           cluster_threshold=1.0;
9428           smoothing_threshold=1.5;
9429           colorspace=sRGBColorspace;
9430           verbose=MagickFalse;
9431           if (attribute_flag[0] != 0)
9432             {
9433               flags=ParseGeometry(argument_list[0].string_reference,
9434                 &geometry_info);
9435               cluster_threshold=geometry_info.rho;
9436               if (flags & SigmaValue)
9437                 smoothing_threshold=geometry_info.sigma;
9438             }
9439           if (attribute_flag[1] != 0)
9440             cluster_threshold=argument_list[1].real_reference;
9441           if (attribute_flag[2] != 0)
9442             smoothing_threshold=argument_list[2].real_reference;
9443           if (attribute_flag[3] != 0)
9444             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9445           if (attribute_flag[4] != 0)
9446             verbose=argument_list[4].integer_reference != 0 ? MagickTrue :
9447               MagickFalse;
9448           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9449             smoothing_threshold,exception);
9450           break;
9451         }
9452         case 51:  /* Signature */
9453         {
9454           (void) SignatureImage(image,exception);
9455           break;
9456         }
9457         case 52:  /* Solarize */
9458         {
9459           geometry_info.rho=QuantumRange/2.0;
9460           if (attribute_flag[0] != 0)
9461             flags=ParseGeometry(argument_list[0].string_reference,
9462               &geometry_info);
9463           if (attribute_flag[1] != 0)
9464             geometry_info.rho=StringToDoubleInterval(
9465               argument_list[1].string_reference,(double) QuantumRange+1.0);
9466           (void) SolarizeImage(image,geometry_info.rho,exception);
9467           break;
9468         }
9469         case 53:  /* Sync */
9470         {
9471           (void) SyncImage(image,exception);
9472           break;
9473         }
9474         case 54:  /* Texture */
9475         {
9476           if (attribute_flag[0] == 0)
9477             break;
9478           TextureImage(image,argument_list[0].image_reference,exception);
9479           break;
9480         }
9481         case 55:  /* Evalute */
9482         {
9483           MagickEvaluateOperator
9484             op;
9485
9486           op=SetEvaluateOperator;
9487           if (attribute_flag[0] == MagickFalse)
9488             argument_list[0].real_reference=0.0;
9489           if (attribute_flag[1] != MagickFalse)
9490             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9491           if (attribute_flag[2] != MagickFalse)
9492             channel=(ChannelType) argument_list[2].integer_reference;
9493           channel_mask=SetImageChannelMask(image,channel);
9494           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9495             exception);
9496           (void) SetImageChannelMask(image,channel_mask);
9497           break;
9498         }
9499         case 56:  /* Transparent */
9500         {
9501           double
9502             opacity;
9503
9504           MagickBooleanType
9505             invert;
9506
9507           PixelInfo
9508             target;
9509
9510           (void) QueryColorCompliance("none",AllCompliance,&target,
9511             exception);
9512           if (attribute_flag[0] != 0)
9513             (void) QueryColorCompliance(argument_list[0].string_reference,
9514               AllCompliance,&target,exception);
9515           opacity=TransparentAlpha;
9516           if (attribute_flag[1] != 0)
9517             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9518               (double) QuantumRange+1.0);
9519           if (attribute_flag[2] != 0)
9520             image->fuzz=StringToDoubleInterval(
9521               argument_list[2].string_reference,(double) QuantumRange+1.0);
9522           if (attribute_flag[3] == 0)
9523             argument_list[3].integer_reference=0;
9524           invert=MagickFalse;
9525           if (attribute_flag[3] != 0)
9526             invert=(MagickBooleanType) argument_list[3].integer_reference;
9527           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9528             invert,exception);
9529           break;
9530         }
9531         case 57:  /* Threshold */
9532         {
9533           double
9534             threshold;
9535
9536           if (attribute_flag[0] == 0)
9537             argument_list[0].string_reference="50%";
9538           if (attribute_flag[1] != 0)
9539             channel=(ChannelType) argument_list[1].integer_reference;
9540           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9541             (double) QuantumRange+1.0);
9542           channel_mask=SetImageChannelMask(image,channel);
9543           (void) BilevelImage(image,threshold,exception);
9544           (void) SetImageChannelMask(image,channel_mask);
9545           break;
9546         }
9547         case 58:  /* Charcoal */
9548         {
9549           if (attribute_flag[0] != 0)
9550             {
9551               flags=ParseGeometry(argument_list[0].string_reference,
9552                 &geometry_info);
9553               if ((flags & SigmaValue) == 0)
9554                 geometry_info.sigma=1.0;
9555             }
9556           if (attribute_flag[1] != 0)
9557             geometry_info.rho=argument_list[1].real_reference;
9558           if (attribute_flag[2] != 0)
9559             geometry_info.sigma=argument_list[2].real_reference;
9560           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9561             exception);
9562           break;
9563         }
9564         case 59:  /* Trim */
9565         {
9566           if (attribute_flag[0] != 0)
9567             image->fuzz=StringToDoubleInterval(
9568               argument_list[0].string_reference,(double) QuantumRange+1.0);
9569           image=TrimImage(image,exception);
9570           break;
9571         }
9572         case 60:  /* Wave */
9573         {
9574           PixelInterpolateMethod
9575             method;
9576
9577           if (attribute_flag[0] != 0)
9578             {
9579               flags=ParseGeometry(argument_list[0].string_reference,
9580                 &geometry_info);
9581               if ((flags & SigmaValue) == 0)
9582                 geometry_info.sigma=1.0;
9583             }
9584           if (attribute_flag[1] != 0)
9585             geometry_info.rho=argument_list[1].real_reference;
9586           if (attribute_flag[2] != 0)
9587             geometry_info.sigma=argument_list[2].real_reference;
9588           method=UndefinedInterpolatePixel;
9589           if (attribute_flag[3] != 0)
9590             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9591           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9592             method,exception);
9593           break;
9594         }
9595         case 61:  /* Separate */
9596         {
9597           if (attribute_flag[0] != 0)
9598             channel=(ChannelType) argument_list[0].integer_reference;
9599           image=SeparateImage(image,channel,exception);
9600           break;
9601         }
9602         case 63:  /* Stereo */
9603         {
9604           if (attribute_flag[0] == 0)
9605             {
9606               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9607                 PackageName);
9608               goto PerlException;
9609             }
9610           if (attribute_flag[1] != 0)
9611             geometry.x=argument_list[1].integer_reference;
9612           if (attribute_flag[2] != 0)
9613             geometry.y=argument_list[2].integer_reference;
9614           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9615             geometry.x,geometry.y,exception);
9616           break;
9617         }
9618         case 64:  /* Stegano */
9619         {
9620           if (attribute_flag[0] == 0)
9621             {
9622               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9623                 PackageName);
9624               goto PerlException;
9625             }
9626           if (attribute_flag[1] == 0)
9627             argument_list[1].integer_reference=0;
9628           image->offset=argument_list[1].integer_reference;
9629           image=SteganoImage(image,argument_list[0].image_reference,exception);
9630           break;
9631         }
9632         case 65:  /* Deconstruct */
9633         {
9634           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9635           break;
9636         }
9637         case 66:  /* GaussianBlur */
9638         {
9639           if (attribute_flag[0] != 0)
9640             {
9641               flags=ParseGeometry(argument_list[0].string_reference,
9642                 &geometry_info);
9643               if ((flags & SigmaValue) == 0)
9644                 geometry_info.sigma=1.0;
9645             }
9646           if (attribute_flag[1] != 0)
9647             geometry_info.rho=argument_list[1].real_reference;
9648           if (attribute_flag[2] != 0)
9649             geometry_info.sigma=argument_list[2].real_reference;
9650           if (attribute_flag[3] != 0)
9651             channel=(ChannelType) argument_list[3].integer_reference;
9652           channel_mask=SetImageChannelMask(image,channel);
9653           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9654             exception);
9655           if (image != (Image *) NULL)
9656             (void) SetImageChannelMask(image,channel_mask);
9657           break;
9658         }
9659         case 67:  /* Convolve */
9660         {
9661           KernelInfo
9662             *kernel;
9663
9664           kernel=(KernelInfo *) NULL;
9665           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9666             break;
9667           if (attribute_flag[0] != 0)
9668             {
9669               AV
9670                 *av;
9671
9672               size_t
9673                 order;
9674
9675               kernel=AcquireKernelInfo((const char *) NULL,exception);
9676               if (kernel == (KernelInfo *) NULL)
9677                 break;
9678               av=(AV *) argument_list[0].array_reference;
9679               order=(size_t) sqrt(av_len(av)+1);
9680               kernel->width=order;
9681               kernel->height=order;
9682               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9683                 order*sizeof(*kernel->values));
9684               if (kernel->values == (MagickRealType *) NULL)
9685                 {
9686                   kernel=DestroyKernelInfo(kernel);
9687                   ThrowPerlException(exception,ResourceLimitFatalError,
9688                     "MemoryAllocationFailed",PackageName);
9689                   goto PerlException;
9690                 }
9691               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9692                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9693               for ( ; j < (ssize_t) (order*order); j++)
9694                 kernel->values[j]=0.0;
9695             }
9696           if (attribute_flag[1] != 0)
9697             channel=(ChannelType) argument_list[1].integer_reference;
9698           if (attribute_flag[2] != 0)
9699             SetImageArtifact(image,"convolve:bias",
9700               argument_list[2].string_reference);
9701           if (attribute_flag[3] != 0)
9702             {
9703               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9704                 exception);
9705               if (kernel == (KernelInfo *) NULL)
9706                 break;
9707             }
9708           channel_mask=SetImageChannelMask(image,channel);
9709           image=ConvolveImage(image,kernel,exception);
9710           if (image != (Image *) NULL)
9711             (void) SetImageChannelMask(image,channel_mask);
9712           kernel=DestroyKernelInfo(kernel);
9713           break;
9714         }
9715         case 68:  /* Profile */
9716         {
9717           const char
9718             *name;
9719
9720           Image
9721             *profile_image;
9722
9723           ImageInfo
9724             *profile_info;
9725
9726           StringInfo
9727             *profile;
9728
9729           name="*";
9730           if (attribute_flag[0] != 0)
9731             name=argument_list[0].string_reference;
9732           if (attribute_flag[2] != 0)
9733             image->rendering_intent=(RenderingIntent)
9734               argument_list[2].integer_reference;
9735           if (attribute_flag[3] != 0)
9736             image->black_point_compensation=
9737               argument_list[3].integer_reference != 0 ? MagickTrue :
9738               MagickFalse;
9739           if (attribute_flag[1] != 0)
9740             {
9741               if (argument_list[1].length == 0)
9742                 {
9743                   /*
9744                     Remove a profile from the image.
9745                   */
9746                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9747                     exception);
9748                   break;
9749                 }
9750               /*
9751                 Associate user supplied profile with the image.
9752               */
9753               profile=AcquireStringInfo(argument_list[1].length);
9754               SetStringInfoDatum(profile,(const unsigned char *)
9755                 argument_list[1].string_reference);
9756               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9757                 (size_t) GetStringInfoLength(profile),exception);
9758               profile=DestroyStringInfo(profile);
9759               break;
9760             }
9761           /*
9762             Associate a profile with the image.
9763           */
9764           profile_info=CloneImageInfo(info ? info->image_info : (ImageInfo *)
9765             NULL);
9766           profile_image=ReadImages(profile_info,name,exception);
9767           if (profile_image == (Image *) NULL)
9768             break;
9769           ResetImageProfileIterator(profile_image);
9770           name=GetNextImageProfile(profile_image);
9771           while (name != (const char *) NULL)
9772           {
9773             const StringInfo
9774               *profile;
9775
9776             profile=GetImageProfile(profile_image,name);
9777             if (profile != (const StringInfo *) NULL)
9778               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9779                 (size_t) GetStringInfoLength(profile),exception);
9780             name=GetNextImageProfile(profile_image);
9781           }
9782           profile_image=DestroyImage(profile_image);
9783           profile_info=DestroyImageInfo(profile_info);
9784           break;
9785         }
9786         case 69:  /* UnsharpMask */
9787         {
9788           if (attribute_flag[0] != 0)
9789             {
9790               flags=ParseGeometry(argument_list[0].string_reference,
9791                 &geometry_info);
9792               if ((flags & SigmaValue) == 0)
9793                 geometry_info.sigma=1.0;
9794               if ((flags & XiValue) == 0)
9795                 geometry_info.xi=1.0;
9796               if ((flags & PsiValue) == 0)
9797                 geometry_info.psi=0.5;
9798             }
9799           if (attribute_flag[1] != 0)
9800             geometry_info.rho=argument_list[1].real_reference;
9801           if (attribute_flag[2] != 0)
9802             geometry_info.sigma=argument_list[2].real_reference;
9803           if (attribute_flag[3] != 0)
9804             geometry_info.xi=argument_list[3].real_reference;
9805           if (attribute_flag[4] != 0)
9806             geometry_info.psi=argument_list[4].real_reference;
9807           if (attribute_flag[5] != 0)
9808             channel=(ChannelType) argument_list[5].integer_reference;
9809           channel_mask=SetImageChannelMask(image,channel);
9810           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9811             geometry_info.xi,geometry_info.psi,exception);
9812           if (image != (Image *) NULL)
9813             (void) SetImageChannelMask(image,channel_mask);
9814           break;
9815         }
9816         case 70:  /* MotionBlur */
9817         {
9818           if (attribute_flag[0] != 0)
9819             {
9820               flags=ParseGeometry(argument_list[0].string_reference,
9821                 &geometry_info);
9822               if ((flags & SigmaValue) == 0)
9823                 geometry_info.sigma=1.0;
9824               if ((flags & XiValue) == 0)
9825                 geometry_info.xi=1.0;
9826             }
9827           if (attribute_flag[1] != 0)
9828             geometry_info.rho=argument_list[1].real_reference;
9829           if (attribute_flag[2] != 0)
9830             geometry_info.sigma=argument_list[2].real_reference;
9831           if (attribute_flag[3] != 0)
9832             geometry_info.xi=argument_list[3].real_reference;
9833           if (attribute_flag[4] != 0)
9834             channel=(ChannelType) argument_list[4].integer_reference;
9835           channel_mask=SetImageChannelMask(image,channel);
9836           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9837             geometry_info.xi,exception);
9838           if (image != (Image *) NULL)
9839             (void) SetImageChannelMask(image,channel_mask);
9840           break;
9841         }
9842         case 71:  /* OrderedDither */
9843         {
9844           if (attribute_flag[0] == 0)
9845             argument_list[0].string_reference="o8x8";
9846           if (attribute_flag[1] != 0)
9847             channel=(ChannelType) argument_list[1].integer_reference;
9848           channel_mask=SetImageChannelMask(image,channel);
9849           (void) OrderedDitherImage(image,argument_list[0].string_reference,
9850             exception);
9851           (void) SetImageChannelMask(image,channel_mask);
9852           break;
9853         }
9854         case 72:  /* Shave */
9855         {
9856           if (attribute_flag[0] != 0)
9857             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9858               &geometry,exception);
9859           if (attribute_flag[1] != 0)
9860             geometry.width=argument_list[1].integer_reference;
9861           if (attribute_flag[2] != 0)
9862             geometry.height=argument_list[2].integer_reference;
9863           image=ShaveImage(image,&geometry,exception);
9864           break;
9865         }
9866         case 73:  /* Level */
9867         {
9868           double
9869             black_point,
9870             gamma,
9871             white_point;
9872
9873           black_point=0.0;
9874           white_point=(double) image->columns*image->rows;
9875           gamma=1.0;
9876           if (attribute_flag[0] != 0)
9877             {
9878               flags=ParseGeometry(argument_list[0].string_reference,
9879                 &geometry_info);
9880               black_point=geometry_info.rho;
9881               if ((flags & SigmaValue) != 0)
9882                 white_point=geometry_info.sigma;
9883               if ((flags & XiValue) != 0)
9884                 gamma=geometry_info.xi;
9885               if ((flags & PercentValue) != 0)
9886                 {
9887                   black_point*=(double) (QuantumRange/100.0);
9888                   white_point*=(double) (QuantumRange/100.0);
9889                 }
9890               if ((flags & SigmaValue) == 0)
9891                 white_point=(double) QuantumRange-black_point;
9892             }
9893           if (attribute_flag[1] != 0)
9894             black_point=argument_list[1].real_reference;
9895           if (attribute_flag[2] != 0)
9896             white_point=argument_list[2].real_reference;
9897           if (attribute_flag[3] != 0)
9898             gamma=argument_list[3].real_reference;
9899           if (attribute_flag[4] != 0)
9900             channel=(ChannelType) argument_list[4].integer_reference;
9901           if (attribute_flag[5] != 0)
9902             {
9903               argument_list[0].real_reference=argument_list[5].real_reference;
9904               attribute_flag[0]=attribute_flag[5];
9905             }
9906           channel_mask=SetImageChannelMask(image,channel);
9907           (void) LevelImage(image,black_point,white_point,gamma,exception);
9908           (void) SetImageChannelMask(image,channel_mask);
9909           break;
9910         }
9911         case 74:  /* Clip */
9912         {
9913           if (attribute_flag[0] == 0)
9914             argument_list[0].string_reference="#1";
9915           if (attribute_flag[1] == 0)
9916             argument_list[1].integer_reference=MagickTrue;
9917           (void) ClipImagePath(image,argument_list[0].string_reference,
9918             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9919             exception);
9920           break;
9921         }
9922         case 75:  /* AffineTransform */
9923         {
9924           DrawInfo
9925             *draw_info;
9926
9927           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9928             (DrawInfo *) NULL);
9929           if (attribute_flag[0] != 0)
9930             {
9931               AV
9932                 *av;
9933
9934               av=(AV *) argument_list[0].array_reference;
9935               if ((av_len(av) != 3) && (av_len(av) != 5))
9936                 {
9937                   ThrowPerlException(exception,OptionError,
9938                     "affine matrix must have 4 or 6 elements",PackageName);
9939                   goto PerlException;
9940                 }
9941               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9942               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9943               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9944               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9945               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9946                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9947                 {
9948                   ThrowPerlException(exception,OptionError,
9949                     "affine matrix is singular",PackageName);
9950                    goto PerlException;
9951                 }
9952               if (av_len(av) == 5)
9953                 {
9954                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9955                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9956                 }
9957             }
9958           for (j=1; j < 6; j++)
9959           {
9960             if (attribute_flag[j] == 0)
9961               continue;
9962             value=argument_list[j].string_reference;
9963             angle=argument_list[j].real_reference;
9964             current=draw_info->affine;
9965             GetAffineMatrix(&affine);
9966             switch (j)
9967             {
9968               case 1:
9969               {
9970                 /*
9971                   Translate.
9972                 */
9973                 flags=ParseGeometry(value,&geometry_info);
9974                 affine.tx=geometry_info.xi;
9975                 affine.ty=geometry_info.psi;
9976                 if ((flags & PsiValue) == 0)
9977                   affine.ty=affine.tx;
9978                 break;
9979               }
9980               case 2:
9981               {
9982                 /*
9983                   Scale.
9984                 */
9985                 flags=ParseGeometry(value,&geometry_info);
9986                 affine.sx=geometry_info.rho;
9987                 affine.sy=geometry_info.sigma;
9988                 if ((flags & SigmaValue) == 0)
9989                   affine.sy=affine.sx;
9990                 break;
9991               }
9992               case 3:
9993               {
9994                 /*
9995                   Rotate.
9996                 */
9997                 if (angle == 0.0)
9998                   break;
9999                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
10000                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
10001                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
10002                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
10003                 break;
10004               }
10005               case 4:
10006               {
10007                 /*
10008                   SkewX.
10009                 */
10010                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
10011                 break;
10012               }
10013               case 5:
10014               {
10015                 /*
10016                   SkewY.
10017                 */
10018                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
10019                 break;
10020               }
10021             }
10022             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
10023             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
10024             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
10025             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
10026             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
10027               current.tx;
10028             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
10029               current.ty;
10030           }
10031           if (attribute_flag[6] != 0)
10032             image->interpolate=(PixelInterpolateMethod)
10033               argument_list[6].integer_reference;
10034           if (attribute_flag[7] != 0)
10035             QueryColorCompliance(argument_list[7].string_reference,
10036               AllCompliance,&image->background_color,exception);
10037           image=AffineTransformImage(image,&draw_info->affine,exception);
10038           draw_info=DestroyDrawInfo(draw_info);
10039           break;
10040         }
10041         case 76:  /* Difference */
10042         {
10043           if (attribute_flag[0] == 0)
10044             {
10045               ThrowPerlException(exception,OptionError,
10046                 "ReferenceImageRequired",PackageName);
10047               goto PerlException;
10048             }
10049           if (attribute_flag[1] != 0)
10050             image->fuzz=StringToDoubleInterval(
10051               argument_list[1].string_reference,(double) QuantumRange+1.0);
10052           (void) SetImageColorMetric(image,argument_list[0].image_reference,
10053             exception);
10054           break;
10055         }
10056         case 77:  /* AdaptiveThreshold */
10057         {
10058           if (attribute_flag[0] != 0)
10059             {
10060               flags=ParseGeometry(argument_list[0].string_reference,
10061                 &geometry_info);
10062               if ((flags & PercentValue) != 0)
10063                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10064             }
10065           if (attribute_flag[1] != 0)
10066             geometry_info.rho=argument_list[1].integer_reference;
10067           if (attribute_flag[2] != 0)
10068             geometry_info.sigma=argument_list[2].integer_reference;
10069           if (attribute_flag[3] != 0)
10070             geometry_info.xi=argument_list[3].integer_reference;;
10071           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
10072             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
10073           break;
10074         }
10075         case 78:  /* Resample */
10076         {
10077           size_t
10078             height,
10079             width;
10080
10081           if (attribute_flag[0] != 0)
10082             {
10083               flags=ParseGeometry(argument_list[0].string_reference,
10084                 &geometry_info);
10085               if ((flags & SigmaValue) == 0)
10086                 geometry_info.sigma=geometry_info.rho;
10087             }
10088           if (attribute_flag[1] != 0)
10089             geometry_info.rho=argument_list[1].real_reference;
10090           if (attribute_flag[2] != 0)
10091             geometry_info.sigma=argument_list[2].real_reference;
10092           if (attribute_flag[3] == 0)
10093             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10094           if (attribute_flag[4] == 0)
10095             SetImageArtifact(image,"filter:support",
10096               argument_list[4].string_reference);
10097           width=(size_t) (geometry_info.rho*image->columns/
10098             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10099           height=(size_t) (geometry_info.sigma*image->rows/
10100             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10101           image=ResizeImage(image,width,height,(FilterType)
10102             argument_list[3].integer_reference,exception);
10103           if (image != (Image *) NULL)
10104             {
10105               image->resolution.x=geometry_info.rho;
10106               image->resolution.y=geometry_info.sigma;
10107             }
10108           break;
10109         }
10110         case 79:  /* Describe */
10111         {
10112           if (attribute_flag[0] == 0)
10113             argument_list[0].file_reference=(FILE *) NULL;
10114           if (attribute_flag[1] != 0)
10115             (void) SetImageArtifact(image,"identify:features",
10116               argument_list[1].string_reference);
10117           (void) IdentifyImage(image,argument_list[0].file_reference,
10118             MagickTrue,exception);
10119           break;
10120         }
10121         case 80:  /* BlackThreshold */
10122         {
10123           if (attribute_flag[0] == 0)
10124             argument_list[0].string_reference="50%";
10125           if (attribute_flag[2] != 0)
10126             channel=(ChannelType) argument_list[2].integer_reference;
10127           channel_mask=SetImageChannelMask(image,channel);
10128           BlackThresholdImage(image,argument_list[0].string_reference,
10129             exception);
10130           (void) SetImageChannelMask(image,channel_mask);
10131           break;
10132         }
10133         case 81:  /* WhiteThreshold */
10134         {
10135           if (attribute_flag[0] == 0)
10136             argument_list[0].string_reference="50%";
10137           if (attribute_flag[2] != 0)
10138             channel=(ChannelType) argument_list[2].integer_reference;
10139           channel_mask=SetImageChannelMask(image,channel);
10140           WhiteThresholdImage(image,argument_list[0].string_reference,
10141             exception);
10142           (void) SetImageChannelMask(image,channel_mask);
10143           break;
10144         }
10145         case 82:  /* RotationalBlur */
10146         {
10147           if (attribute_flag[0] != 0)
10148             flags=ParseGeometry(argument_list[0].string_reference,
10149               &geometry_info);
10150           if (attribute_flag[1] != 0)
10151             geometry_info.rho=argument_list[1].real_reference;
10152           if (attribute_flag[2] != 0)
10153             channel=(ChannelType) argument_list[2].integer_reference;
10154           channel_mask=SetImageChannelMask(image,channel);
10155           image=RotationalBlurImage(image,geometry_info.rho,exception);
10156           if (image != (Image *) NULL)
10157             (void) SetImageChannelMask(image,channel_mask);
10158           break;
10159         }
10160         case 83:  /* Thumbnail */
10161         {
10162           if (attribute_flag[0] != 0)
10163             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10164               &geometry,exception);
10165           if (attribute_flag[1] != 0)
10166             geometry.width=argument_list[1].integer_reference;
10167           if (attribute_flag[2] != 0)
10168             geometry.height=argument_list[2].integer_reference;
10169           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10170           break;
10171         }
10172         case 84:  /* Strip */
10173         {
10174           (void) StripImage(image,exception);
10175           break;
10176         }
10177         case 85:  /* Tint */
10178         {
10179           PixelInfo
10180             tint;
10181
10182           GetPixelInfo(image,&tint);
10183           if (attribute_flag[0] != 0)
10184             (void) QueryColorCompliance(argument_list[0].string_reference,
10185               AllCompliance,&tint,exception);
10186           if (attribute_flag[1] == 0)
10187             argument_list[1].string_reference="100";
10188           image=TintImage(image,argument_list[1].string_reference,&tint,
10189             exception);
10190           break;
10191         }
10192         case 86:  /* Channel */
10193         {
10194           if (attribute_flag[0] != 0)
10195             channel=(ChannelType) argument_list[0].integer_reference;
10196           image=SeparateImage(image,channel,exception);
10197           break;
10198         }
10199         case 87:  /* Splice */
10200         {
10201           if (attribute_flag[7] != 0)
10202             image->gravity=(GravityType) argument_list[7].integer_reference;
10203           if (attribute_flag[0] != 0)
10204             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10205               &geometry,exception);
10206           if (attribute_flag[1] != 0)
10207             geometry.width=argument_list[1].integer_reference;
10208           if (attribute_flag[2] != 0)
10209             geometry.height=argument_list[2].integer_reference;
10210           if (attribute_flag[3] != 0)
10211             geometry.x=argument_list[3].integer_reference;
10212           if (attribute_flag[4] != 0)
10213             geometry.y=argument_list[4].integer_reference;
10214           if (attribute_flag[5] != 0)
10215             image->fuzz=StringToDoubleInterval(
10216               argument_list[5].string_reference,(double) QuantumRange+1.0);
10217           if (attribute_flag[6] != 0)
10218             (void) QueryColorCompliance(argument_list[6].string_reference,
10219               AllCompliance,&image->background_color,exception);
10220           image=SpliceImage(image,&geometry,exception);
10221           break;
10222         }
10223         case 88:  /* Posterize */
10224         {
10225           if (attribute_flag[0] == 0)
10226             argument_list[0].integer_reference=3;
10227           if (attribute_flag[1] == 0)
10228             argument_list[1].integer_reference=0;
10229           (void) PosterizeImage(image,argument_list[0].integer_reference,
10230             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10231             NoDitherMethod,exception);
10232           break;
10233         }
10234         case 89:  /* Shadow */
10235         {
10236           if (attribute_flag[0] != 0)
10237             {
10238               flags=ParseGeometry(argument_list[0].string_reference,
10239                 &geometry_info);
10240               if ((flags & SigmaValue) == 0)
10241                 geometry_info.sigma=1.0;
10242               if ((flags & XiValue) == 0)
10243                 geometry_info.xi=4.0;
10244               if ((flags & PsiValue) == 0)
10245                 geometry_info.psi=4.0;
10246             }
10247           if (attribute_flag[1] != 0)
10248             geometry_info.rho=argument_list[1].real_reference;
10249           if (attribute_flag[2] != 0)
10250             geometry_info.sigma=argument_list[2].real_reference;
10251           if (attribute_flag[3] != 0)
10252             geometry_info.xi=argument_list[3].integer_reference;
10253           if (attribute_flag[4] != 0)
10254             geometry_info.psi=argument_list[4].integer_reference;
10255           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10256             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10257             ceil(geometry_info.psi-0.5),exception);
10258           break;
10259         }
10260         case 90:  /* Identify */
10261         {
10262           if (attribute_flag[0] == 0)
10263             argument_list[0].file_reference=(FILE *) NULL;
10264           if (attribute_flag[1] != 0)
10265             (void) SetImageArtifact(image,"identify:features",
10266               argument_list[1].string_reference);
10267           if ((attribute_flag[2] != 0) &&
10268               (argument_list[2].integer_reference != 0))
10269             (void) SetImageArtifact(image,"identify:unique","true");
10270           (void) IdentifyImage(image,argument_list[0].file_reference,
10271             MagickTrue,exception);
10272           break;
10273         }
10274         case 91:  /* SepiaTone */
10275         {
10276           if (attribute_flag[0] == 0)
10277             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10278           image=SepiaToneImage(image,argument_list[0].real_reference,exception);
10279           break;
10280         }
10281         case 92:  /* SigmoidalContrast */
10282         {
10283           MagickBooleanType
10284             sharpen;
10285
10286           if (attribute_flag[0] != 0)
10287             {
10288               flags=ParseGeometry(argument_list[0].string_reference,
10289                 &geometry_info);
10290               if ((flags & SigmaValue) == 0)
10291                 geometry_info.sigma=QuantumRange/2.0;
10292               if ((flags & PercentValue) != 0)
10293                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10294             }
10295           if (attribute_flag[1] != 0)
10296             geometry_info.rho=argument_list[1].real_reference;
10297           if (attribute_flag[2] != 0)
10298             geometry_info.sigma=argument_list[2].real_reference;
10299           if (attribute_flag[3] != 0)
10300             channel=(ChannelType) argument_list[3].integer_reference;
10301           sharpen=MagickTrue;
10302           if (attribute_flag[4] != 0)
10303             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10304               MagickFalse;
10305           channel_mask=SetImageChannelMask(image,channel);
10306           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10307             geometry_info.sigma,exception);
10308           (void) SetImageChannelMask(image,channel_mask);
10309           break;
10310         }
10311         case 93:  /* Extent */
10312         {
10313           if (attribute_flag[7] != 0)
10314             image->gravity=(GravityType) argument_list[7].integer_reference;
10315           if (attribute_flag[0] != 0)
10316             {
10317               int
10318                 flags;
10319
10320               flags=ParseGravityGeometry(image,
10321                 argument_list[0].string_reference,&geometry,exception);
10322               (void) flags;
10323               if (geometry.width == 0)
10324                 geometry.width=image->columns;
10325               if (geometry.height == 0)
10326                 geometry.height=image->rows;
10327             }
10328           if (attribute_flag[1] != 0)
10329             geometry.width=argument_list[1].integer_reference;
10330           if (attribute_flag[2] != 0)
10331             geometry.height=argument_list[2].integer_reference;
10332           if (attribute_flag[3] != 0)
10333             geometry.x=argument_list[3].integer_reference;
10334           if (attribute_flag[4] != 0)
10335             geometry.y=argument_list[4].integer_reference;
10336           if (attribute_flag[5] != 0)
10337             image->fuzz=StringToDoubleInterval(
10338               argument_list[5].string_reference,(double) QuantumRange+1.0);
10339           if (attribute_flag[6] != 0)
10340             (void) QueryColorCompliance(argument_list[6].string_reference,
10341               AllCompliance,&image->background_color,exception);
10342           image=ExtentImage(image,&geometry,exception);
10343           break;
10344         }
10345         case 94:  /* Vignette */
10346         {
10347           if (attribute_flag[0] != 0)
10348             {
10349               flags=ParseGeometry(argument_list[0].string_reference,
10350                 &geometry_info);
10351               if ((flags & SigmaValue) == 0)
10352                 geometry_info.sigma=1.0;
10353               if ((flags & XiValue) == 0)
10354                 geometry_info.xi=0.1*image->columns;
10355               if ((flags & PsiValue) == 0)
10356                 geometry_info.psi=0.1*image->rows;
10357             }
10358           if (attribute_flag[1] != 0)
10359             geometry_info.rho=argument_list[1].real_reference;
10360           if (attribute_flag[2] != 0)
10361             geometry_info.sigma=argument_list[2].real_reference;
10362           if (attribute_flag[3] != 0)
10363             geometry_info.xi=argument_list[3].integer_reference;
10364           if (attribute_flag[4] != 0)
10365             geometry_info.psi=argument_list[4].integer_reference;
10366           if (attribute_flag[5] != 0)
10367             (void) QueryColorCompliance(argument_list[5].string_reference,
10368               AllCompliance,&image->background_color,exception);
10369           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10370             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10371             ceil(geometry_info.psi-0.5),exception);
10372           break;
10373         }
10374         case 95:  /* ContrastStretch */
10375         {
10376           double
10377             black_point,
10378             white_point;
10379
10380           black_point=0.0;
10381           white_point=(double) image->columns*image->rows;
10382           if (attribute_flag[0] != 0)
10383             {
10384               flags=ParseGeometry(argument_list[0].string_reference,
10385                 &geometry_info);
10386               black_point=geometry_info.rho;
10387               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10388                 black_point;
10389               if ((flags & PercentValue) != 0)
10390                 {
10391                   black_point*=(double) image->columns*image->rows/100.0;
10392                   white_point*=(double) image->columns*image->rows/100.0;
10393                 }
10394               white_point=(double) image->columns*image->rows-white_point;
10395             }
10396           if (attribute_flag[1] != 0)
10397             black_point=argument_list[1].real_reference;
10398           if (attribute_flag[2] != 0)
10399             white_point=argument_list[2].real_reference;
10400           if (attribute_flag[4] != 0)
10401             channel=(ChannelType) argument_list[4].integer_reference;
10402           channel_mask=SetImageChannelMask(image,channel);
10403           (void) ContrastStretchImage(image,black_point,white_point,exception);
10404           (void) SetImageChannelMask(image,channel_mask);
10405           break;
10406         }
10407         case 96:  /* Sans0 */
10408         {
10409           break;
10410         }
10411         case 97:  /* Sans1 */
10412         {
10413           break;
10414         }
10415         case 98:  /* AdaptiveSharpen */
10416         {
10417           if (attribute_flag[0] != 0)
10418             {
10419               flags=ParseGeometry(argument_list[0].string_reference,
10420                 &geometry_info);
10421               if ((flags & SigmaValue) == 0)
10422                 geometry_info.sigma=1.0;
10423               if ((flags & XiValue) == 0)
10424                 geometry_info.xi=0.0;
10425             }
10426           if (attribute_flag[1] != 0)
10427             geometry_info.rho=argument_list[1].real_reference;
10428           if (attribute_flag[2] != 0)
10429             geometry_info.sigma=argument_list[2].real_reference;
10430           if (attribute_flag[3] != 0)
10431             geometry_info.xi=argument_list[3].real_reference;
10432           if (attribute_flag[4] != 0)
10433             channel=(ChannelType) argument_list[4].integer_reference;
10434           channel_mask=SetImageChannelMask(image,channel);
10435           image=AdaptiveSharpenImage(image,geometry_info.rho,
10436             geometry_info.sigma,exception);
10437           if (image != (Image *) NULL)
10438             (void) SetImageChannelMask(image,channel_mask);
10439           break;
10440         }
10441         case 99:  /* Transpose */
10442         {
10443           image=TransposeImage(image,exception);
10444           break;
10445         }
10446         case 100:  /* Tranverse */
10447         {
10448           image=TransverseImage(image,exception);
10449           break;
10450         }
10451         case 101:  /* AutoOrient */
10452         {
10453           image=AutoOrientImage(image,image->orientation,exception);
10454           break;
10455         }
10456         case 102:  /* AdaptiveBlur */
10457         {
10458           if (attribute_flag[0] != 0)
10459             {
10460               flags=ParseGeometry(argument_list[0].string_reference,
10461                 &geometry_info);
10462               if ((flags & SigmaValue) == 0)
10463                 geometry_info.sigma=1.0;
10464               if ((flags & XiValue) == 0)
10465                 geometry_info.xi=0.0;
10466             }
10467           if (attribute_flag[1] != 0)
10468             geometry_info.rho=argument_list[1].real_reference;
10469           if (attribute_flag[2] != 0)
10470             geometry_info.sigma=argument_list[2].real_reference;
10471           if (attribute_flag[3] != 0)
10472             channel=(ChannelType) argument_list[3].integer_reference;
10473           channel_mask=SetImageChannelMask(image,channel);
10474           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10475             exception);
10476           if (image != (Image *) NULL)
10477             (void) SetImageChannelMask(image,channel_mask);
10478           break;
10479         }
10480         case 103:  /* Sketch */
10481         {
10482           if (attribute_flag[0] != 0)
10483             {
10484               flags=ParseGeometry(argument_list[0].string_reference,
10485                 &geometry_info);
10486               if ((flags & SigmaValue) == 0)
10487                 geometry_info.sigma=1.0;
10488               if ((flags & XiValue) == 0)
10489                 geometry_info.xi=1.0;
10490             }
10491           if (attribute_flag[1] != 0)
10492             geometry_info.rho=argument_list[1].real_reference;
10493           if (attribute_flag[2] != 0)
10494             geometry_info.sigma=argument_list[2].real_reference;
10495           if (attribute_flag[3] != 0)
10496             geometry_info.xi=argument_list[3].real_reference;
10497           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10498             geometry_info.xi,exception);
10499           break;
10500         }
10501         case 104:  /* UniqueColors */
10502         {
10503           image=UniqueImageColors(image,exception);
10504           break;
10505         }
10506         case 105:  /* AdaptiveResize */
10507         {
10508           if (attribute_flag[0] != 0)
10509             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10510               &geometry,exception);
10511           if (attribute_flag[1] != 0)
10512             geometry.width=argument_list[1].integer_reference;
10513           if (attribute_flag[2] != 0)
10514             geometry.height=argument_list[2].integer_reference;
10515           if (attribute_flag[3] != 0)
10516             image->filter=(FilterType) argument_list[4].integer_reference;
10517           if (attribute_flag[4] != 0)
10518             SetImageArtifact(image,"filter:support",
10519               argument_list[4].string_reference);
10520           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10521             exception);
10522           break;
10523         }
10524         case 106:  /* ClipMask */
10525         {
10526           Image
10527             *mask_image;
10528
10529           if (attribute_flag[0] == 0)
10530             {
10531               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10532                 PackageName);
10533               goto PerlException;
10534             }
10535           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10536             exception);
10537           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10538           mask_image=DestroyImage(mask_image);
10539           break;
10540         }
10541         case 107:  /* LinearStretch */
10542         {
10543            double
10544              black_point,
10545              white_point;
10546
10547            black_point=0.0;
10548            white_point=(double) image->columns*image->rows;
10549            if (attribute_flag[0] != 0)
10550              {
10551                flags=ParseGeometry(argument_list[0].string_reference,
10552                  &geometry_info);
10553                if ((flags & SigmaValue) != 0)
10554                   white_point=geometry_info.sigma;
10555                if ((flags & PercentValue) != 0)
10556                  {
10557                    black_point*=(double) image->columns*image->rows/100.0;
10558                    white_point*=(double) image->columns*image->rows/100.0;
10559                  }
10560                if ((flags & SigmaValue) == 0)
10561                  white_point=(double) image->columns*image->rows-black_point;
10562              }
10563           if (attribute_flag[1] != 0)
10564             black_point=argument_list[1].real_reference;
10565           if (attribute_flag[2] != 0)
10566             white_point=argument_list[2].real_reference;
10567           (void) LinearStretchImage(image,black_point,white_point,exception);
10568           break;
10569         }
10570         case 108:  /* ColorMatrix */
10571         {
10572           AV
10573             *av;
10574
10575           double
10576             *color_matrix;
10577
10578           KernelInfo
10579             *kernel_info;
10580
10581           size_t
10582             order;
10583
10584           if (attribute_flag[0] == 0)
10585             break;
10586           av=(AV *) argument_list[0].array_reference;
10587           order=(size_t) sqrt(av_len(av)+1);
10588           color_matrix=(double *) AcquireQuantumMemory(order,order*
10589             sizeof(*color_matrix));
10590           if (color_matrix == (double *) NULL)
10591             {
10592               ThrowPerlException(exception,ResourceLimitFatalError,
10593                 "MemoryAllocationFailed",PackageName);
10594               goto PerlException;
10595            }
10596           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10597             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10598           for ( ; j < (ssize_t) (order*order); j++)
10599             color_matrix[j]=0.0;
10600           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10601           if (kernel_info == (KernelInfo *) NULL)
10602             break;
10603           kernel_info->width=order;
10604           kernel_info->height=order;
10605           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10606             order*sizeof(*kernel_info->values));
10607           if (kernel_info->values != (MagickRealType *) NULL)
10608             {
10609               for (i=0; i < (ssize_t) (order*order); i++)
10610                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10611               image=ColorMatrixImage(image,kernel_info,exception);
10612             }
10613           kernel_info=DestroyKernelInfo(kernel_info);
10614           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10615           break;
10616         }
10617         case 109:  /* Mask */
10618         {
10619           Image
10620             *mask_image;
10621
10622           if (attribute_flag[0] == 0)
10623             {
10624               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10625                 PackageName);
10626               goto PerlException;
10627             }
10628           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10629             MagickTrue,exception);
10630           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10631           mask_image=DestroyImage(mask_image);
10632           break;
10633         }
10634         case 110:  /* Polaroid */
10635         {
10636           char
10637             *caption;
10638
10639           double
10640             angle;
10641
10642           DrawInfo
10643             *draw_info;
10644
10645           PixelInterpolateMethod
10646             method;
10647
10648           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10649             (DrawInfo *) NULL);
10650           caption=(char *) NULL;
10651           if (attribute_flag[0] != 0)
10652             caption=InterpretImageProperties(info ? info->image_info :
10653               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10654               exception);
10655           angle=0.0;
10656           if (attribute_flag[1] != 0)
10657             angle=argument_list[1].real_reference;
10658           if (attribute_flag[2] != 0)
10659             (void) CloneString(&draw_info->font,
10660               argument_list[2].string_reference);
10661           if (attribute_flag[3] != 0)
10662             (void) QueryColorCompliance(argument_list[3].string_reference,
10663               AllCompliance,&draw_info->stroke,exception);
10664           if (attribute_flag[4] != 0)
10665             (void) QueryColorCompliance(argument_list[4].string_reference,
10666               AllCompliance,&draw_info->fill,exception);
10667           if (attribute_flag[5] != 0)
10668             draw_info->stroke_width=argument_list[5].real_reference;
10669           if (attribute_flag[6] != 0)
10670             draw_info->pointsize=argument_list[6].real_reference;
10671           if (attribute_flag[7] != 0)
10672             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10673           if (attribute_flag[8] != 0)
10674             (void) QueryColorCompliance(argument_list[8].string_reference,
10675               AllCompliance,&image->background_color,exception);
10676           method=UndefinedInterpolatePixel;
10677           if (attribute_flag[9] != 0)
10678             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10679           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10680           draw_info=DestroyDrawInfo(draw_info);
10681           if (caption != (char *) NULL)
10682             caption=DestroyString(caption);
10683           break;
10684         }
10685         case 111:  /* FloodfillPaint */
10686         {
10687           DrawInfo
10688             *draw_info;
10689
10690           MagickBooleanType
10691             invert;
10692
10693           PixelInfo
10694             target;
10695
10696           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10697             (DrawInfo *) NULL);
10698           if (attribute_flag[0] != 0)
10699             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10700               &geometry,exception);
10701           if (attribute_flag[1] != 0)
10702             geometry.x=argument_list[1].integer_reference;
10703           if (attribute_flag[2] != 0)
10704             geometry.y=argument_list[2].integer_reference;
10705           if (attribute_flag[3] != 0)
10706             (void) QueryColorCompliance(argument_list[3].string_reference,
10707               AllCompliance,&draw_info->fill,exception);
10708           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10709             geometry.x,geometry.y,&target,exception);
10710           if (attribute_flag[4] != 0)
10711             QueryColorCompliance(argument_list[4].string_reference,
10712               AllCompliance,&target,exception);
10713           if (attribute_flag[5] != 0)
10714             image->fuzz=StringToDoubleInterval(
10715               argument_list[5].string_reference,(double) QuantumRange+1.0);
10716           if (attribute_flag[6] != 0)
10717             channel=(ChannelType) argument_list[6].integer_reference;
10718           invert=MagickFalse;
10719           if (attribute_flag[7] != 0)
10720             invert=(MagickBooleanType) argument_list[7].integer_reference;
10721           channel_mask=SetImageChannelMask(image,channel);
10722           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10723             geometry.y,invert,exception);
10724           (void) SetImageChannelMask(image,channel_mask);
10725           draw_info=DestroyDrawInfo(draw_info);
10726           break;
10727         }
10728         case 112:  /* Distort */
10729         {
10730           AV
10731             *av;
10732
10733           DistortMethod
10734             method;
10735
10736           double
10737             *coordinates;
10738
10739           size_t
10740             number_coordinates;
10741
10742           VirtualPixelMethod
10743             virtual_pixel;
10744
10745           if (attribute_flag[0] == 0)
10746             break;
10747           method=UndefinedDistortion;
10748           if (attribute_flag[1] != 0)
10749             method=(DistortMethod) argument_list[1].integer_reference;
10750           av=(AV *) argument_list[0].array_reference;
10751           number_coordinates=(size_t) av_len(av)+1;
10752           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10753             sizeof(*coordinates));
10754           if (coordinates == (double *) NULL)
10755             {
10756               ThrowPerlException(exception,ResourceLimitFatalError,
10757                 "MemoryAllocationFailed",PackageName);
10758               goto PerlException;
10759             }
10760           for (j=0; j < (ssize_t) number_coordinates; j++)
10761             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10762           virtual_pixel=UndefinedVirtualPixelMethod;
10763           if (attribute_flag[2] != 0)
10764             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10765               argument_list[2].integer_reference,exception);
10766           image=DistortImage(image,method,number_coordinates,coordinates,
10767             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10768             exception);
10769           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10770             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10771               exception);
10772           coordinates=(double *) RelinquishMagickMemory(coordinates);
10773           break;
10774         }
10775         case 113:  /* Clut */
10776         {
10777           PixelInterpolateMethod
10778             method;
10779
10780           if (attribute_flag[0] == 0)
10781             {
10782               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10783                 PackageName);
10784               goto PerlException;
10785             }
10786           method=UndefinedInterpolatePixel;
10787           if (attribute_flag[1] != 0)
10788             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10789           if (attribute_flag[2] != 0)
10790             channel=(ChannelType) argument_list[2].integer_reference;
10791           channel_mask=SetImageChannelMask(image,channel);
10792           (void) ClutImage(image,argument_list[0].image_reference,method,
10793             exception);
10794           (void) SetImageChannelMask(image,channel_mask);
10795           break;
10796         }
10797         case 114:  /* LiquidRescale */
10798         {
10799           if (attribute_flag[0] != 0)
10800             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10801               &geometry,exception);
10802           if (attribute_flag[1] != 0)
10803             geometry.width=argument_list[1].integer_reference;
10804           if (attribute_flag[2] != 0)
10805             geometry.height=argument_list[2].integer_reference;
10806           if (attribute_flag[3] == 0)
10807             argument_list[3].real_reference=1.0;
10808           if (attribute_flag[4] == 0)
10809             argument_list[4].real_reference=0.0;
10810           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10811             argument_list[3].real_reference,argument_list[4].real_reference,
10812             exception);
10813           break;
10814         }
10815         case 115:  /* EncipherImage */
10816         {
10817           (void) EncipherImage(image,argument_list[0].string_reference,
10818             exception);
10819           break;
10820         }
10821         case 116:  /* DecipherImage */
10822         {
10823           (void) DecipherImage(image,argument_list[0].string_reference,
10824             exception);
10825           break;
10826         }
10827         case 117:  /* Deskew */
10828         {
10829           geometry_info.rho=QuantumRange/2.0;
10830           if (attribute_flag[0] != 0)
10831             flags=ParseGeometry(argument_list[0].string_reference,
10832               &geometry_info);
10833           if (attribute_flag[1] != 0)
10834             geometry_info.rho=StringToDoubleInterval(
10835               argument_list[1].string_reference,(double) QuantumRange+1.0);
10836           image=DeskewImage(image,geometry_info.rho,exception);
10837           break;
10838         }
10839         case 118:  /* Remap */
10840         {
10841           QuantizeInfo
10842             *quantize_info;
10843
10844           if (attribute_flag[0] == 0)
10845             {
10846               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10847                 PackageName);
10848               goto PerlException;
10849             }
10850           quantize_info=AcquireQuantizeInfo(info->image_info);
10851           if (attribute_flag[1] != 0)
10852             quantize_info->dither_method=(DitherMethod)
10853               argument_list[1].integer_reference;
10854           (void) RemapImages(quantize_info,image,
10855             argument_list[0].image_reference,exception);
10856           quantize_info=DestroyQuantizeInfo(quantize_info);
10857           break;
10858         }
10859         case 119:  /* SparseColor */
10860         {
10861           AV
10862             *av;
10863
10864           double
10865             *coordinates;
10866
10867           size_t
10868             number_coordinates;
10869
10870           SparseColorMethod
10871             method;
10872
10873           VirtualPixelMethod
10874             virtual_pixel;
10875
10876           if (attribute_flag[0] == 0)
10877             break;
10878           method=UndefinedColorInterpolate;
10879           if (attribute_flag[1] != 0)
10880             method=(SparseColorMethod) argument_list[1].integer_reference;
10881           av=(AV *) argument_list[0].array_reference;
10882           number_coordinates=(size_t) av_len(av)+1;
10883           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10884             sizeof(*coordinates));
10885           if (coordinates == (double *) NULL)
10886             {
10887               ThrowPerlException(exception,ResourceLimitFatalError,
10888                 "MemoryAllocationFailed",PackageName);
10889               goto PerlException;
10890             }
10891           for (j=0; j < (ssize_t) number_coordinates; j++)
10892             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10893           virtual_pixel=UndefinedVirtualPixelMethod;
10894           if (attribute_flag[2] != 0)
10895             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10896               argument_list[2].integer_reference,exception);
10897           if (attribute_flag[3] != 0)
10898             channel=(ChannelType) argument_list[3].integer_reference;
10899           channel_mask=SetImageChannelMask(image,channel);
10900           image=SparseColorImage(image,method,number_coordinates,coordinates,
10901             exception);
10902           if (image != (Image *) NULL)
10903             (void) SetImageChannelMask(image,channel_mask);
10904           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10905             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10906               exception);
10907           coordinates=(double *) RelinquishMagickMemory(coordinates);
10908           break;
10909         }
10910         case 120:  /* Function */
10911         {
10912           AV
10913             *av;
10914
10915           double
10916             *parameters;
10917
10918           MagickFunction
10919             function;
10920
10921           size_t
10922             number_parameters;
10923
10924           VirtualPixelMethod
10925             virtual_pixel;
10926
10927           if (attribute_flag[0] == 0)
10928             break;
10929           function=UndefinedFunction;
10930           if (attribute_flag[1] != 0)
10931             function=(MagickFunction) argument_list[1].integer_reference;
10932           av=(AV *) argument_list[0].array_reference;
10933           number_parameters=(size_t) av_len(av)+1;
10934           parameters=(double *) AcquireQuantumMemory(number_parameters,
10935             sizeof(*parameters));
10936           if (parameters == (double *) NULL)
10937             {
10938               ThrowPerlException(exception,ResourceLimitFatalError,
10939                 "MemoryAllocationFailed",PackageName);
10940               goto PerlException;
10941             }
10942           for (j=0; j < (ssize_t) number_parameters; j++)
10943             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10944           virtual_pixel=UndefinedVirtualPixelMethod;
10945           if (attribute_flag[2] != 0)
10946             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10947               argument_list[2].integer_reference,exception);
10948           (void) FunctionImage(image,function,number_parameters,parameters,
10949             exception);
10950           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10951             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10952               exception);
10953           parameters=(double *) RelinquishMagickMemory(parameters);
10954           break;
10955         }
10956         case 121:  /* SelectiveBlur */
10957         {
10958           if (attribute_flag[0] != 0)
10959             {
10960               flags=ParseGeometry(argument_list[0].string_reference,
10961                 &geometry_info);
10962               if ((flags & SigmaValue) == 0)
10963                 geometry_info.sigma=1.0;
10964               if ((flags & PercentValue) != 0)
10965                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10966             }
10967           if (attribute_flag[1] != 0)
10968             geometry_info.rho=argument_list[1].real_reference;
10969           if (attribute_flag[2] != 0)
10970             geometry_info.sigma=argument_list[2].real_reference;
10971           if (attribute_flag[3] != 0)
10972             geometry_info.xi=argument_list[3].integer_reference;;
10973           if (attribute_flag[5] != 0)
10974             channel=(ChannelType) argument_list[5].integer_reference;
10975           channel_mask=SetImageChannelMask(image,channel);
10976           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10977             geometry_info.xi,exception);
10978           if (image != (Image *) NULL)
10979             (void) SetImageChannelMask(image,channel_mask);
10980           break;
10981         }
10982         case 122:  /* HaldClut */
10983         {
10984           if (attribute_flag[0] == 0)
10985             {
10986               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10987                 PackageName);
10988               goto PerlException;
10989             }
10990           if (attribute_flag[1] != 0)
10991             channel=(ChannelType) argument_list[1].integer_reference;
10992           channel_mask=SetImageChannelMask(image,channel);
10993           (void) HaldClutImage(image,argument_list[0].image_reference,
10994             exception);
10995           (void) SetImageChannelMask(image,channel_mask);
10996           break;
10997         }
10998         case 123:  /* BlueShift */
10999         {
11000           if (attribute_flag[0] != 0)
11001             (void) ParseGeometry(argument_list[0].string_reference,
11002               &geometry_info);
11003           image=BlueShiftImage(image,geometry_info.rho,exception);
11004           break;
11005         }
11006         case 124:  /* ForwardFourierTransformImage */
11007         {
11008           image=ForwardFourierTransformImage(image,
11009             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11010             exception);
11011           break;
11012         }
11013         case 125:  /* InverseFourierTransformImage */
11014         {
11015           image=InverseFourierTransformImage(image,image->next,
11016             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11017             exception);
11018           break;
11019         }
11020         case 126:  /* ColorDecisionList */
11021         {
11022           if (attribute_flag[0] == 0)
11023             argument_list[0].string_reference=(char *) NULL;
11024           (void) ColorDecisionListImage(image,
11025             argument_list[0].string_reference,exception);
11026           break;
11027         }
11028         case 127:  /* AutoGamma */
11029         {
11030           if (attribute_flag[0] != 0)
11031             channel=(ChannelType) argument_list[0].integer_reference;
11032           channel_mask=SetImageChannelMask(image,channel);
11033           (void) AutoGammaImage(image,exception);
11034           (void) SetImageChannelMask(image,channel_mask);
11035           break;
11036         }
11037         case 128:  /* AutoLevel */
11038         {
11039           if (attribute_flag[0] != 0)
11040             channel=(ChannelType) argument_list[0].integer_reference;
11041           channel_mask=SetImageChannelMask(image,channel);
11042           (void) AutoLevelImage(image,exception);
11043           (void) SetImageChannelMask(image,channel_mask);
11044           break;
11045         }
11046         case 129:  /* LevelColors */
11047         {
11048           PixelInfo
11049             black_point,
11050             white_point;
11051
11052           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
11053             exception);
11054           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
11055             exception);
11056           if (attribute_flag[1] != 0)
11057              (void) QueryColorCompliance(
11058                argument_list[1].string_reference,AllCompliance,&black_point,
11059                exception);
11060           if (attribute_flag[2] != 0)
11061              (void) QueryColorCompliance(
11062                argument_list[2].string_reference,AllCompliance,&white_point,
11063                exception);
11064           if (attribute_flag[3] != 0)
11065             channel=(ChannelType) argument_list[3].integer_reference;
11066           channel_mask=SetImageChannelMask(image,channel);
11067           (void) LevelImageColors(image,&black_point,&white_point,
11068             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
11069             exception);
11070           (void) SetImageChannelMask(image,channel_mask);
11071           break;
11072         }
11073         case 130:  /* Clamp */
11074         {
11075           if (attribute_flag[0] != 0)
11076             channel=(ChannelType) argument_list[0].integer_reference;
11077           channel_mask=SetImageChannelMask(image,channel);
11078           (void) ClampImage(image,exception);
11079           (void) SetImageChannelMask(image,channel_mask);
11080           break;
11081         }
11082         case 131:  /* BrightnessContrast */
11083         {
11084           double
11085             brightness,
11086             contrast;
11087
11088           brightness=0.0;
11089           contrast=0.0;
11090           if (attribute_flag[0] != 0)
11091             {
11092               flags=ParseGeometry(argument_list[0].string_reference,
11093                 &geometry_info);
11094               brightness=geometry_info.rho;
11095               if ((flags & SigmaValue) == 0)
11096                 contrast=geometry_info.sigma;
11097             }
11098           if (attribute_flag[1] != 0)
11099             brightness=argument_list[1].real_reference;
11100           if (attribute_flag[2] != 0)
11101             contrast=argument_list[2].real_reference;
11102           if (attribute_flag[4] != 0)
11103             channel=(ChannelType) argument_list[4].integer_reference;
11104           channel_mask=SetImageChannelMask(image,channel);
11105           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11106           (void) SetImageChannelMask(image,channel_mask);
11107           break;
11108         }
11109         case 132:  /* Morphology */
11110         {
11111           KernelInfo
11112             *kernel;
11113
11114           MorphologyMethod
11115             method;
11116
11117           ssize_t
11118             iterations;
11119
11120           if (attribute_flag[0] == 0)
11121             break;
11122           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11123           if (kernel == (KernelInfo *) NULL)
11124             break;
11125           if (attribute_flag[1] != 0)
11126             channel=(ChannelType) argument_list[1].integer_reference;
11127           method=UndefinedMorphology;
11128           if (attribute_flag[2] != 0)
11129             method=argument_list[2].integer_reference;
11130           iterations=1;
11131           if (attribute_flag[3] != 0)
11132             iterations=argument_list[3].integer_reference;
11133           channel_mask=SetImageChannelMask(image,channel);
11134           image=MorphologyImage(image,method,iterations,kernel,exception);
11135           if (image != (Image *) NULL)
11136             (void) SetImageChannelMask(image,channel_mask);
11137           kernel=DestroyKernelInfo(kernel);
11138           break;
11139         }
11140         case 133:  /* Mode */
11141         {
11142           if (attribute_flag[0] != 0)
11143             {
11144               flags=ParseGeometry(argument_list[0].string_reference,
11145                 &geometry_info);
11146               if ((flags & SigmaValue) == 0)
11147                 geometry_info.sigma=1.0;
11148             }
11149           if (attribute_flag[1] != 0)
11150             geometry_info.rho=argument_list[1].real_reference;
11151           if (attribute_flag[2] != 0)
11152             geometry_info.sigma=argument_list[2].real_reference;
11153           if (attribute_flag[3] != 0)
11154             channel=(ChannelType) argument_list[3].integer_reference;
11155           channel_mask=SetImageChannelMask(image,channel);
11156           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11157             (size_t) geometry_info.sigma,exception);
11158           if (image != (Image *) NULL)
11159             (void) SetImageChannelMask(image,channel_mask);
11160           break;
11161         }
11162         case 134:  /* Statistic */
11163         {
11164           StatisticType
11165             statistic;
11166
11167           statistic=UndefinedStatistic;
11168           if (attribute_flag[0] != 0)
11169             {
11170               flags=ParseGeometry(argument_list[0].string_reference,
11171                 &geometry_info);
11172               if ((flags & SigmaValue) == 0)
11173                 geometry_info.sigma=1.0;
11174             }
11175           if (attribute_flag[1] != 0)
11176             geometry_info.rho=argument_list[1].real_reference;
11177           if (attribute_flag[2] != 0)
11178             geometry_info.sigma=argument_list[2].real_reference;
11179           if (attribute_flag[3] != 0)
11180             channel=(ChannelType) argument_list[3].integer_reference;
11181           if (attribute_flag[4] != 0)
11182             statistic=(StatisticType) argument_list[4].integer_reference;
11183           channel_mask=SetImageChannelMask(image,channel);
11184           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11185             (size_t) geometry_info.sigma,exception);
11186           if (image != (Image *) NULL)
11187             (void) SetImageChannelMask(image,channel_mask);
11188           break;
11189         }
11190         case 135:  /* Perceptible */
11191         {
11192           double
11193             epsilon;
11194
11195           epsilon=MagickEpsilon;
11196           if (attribute_flag[0] != 0)
11197             epsilon=argument_list[0].real_reference;
11198           if (attribute_flag[1] != 0)
11199             channel=(ChannelType) argument_list[1].integer_reference;
11200           channel_mask=SetImageChannelMask(image,channel);
11201           (void) PerceptibleImage(image,epsilon,exception);
11202           (void) SetImageChannelMask(image,channel_mask);
11203           break;
11204         }
11205         case 136:  /* Poly */
11206         {
11207           AV
11208             *av;
11209
11210           double
11211             *terms;
11212
11213           size_t
11214             number_terms;
11215
11216           if (attribute_flag[0] == 0)
11217             break;
11218           if (attribute_flag[1] != 0)
11219             channel=(ChannelType) argument_list[1].integer_reference;
11220           av=(AV *) argument_list[0].array_reference;
11221           number_terms=(size_t) av_len(av);
11222           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11223           if (terms == (double *) NULL)
11224             {
11225               ThrowPerlException(exception,ResourceLimitFatalError,
11226                 "MemoryAllocationFailed",PackageName);
11227               goto PerlException;
11228             }
11229           for (j=0; j < av_len(av); j++)
11230             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11231           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11232           terms=(double *) RelinquishMagickMemory(terms);
11233           break;
11234         }
11235         case 137:  /* Grayscale */
11236         {
11237           PixelIntensityMethod
11238             method;
11239
11240           method=UndefinedPixelIntensityMethod;
11241           if (attribute_flag[0] != 0)
11242             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11243           (void) GrayscaleImage(image,method,exception);
11244           break;
11245         }
11246         case 138:  /* Canny */
11247         {
11248           if (attribute_flag[0] != 0)
11249             {
11250               flags=ParseGeometry(argument_list[0].string_reference,
11251                 &geometry_info);
11252               if ((flags & SigmaValue) == 0)
11253                 geometry_info.sigma=1.0;
11254               if ((flags & XiValue) == 0)
11255                 geometry_info.xi=0.10;
11256               if ((flags & PsiValue) == 0)
11257                 geometry_info.psi=0.30;
11258               if ((flags & PercentValue) != 0)
11259                 {
11260                   geometry_info.xi/=100.0;
11261                   geometry_info.psi/=100.0;
11262                 }
11263             }
11264           if (attribute_flag[1] != 0)
11265             geometry_info.rho=argument_list[1].real_reference;
11266           if (attribute_flag[2] != 0)
11267             geometry_info.sigma=argument_list[2].real_reference;
11268           if (attribute_flag[3] != 0)
11269             geometry_info.xi=argument_list[3].real_reference;
11270           if (attribute_flag[4] != 0)
11271             geometry_info.psi=argument_list[4].real_reference;
11272           if (attribute_flag[5] != 0)
11273             channel=(ChannelType) argument_list[5].integer_reference;
11274           channel_mask=SetImageChannelMask(image,channel);
11275           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11276             geometry_info.xi,geometry_info.psi,exception);
11277           if (image != (Image *) NULL)
11278             (void) SetImageChannelMask(image,channel_mask);
11279           break;
11280         }
11281         case 139:  /* HoughLine */
11282         {
11283           if (attribute_flag[0] != 0)
11284             {
11285               flags=ParseGeometry(argument_list[0].string_reference,
11286                 &geometry_info);
11287               if ((flags & SigmaValue) == 0)
11288                 geometry_info.sigma=geometry_info.rho;
11289               if ((flags & XiValue) == 0)
11290                 geometry_info.xi=40;
11291             }
11292           if (attribute_flag[1] != 0)
11293             geometry_info.rho=(double) argument_list[1].integer_reference;
11294           if (attribute_flag[2] != 0)
11295             geometry_info.sigma=(double) argument_list[2].integer_reference;
11296           if (attribute_flag[3] != 0)
11297             geometry_info.xi=(double) argument_list[3].integer_reference;
11298           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11299             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11300           break;
11301         }
11302         case 140:  /* MeanShift */
11303         {
11304           if (attribute_flag[0] != 0)
11305             {
11306               flags=ParseGeometry(argument_list[0].string_reference,
11307                 &geometry_info);
11308               if ((flags & SigmaValue) == 0)
11309                 geometry_info.sigma=geometry_info.rho;
11310               if ((flags & XiValue) == 0)
11311                 geometry_info.xi=0.10*QuantumRange;
11312               if ((flags & PercentValue) != 0)
11313                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11314             }
11315           if (attribute_flag[1] != 0)
11316             geometry_info.rho=(double) argument_list[1].integer_reference;
11317           if (attribute_flag[2] != 0)
11318             geometry_info.sigma=(double) argument_list[2].integer_reference;
11319           if (attribute_flag[3] != 0)
11320             geometry_info.xi=(double) argument_list[3].integer_reference;
11321           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11322             geometry_info.sigma,geometry_info.xi,exception);
11323           break;
11324         }
11325         case 141:  /* Kuwahara */
11326         {
11327           if (attribute_flag[0] != 0)
11328             {
11329               flags=ParseGeometry(argument_list[0].string_reference,
11330                 &geometry_info);
11331               if ((flags & SigmaValue) == 0)
11332                 geometry_info.sigma=geometry_info.rho-0.5;
11333             }
11334           if (attribute_flag[1] != 0)
11335             geometry_info.rho=argument_list[1].real_reference;
11336           if (attribute_flag[2] != 0)
11337             geometry_info.sigma=argument_list[2].real_reference;
11338           if (attribute_flag[3] != 0)
11339             channel=(ChannelType) argument_list[3].integer_reference;
11340           channel_mask=SetImageChannelMask(image,channel);
11341           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11342             exception);
11343           if (image != (Image *) NULL)
11344             (void) SetImageChannelMask(image,channel_mask);
11345           break;
11346         }
11347         case 142:  /* ConnectedComponents */
11348         {
11349           size_t
11350             connectivity;
11351
11352           connectivity=4;
11353           if (attribute_flag[0] != 0)
11354             connectivity=argument_list[0].integer_reference;
11355           image=ConnectedComponentsImage(image,connectivity,
11356             (CCObjectInfo **) NULL,exception);
11357           break;
11358         }
11359         case 143:  /* Copy */
11360         {
11361           Image
11362             *source_image;
11363
11364           OffsetInfo
11365             offset;
11366
11367           RectangleInfo
11368             offset_geometry;
11369
11370           source_image=image;
11371           if (attribute_flag[0] != 0)
11372             source_image=argument_list[0].image_reference;
11373           SetGeometry(source_image,&geometry);
11374           if (attribute_flag[1] != 0)
11375             flags=ParseGravityGeometry(source_image,
11376               argument_list[1].string_reference,&geometry,exception);
11377           if (attribute_flag[2] != 0)
11378             geometry.width=argument_list[2].integer_reference;
11379           if (attribute_flag[3] != 0)
11380             geometry.height=argument_list[3].integer_reference;
11381           if (attribute_flag[4] != 0)
11382             geometry.x=argument_list[4].integer_reference;
11383           if (attribute_flag[5] != 0)
11384             geometry.y=argument_list[5].integer_reference;
11385           if (attribute_flag[6] != 0)
11386             image->gravity=(GravityType) argument_list[6].integer_reference;
11387           SetGeometry(image,&offset_geometry);
11388           if (attribute_flag[7] != 0)
11389             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11390               &offset_geometry,exception);
11391           offset.x=offset_geometry.x;
11392           offset.y=offset_geometry.y;
11393           if (attribute_flag[8] != 0)
11394             offset.x=argument_list[8].integer_reference;
11395           if (attribute_flag[9] != 0)
11396             offset.y=argument_list[9].integer_reference;
11397           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11398             exception);
11399           break;
11400         }
11401         case 144:  /* Color */
11402         {
11403           PixelInfo
11404             color;
11405
11406           (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11407           if (attribute_flag[0] != 0)
11408             (void) QueryColorCompliance(argument_list[0].string_reference,
11409               AllCompliance,&color,exception);
11410           (void) SetImageColor(image,&color,exception);
11411           break;
11412         }
11413         case 145:  /* WaveletDenoise */
11414         {
11415           if (attribute_flag[0] != 0)
11416             {
11417               flags=ParseGeometry(argument_list[0].string_reference,
11418                 &geometry_info);
11419               if ((flags & PercentValue) != 0)
11420                 {
11421                   geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11422                   geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11423                 }
11424               if ((flags & SigmaValue) == 0)
11425                 geometry_info.sigma=0.0;
11426             }
11427           if (attribute_flag[1] != 0)
11428             geometry_info.rho=argument_list[1].real_reference;
11429           if (attribute_flag[2] != 0)
11430             geometry_info.sigma=argument_list[2].real_reference;
11431           if (attribute_flag[3] != 0)
11432             channel=(ChannelType) argument_list[3].integer_reference;
11433           channel_mask=SetImageChannelMask(image,channel);
11434           image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11435             exception);
11436           if (image != (Image *) NULL)
11437             (void) SetImageChannelMask(image,channel_mask);
11438           break;
11439         }
11440         case 146:  /* Colorspace */
11441         {
11442           ColorspaceType
11443             colorspace;
11444
11445           colorspace=sRGBColorspace;
11446           if (attribute_flag[0] != 0)
11447             colorspace=(ColorspaceType) argument_list[0].integer_reference;
11448           (void) TransformImageColorspace(image,colorspace,exception);
11449           break;
11450         }
11451         case 147:  /* AutoThreshold */
11452         {
11453           AutoThresholdMethod
11454             method;
11455
11456           method=UndefinedThresholdMethod;
11457           if (attribute_flag[0] != 0)
11458             method=(AutoThresholdMethod) argument_list[0].integer_reference;
11459           (void) AutoThresholdImage(image,method,exception);
11460           break;
11461         }
11462         case 148:  /* RangeThreshold */
11463         {
11464           if (attribute_flag[0] != 0)
11465             {
11466               flags=ParseGeometry(argument_list[0].string_reference,
11467                 &geometry_info);
11468               if ((flags & SigmaValue) == 0)
11469                 geometry_info.sigma=geometry_info.rho;
11470               if ((flags & XiValue) == 0)
11471                 geometry_info.xi=geometry_info.sigma;
11472               if ((flags & PsiValue) == 0)
11473                 geometry_info.psi=geometry_info.xi;
11474             }
11475           if (attribute_flag[1] != 0)
11476             geometry_info.rho=argument_list[1].real_reference;
11477           if (attribute_flag[2] != 0)
11478             geometry_info.sigma=argument_list[2].real_reference;
11479           if (attribute_flag[3] != 0)
11480             geometry_info.xi=argument_list[3].real_reference;
11481           if (attribute_flag[4] != 0)
11482             geometry_info.psi=argument_list[4].real_reference;
11483           if (attribute_flag[5] != 0)
11484             channel=(ChannelType) argument_list[5].integer_reference;
11485           channel_mask=SetImageChannelMask(image,channel);
11486           (void) RangeThresholdImage(image,geometry_info.rho,
11487             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
11488           if (image != (Image *) NULL)
11489             (void) SetImageChannelMask(image,channel_mask);
11490           break;
11491         }
11492         case 149:  /* CLAHE */
11493         {
11494           if (attribute_flag[0] != 0)
11495             {
11496               flags=ParseGeometry(argument_list[0].string_reference,
11497                 &geometry_info);
11498               flags=ParseRegionGeometry(image,argument_list[0].string_reference,
11499                 &geometry,exception);
11500             }
11501           if (attribute_flag[1] != 0)
11502             geometry.width=argument_list[1].integer_reference;
11503           if (attribute_flag[2] != 0)
11504             geometry.height=argument_list[2].integer_reference;
11505           if (attribute_flag[3] != 0)
11506             geometry.x=argument_list[3].integer_reference;
11507           if (attribute_flag[4] != 0)
11508             geometry_info.psi=argument_list[4].real_reference;
11509           (void) CLAHEImage(image,geometry.width,geometry.height,geometry.x,
11510             geometry_info.psi,exception);
11511           break;
11512         }
11513         case 150:  /* OTSUThreshold */
11514         {
11515           if (attribute_flag[0] != 0)
11516             channel=(ChannelType) argument_list[0].integer_reference;
11517           channel_mask=SetImageChannelMask(image,channel);
11518           (void) OTSUThresholdImage(image,exception);
11519           if (image != (Image *) NULL)
11520             (void) SetImageChannelMask(image,channel_mask);
11521           break;
11522         }
11523       }
11524       if (next != (Image *) NULL)
11525         (void) CatchImageException(next);
11526       if ((region_info.width*region_info.height) != 0)
11527         (void) SetImageRegionMask(image,WritePixelMask,(const RectangleInfo *)
11528           NULL,exception);
11529       if (image != (Image *) NULL)
11530         {
11531           number_images++;
11532           if (next && (next != image))
11533             {
11534               image->next=next->next;
11535               if (image->next != (Image *) NULL)
11536                 image->next->previous=image;
11537               DeleteImageFromRegistry(*pv,next);
11538             }
11539           sv_setiv(*pv,PTR2IV(image));
11540           next=image;
11541         }
11542       if (*pv)
11543         pv++;
11544     }
11545
11546   PerlException:
11547     if (reference_vector)
11548       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11549     InheritPerlException(exception,perl_exception);
11550     exception=DestroyExceptionInfo(exception);
11551     sv_setiv(perl_exception,(IV) number_images);
11552     SvPOK_on(perl_exception);
11553     ST(0)=sv_2mortal(perl_exception);
11554     XSRETURN(1);
11555   }
11556 \f
11557 #
11558 ###############################################################################
11559 #                                                                             #
11560 #                                                                             #
11561 #                                                                             #
11562 #   M o n t a g e                                                             #
11563 #                                                                             #
11564 #                                                                             #
11565 #                                                                             #
11566 ###############################################################################
11567 #
11568 #
11569 void
11570 Montage(ref,...)
11571   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11572   ALIAS:
11573     MontageImage  = 1
11574     montage       = 2
11575     montageimage  = 3
11576   PPCODE:
11577   {
11578     AV
11579       *av;
11580
11581     char
11582       *attribute;
11583
11584     ExceptionInfo
11585       *exception;
11586
11587     HV
11588       *hv;
11589
11590     Image
11591       *image,
11592       *next;
11593
11594     MontageInfo
11595       *montage_info;
11596
11597     PixelInfo
11598       transparent_color;
11599
11600     register ssize_t
11601       i;
11602
11603     ssize_t
11604       sp;
11605
11606     struct PackageInfo
11607       *info;
11608
11609     SV
11610       *av_reference,
11611       *perl_exception,
11612       *reference,
11613       *rv,
11614       *sv;
11615
11616     PERL_UNUSED_VAR(ref);
11617     PERL_UNUSED_VAR(ix);
11618     exception=AcquireExceptionInfo();
11619     perl_exception=newSVpv("",0);
11620     sv=NULL;
11621     attribute=NULL;
11622     if (sv_isobject(ST(0)) == 0)
11623       {
11624         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11625           PackageName);
11626         goto PerlException;
11627       }
11628     reference=SvRV(ST(0));
11629     hv=SvSTASH(reference);
11630     av=newAV();
11631     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11632     SvREFCNT_dec(av);
11633     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11634     if (image == (Image *) NULL)
11635       {
11636         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11637           PackageName);
11638         goto PerlException;
11639       }
11640     /*
11641       Get options.
11642     */
11643     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11644     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11645     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11646       exception);
11647     for (i=2; i < items; i+=2)
11648     {
11649       attribute=(char *) SvPV(ST(i-1),na);
11650       switch (*attribute)
11651       {
11652         case 'B':
11653         case 'b':
11654         {
11655           if (LocaleCompare(attribute,"background") == 0)
11656             {
11657               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11658                 &montage_info->background_color,exception);
11659               for (next=image; next; next=next->next)
11660                 next->background_color=montage_info->background_color;
11661               break;
11662             }
11663           if (LocaleCompare(attribute,"border") == 0)
11664             {
11665               montage_info->border_width=SvIV(ST(i));
11666               break;
11667             }
11668           if (LocaleCompare(attribute,"bordercolor") == 0)
11669             {
11670               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11671                 &montage_info->border_color,exception);
11672               for (next=image; next; next=next->next)
11673                 next->border_color=montage_info->border_color;
11674               break;
11675             }
11676           if (LocaleCompare(attribute,"borderwidth") == 0)
11677             {
11678               montage_info->border_width=SvIV(ST(i));
11679               break;
11680             }
11681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11682             attribute);
11683           break;
11684         }
11685         case 'C':
11686         case 'c':
11687         {
11688           if (LocaleCompare(attribute,"compose") == 0)
11689             {
11690               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11691                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11692               if (sp < 0)
11693                 {
11694                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11695                     SvPV(ST(i),na));
11696                   break;
11697                 }
11698               for (next=image; next; next=next->next)
11699                 next->compose=(CompositeOperator) sp;
11700               break;
11701             }
11702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11703             attribute);
11704           break;
11705         }
11706         case 'F':
11707         case 'f':
11708         {
11709           if (LocaleCompare(attribute,"fill") == 0)
11710             {
11711               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11712                 &montage_info->fill,exception);
11713               break;
11714             }
11715           if (LocaleCompare(attribute,"font") == 0)
11716             {
11717               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11718               break;
11719             }
11720           if (LocaleCompare(attribute,"frame") == 0)
11721             {
11722               char
11723                 *p;
11724
11725               p=SvPV(ST(i),na);
11726               if (IsGeometry(p) == MagickFalse)
11727                 {
11728                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11729                     p);
11730                   break;
11731                 }
11732               (void) CloneString(&montage_info->frame,p);
11733               if (*p == '\0')
11734                 montage_info->frame=(char *) NULL;
11735               break;
11736             }
11737           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11738             attribute);
11739           break;
11740         }
11741         case 'G':
11742         case 'g':
11743         {
11744           if (LocaleCompare(attribute,"geometry") == 0)
11745             {
11746               char
11747                 *p;
11748
11749               p=SvPV(ST(i),na);
11750               if (IsGeometry(p) == MagickFalse)
11751                 {
11752                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11753                     p);
11754                   break;
11755                 }
11756              (void) CloneString(&montage_info->geometry,p);
11757              if (*p == '\0')
11758                montage_info->geometry=(char *) NULL;
11759              break;
11760            }
11761          if (LocaleCompare(attribute,"gravity") == 0)
11762            {
11763              ssize_t
11764                in;
11765
11766              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11767                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11768              if (in < 0)
11769                {
11770                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11771                    SvPV(ST(i),na));
11772                  return;
11773                }
11774              montage_info->gravity=(GravityType) in;
11775              for (next=image; next; next=next->next)
11776                next->gravity=(GravityType) in;
11777              break;
11778            }
11779           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11780             attribute);
11781           break;
11782         }
11783         case 'L':
11784         case 'l':
11785         {
11786           if (LocaleCompare(attribute,"label") == 0)
11787             {
11788               for (next=image; next; next=next->next)
11789                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11790                   info ? info->image_info : (ImageInfo *) NULL,next,
11791                   SvPV(ST(i),na),exception),exception);
11792               break;
11793             }
11794           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11795             attribute);
11796           break;
11797         }
11798         case 'M':
11799         case 'm':
11800         {
11801           if (LocaleCompare(attribute,"mattecolor") == 0)
11802             {
11803               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11804                 &montage_info->alpha_color,exception);
11805               for (next=image; next; next=next->next)
11806                 next->alpha_color=montage_info->alpha_color;
11807               break;
11808             }
11809           if (LocaleCompare(attribute,"mode") == 0)
11810             {
11811               ssize_t
11812                 in;
11813
11814               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11815                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11816               switch (in)
11817               {
11818                 default:
11819                 {
11820                   ThrowPerlException(exception,OptionError,
11821                     "UnrecognizedModeType",SvPV(ST(i),na));
11822                   break;
11823                 }
11824                 case FrameMode:
11825                 {
11826                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11827                   montage_info->shadow=MagickTrue;
11828                   break;
11829                 }
11830                 case UnframeMode:
11831                 {
11832                   montage_info->frame=(char *) NULL;
11833                   montage_info->shadow=MagickFalse;
11834                   montage_info->border_width=0;
11835                   break;
11836                 }
11837                 case ConcatenateMode:
11838                 {
11839                   montage_info->frame=(char *) NULL;
11840                   montage_info->shadow=MagickFalse;
11841                   (void) CloneString(&montage_info->geometry,"+0+0");
11842                   montage_info->border_width=0;
11843                 }
11844               }
11845               break;
11846             }
11847           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11848             attribute);
11849           break;
11850         }
11851         case 'P':
11852         case 'p':
11853         {
11854           if (LocaleCompare(attribute,"pointsize") == 0)
11855             {
11856               montage_info->pointsize=SvIV(ST(i));
11857               break;
11858             }
11859           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11860             attribute);
11861           break;
11862         }
11863         case 'S':
11864         case 's':
11865         {
11866           if (LocaleCompare(attribute,"shadow") == 0)
11867             {
11868               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11869                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11870               if (sp < 0)
11871                 {
11872                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11873                     SvPV(ST(i),na));
11874                   break;
11875                 }
11876              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11877              break;
11878             }
11879           if (LocaleCompare(attribute,"stroke") == 0)
11880             {
11881               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11882                 &montage_info->stroke,exception);
11883               break;
11884             }
11885           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11886             attribute);
11887           break;
11888         }
11889         case 'T':
11890         case 't':
11891         {
11892           if (LocaleCompare(attribute,"texture") == 0)
11893             {
11894               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11895               break;
11896             }
11897           if (LocaleCompare(attribute,"tile") == 0)
11898             {
11899               char *p=SvPV(ST(i),na);
11900               if (IsGeometry(p) == MagickFalse)
11901                 {
11902                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11903                     p);
11904                   break;
11905                 }
11906               (void) CloneString(&montage_info->tile,p);
11907               if (*p == '\0')
11908                 montage_info->tile=(char *) NULL;
11909               break;
11910             }
11911           if (LocaleCompare(attribute,"title") == 0)
11912             {
11913               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11914               break;
11915             }
11916           if (LocaleCompare(attribute,"transparent") == 0)
11917             {
11918               PixelInfo
11919                 transparent_color;
11920
11921               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11922                 &transparent_color,exception);
11923               for (next=image; next; next=next->next)
11924                 (void) TransparentPaintImage(next,&transparent_color,
11925                   TransparentAlpha,MagickFalse,exception);
11926               break;
11927             }
11928           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11929             attribute);
11930           break;
11931         }
11932         default:
11933         {
11934           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11935             attribute);
11936           break;
11937         }
11938       }
11939     }
11940     image=MontageImageList(info->image_info,montage_info,image,exception);
11941     montage_info=DestroyMontageInfo(montage_info);
11942     if (image == (Image *) NULL)
11943       goto PerlException;
11944     if (transparent_color.alpha != TransparentAlpha)
11945       for (next=image; next; next=next->next)
11946         (void) TransparentPaintImage(next,&transparent_color,
11947           TransparentAlpha,MagickFalse,exception);
11948     for (  ; image; image=image->next)
11949     {
11950       AddImageToRegistry(sv,image);
11951       rv=newRV(sv);
11952       av_push(av,sv_bless(rv,hv));
11953       SvREFCNT_dec(sv);
11954     }
11955     exception=DestroyExceptionInfo(exception);
11956     ST(0)=av_reference;
11957     SvREFCNT_dec(perl_exception);
11958     XSRETURN(1);
11959
11960   PerlException:
11961     InheritPerlException(exception,perl_exception);
11962     exception=DestroyExceptionInfo(exception);
11963     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11964     SvPOK_on(perl_exception);
11965     ST(0)=sv_2mortal(perl_exception);
11966     XSRETURN(1);
11967   }
11968 \f
11969 #
11970 ###############################################################################
11971 #                                                                             #
11972 #                                                                             #
11973 #                                                                             #
11974 #   M o r p h                                                                 #
11975 #                                                                             #
11976 #                                                                             #
11977 #                                                                             #
11978 ###############################################################################
11979 #
11980 #
11981 void
11982 Morph(ref,...)
11983   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
11984   ALIAS:
11985     MorphImage  = 1
11986     morph       = 2
11987     morphimage  = 3
11988   PPCODE:
11989   {
11990     AV
11991       *av;
11992
11993     char
11994       *attribute;
11995
11996     ExceptionInfo
11997       *exception;
11998
11999     HV
12000       *hv;
12001
12002     Image
12003       *image;
12004
12005     register ssize_t
12006       i;
12007
12008     ssize_t
12009       number_frames;
12010
12011     struct PackageInfo
12012       *info;
12013
12014     SV
12015       *av_reference,
12016       *perl_exception,
12017       *reference,
12018       *rv,
12019       *sv;
12020
12021     PERL_UNUSED_VAR(ref);
12022     PERL_UNUSED_VAR(ix);
12023     exception=AcquireExceptionInfo();
12024     perl_exception=newSVpv("",0);
12025     sv=NULL;
12026     av=NULL;
12027     attribute=NULL;
12028     if (sv_isobject(ST(0)) == 0)
12029       {
12030         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12031           PackageName);
12032         goto PerlException;
12033       }
12034     reference=SvRV(ST(0));
12035     hv=SvSTASH(reference);
12036     av=newAV();
12037     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12038     SvREFCNT_dec(av);
12039     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12040     if (image == (Image *) NULL)
12041       {
12042         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12043           PackageName);
12044         goto PerlException;
12045       }
12046     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12047     /*
12048       Get attribute.
12049     */
12050     number_frames=30;
12051     for (i=2; i < items; i+=2)
12052     {
12053       attribute=(char *) SvPV(ST(i-1),na);
12054       switch (*attribute)
12055       {
12056         case 'F':
12057         case 'f':
12058         {
12059           if (LocaleCompare(attribute,"frames") == 0)
12060             {
12061               number_frames=SvIV(ST(i));
12062               break;
12063             }
12064           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12065             attribute);
12066           break;
12067         }
12068         default:
12069         {
12070           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12071             attribute);
12072           break;
12073         }
12074       }
12075     }
12076     image=MorphImages(image,number_frames,exception);
12077     if (image == (Image *) NULL)
12078       goto PerlException;
12079     for ( ; image; image=image->next)
12080     {
12081       AddImageToRegistry(sv,image);
12082       rv=newRV(sv);
12083       av_push(av,sv_bless(rv,hv));
12084       SvREFCNT_dec(sv);
12085     }
12086     exception=DestroyExceptionInfo(exception);
12087     ST(0)=av_reference;
12088     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12089     XSRETURN(1);
12090
12091   PerlException:
12092     InheritPerlException(exception,perl_exception);
12093     exception=DestroyExceptionInfo(exception);
12094     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12095     SvPOK_on(perl_exception);
12096     ST(0)=sv_2mortal(perl_exception);
12097     XSRETURN(1);
12098   }
12099 \f
12100 #
12101 ###############################################################################
12102 #                                                                             #
12103 #                                                                             #
12104 #                                                                             #
12105 #   M o s a i c                                                               #
12106 #                                                                             #
12107 #                                                                             #
12108 #                                                                             #
12109 ###############################################################################
12110 #
12111 #
12112 void
12113 Mosaic(ref)
12114   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12115   ALIAS:
12116     MosaicImage   = 1
12117     mosaic        = 2
12118     mosaicimage   = 3
12119   PPCODE:
12120   {
12121     AV
12122       *av;
12123
12124     ExceptionInfo
12125       *exception;
12126
12127     HV
12128       *hv;
12129
12130     Image
12131       *image;
12132
12133     struct PackageInfo
12134       *info;
12135
12136     SV
12137       *perl_exception,
12138       *reference,
12139       *rv,
12140       *sv;
12141
12142     PERL_UNUSED_VAR(ref);
12143     PERL_UNUSED_VAR(ix);
12144     exception=AcquireExceptionInfo();
12145     perl_exception=newSVpv("",0);
12146     sv=NULL;
12147     if (sv_isobject(ST(0)) == 0)
12148       {
12149         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12150           PackageName);
12151         goto PerlException;
12152       }
12153     reference=SvRV(ST(0));
12154     hv=SvSTASH(reference);
12155     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12156     if (image == (Image *) NULL)
12157       {
12158         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12159           PackageName);
12160         goto PerlException;
12161       }
12162     image=MergeImageLayers(image,MosaicLayer,exception);
12163     /*
12164       Create blessed Perl array for the returned image.
12165     */
12166     av=newAV();
12167     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12168     SvREFCNT_dec(av);
12169     AddImageToRegistry(sv,image);
12170     rv=newRV(sv);
12171     av_push(av,sv_bless(rv,hv));
12172     SvREFCNT_dec(sv);
12173     (void) CopyMagickString(info->image_info->filename,image->filename,
12174       MagickPathExtent);
12175     SetImageInfo(info->image_info,0,exception);
12176     exception=DestroyExceptionInfo(exception);
12177     SvREFCNT_dec(perl_exception);
12178     XSRETURN(1);
12179
12180   PerlException:
12181     InheritPerlException(exception,perl_exception);
12182     exception=DestroyExceptionInfo(exception);
12183     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12184     SvPOK_on(perl_exception);  /* return messages in string context */
12185     ST(0)=sv_2mortal(perl_exception);
12186     XSRETURN(1);
12187   }
12188 \f
12189 #
12190 ###############################################################################
12191 #                                                                             #
12192 #                                                                             #
12193 #                                                                             #
12194 #   P e r c e p t u a l H a s h                                               #
12195 #                                                                             #
12196 #                                                                             #
12197 #                                                                             #
12198 ###############################################################################
12199 #
12200 #
12201 void
12202 PerceptualHash(ref)
12203   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12204   ALIAS:
12205     PerceptualHashImage = 1
12206     perceptualhash      = 2
12207     perceptualhashimage = 3
12208   PPCODE:
12209   {
12210     AV
12211       *av;
12212
12213     ChannelPerceptualHash
12214       *channel_phash;
12215
12216     char
12217       message[MagickPathExtent];
12218
12219     ExceptionInfo
12220       *exception;
12221
12222     Image
12223       *image;
12224
12225     ssize_t
12226       count;
12227
12228     struct PackageInfo
12229       *info;
12230
12231     SV
12232       *perl_exception,
12233       *reference;
12234
12235     PERL_UNUSED_VAR(ref);
12236     PERL_UNUSED_VAR(ix);
12237     exception=AcquireExceptionInfo();
12238     perl_exception=newSVpv("",0);
12239     av=NULL;
12240     if (sv_isobject(ST(0)) == 0)
12241       {
12242         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12243           PackageName);
12244         goto PerlException;
12245       }
12246     reference=SvRV(ST(0));
12247     av=newAV();
12248     SvREFCNT_dec(av);
12249     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12250     if (image == (Image *) NULL)
12251       {
12252         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12253           PackageName);
12254         goto PerlException;
12255       }
12256     count=0;
12257     for ( ; image; image=image->next)
12258     {
12259       register size_t
12260         i;
12261
12262       channel_phash=GetImagePerceptualHash(image,exception);
12263       if (channel_phash == (ChannelPerceptualHash *) NULL)
12264         continue;
12265       count++;
12266       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
12267       {
12268         ssize_t
12269           j;
12270
12271         PixelChannel channel=GetPixelChannelChannel(image,i);
12272         PixelTrait traits=GetPixelChannelTraits(image,channel);
12273         if (traits == UndefinedPixelTrait)
12274           continue;
12275         EXTEND(sp,GetPixelChannels(image)*MaximumNumberOfPerceptualHashes*
12276           channel_phash[0].number_colorspaces*(i+1)*count);
12277         for (j=0; j < MaximumNumberOfPerceptualHashes; j++)
12278         {
12279           register ssize_t
12280             k;
12281
12282           for (k=0; k < (ssize_t) channel_phash[0].number_colorspaces; k++)
12283           {
12284             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
12285               channel_phash[channel].phash[k][j]);
12286             PUSHs(sv_2mortal(newSVpv(message,0)));
12287           }
12288         }
12289       }
12290       channel_phash=(ChannelPerceptualHash *)
12291         RelinquishMagickMemory(channel_phash);
12292     }
12293
12294   PerlException:
12295     InheritPerlException(exception,perl_exception);
12296     exception=DestroyExceptionInfo(exception);
12297     SvREFCNT_dec(perl_exception);
12298   }
12299 \f
12300 #
12301 ###############################################################################
12302 #                                                                             #
12303 #                                                                             #
12304 #                                                                             #
12305 #   P i n g                                                                   #
12306 #                                                                             #
12307 #                                                                             #
12308 #                                                                             #
12309 ###############################################################################
12310 #
12311 #
12312 void
12313 Ping(ref,...)
12314   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12315   ALIAS:
12316     PingImage  = 1
12317     ping       = 2
12318     pingimage  = 3
12319   PPCODE:
12320   {
12321     AV
12322       *av;
12323
12324     char
12325       **keep,
12326       **list;
12327
12328     ExceptionInfo
12329       *exception;
12330
12331     Image
12332       *image,
12333       *next;
12334
12335     int
12336       n;
12337
12338     MagickBooleanType
12339       status;
12340
12341     register char
12342       **p;
12343
12344     register ssize_t
12345       i;
12346
12347     ssize_t
12348       ac;
12349
12350     STRLEN
12351       *length;
12352
12353     struct PackageInfo
12354       *info,
12355       *package_info;
12356
12357     SV
12358       *perl_exception,
12359       *reference;
12360
12361     size_t
12362       count;
12363
12364     PERL_UNUSED_VAR(ref);
12365     PERL_UNUSED_VAR(ix);
12366     exception=AcquireExceptionInfo();
12367     perl_exception=newSVpv("",0);
12368     package_info=(struct PackageInfo *) NULL;
12369     ac=(items < 2) ? 1 : items-1;
12370     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12371     keep=list;
12372     length=(STRLEN *) NULL;
12373     if (list == (char **) NULL)
12374       {
12375         ThrowPerlException(exception,ResourceLimitError,
12376           "MemoryAllocationFailed",PackageName);
12377         goto PerlException;
12378       }
12379     keep=list;
12380     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12381     if (length == (STRLEN *) NULL)
12382       {
12383         ThrowPerlException(exception,ResourceLimitError,
12384           "MemoryAllocationFailed",PackageName);
12385         goto PerlException;
12386       }
12387     if (sv_isobject(ST(0)) == 0)
12388       {
12389         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12390           PackageName);
12391         goto PerlException;
12392       }
12393     reference=SvRV(ST(0));
12394     if (SvTYPE(reference) != SVt_PVAV)
12395       {
12396         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12397           PackageName);
12398         goto PerlException;
12399       }
12400     av=(AV *) reference;
12401     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12402       exception);
12403     package_info=ClonePackageInfo(info,exception);
12404     n=1;
12405     if (items <= 1)
12406       *list=(char *) (*package_info->image_info->filename ?
12407         package_info->image_info->filename : "XC:black");
12408     else
12409       for (n=0, i=0; i < ac; i++)
12410       {
12411         list[n]=(char *) SvPV(ST(i+1),length[n]);
12412         if ((items >= 3) && strEQcase(list[n],"blob"))
12413           {
12414             void
12415               *blob;
12416
12417             i++;
12418             blob=(void *) (SvPV(ST(i+1),length[n]));
12419             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12420           }
12421         if ((items >= 3) && strEQcase(list[n],"filename"))
12422           continue;
12423         if ((items >= 3) && strEQcase(list[n],"file"))
12424           {
12425             FILE
12426               *file;
12427
12428             PerlIO
12429               *io_info;
12430
12431             i++;
12432             io_info=IoIFP(sv_2io(ST(i+1)));
12433             if (io_info == (PerlIO *) NULL)
12434               {
12435                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12436                   PackageName);
12437                 continue;
12438               }
12439             file=PerlIO_findFILE(io_info);
12440             if (file == (FILE *) NULL)
12441               {
12442                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12443                   PackageName);
12444                 continue;
12445               }
12446             SetImageInfoFile(package_info->image_info,file);
12447           }
12448         if ((items >= 3) && strEQcase(list[n],"magick"))
12449           continue;
12450         n++;
12451       }
12452     list[n]=(char *) NULL;
12453     keep=list;
12454     status=ExpandFilenames(&n,&list);
12455     if (status == MagickFalse)
12456       {
12457         ThrowPerlException(exception,ResourceLimitError,
12458           "MemoryAllocationFailed",PackageName);
12459         goto PerlException;
12460       }
12461     count=0;
12462     for (i=0; i < n; i++)
12463     {
12464       (void) CopyMagickString(package_info->image_info->filename,list[i],
12465         MagickPathExtent);
12466       image=PingImage(package_info->image_info,exception);
12467       if (image == (Image *) NULL)
12468         break;
12469       if ((package_info->image_info->file != (FILE *) NULL) ||
12470           (package_info->image_info->blob != (void *) NULL))
12471         DisassociateImageStream(image);
12472       count+=GetImageListLength(image);
12473       EXTEND(sp,4*count);
12474       for (next=image; next; next=next->next)
12475       {
12476         PUSHs(sv_2mortal(newSViv(next->columns)));
12477         PUSHs(sv_2mortal(newSViv(next->rows)));
12478         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12479         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12480       }
12481       image=DestroyImageList(image);
12482     }
12483     /*
12484       Free resources.
12485     */
12486     for (i=0; i < n; i++)
12487       if (list[i] != (char *) NULL)
12488         for (p=keep; list[i] != *p++; )
12489           if (*p == NULL)
12490             {
12491               list[i]=(char *) RelinquishMagickMemory(list[i]);
12492               break;
12493             }
12494
12495   PerlException:
12496     if (package_info != (struct PackageInfo *) NULL)
12497       DestroyPackageInfo(package_info);
12498     if (list && (list != keep))
12499       list=(char **) RelinquishMagickMemory(list);
12500     if (keep)
12501       keep=(char **) RelinquishMagickMemory(keep);
12502     if (length)
12503       length=(STRLEN *) RelinquishMagickMemory(length);
12504     InheritPerlException(exception,perl_exception);
12505     exception=DestroyExceptionInfo(exception);
12506     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12507   }
12508 \f
12509 #
12510 ###############################################################################
12511 #                                                                             #
12512 #                                                                             #
12513 #                                                                             #
12514 #   P r e v i e w                                                             #
12515 #                                                                             #
12516 #                                                                             #
12517 #                                                                             #
12518 ###############################################################################
12519 #
12520 #
12521 void
12522 Preview(ref,...)
12523   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12524   ALIAS:
12525     PreviewImage = 1
12526     preview      = 2
12527     previewimage = 3
12528   PPCODE:
12529   {
12530     AV
12531       *av;
12532
12533     ExceptionInfo
12534       *exception;
12535
12536     HV
12537       *hv;
12538
12539     Image
12540       *image,
12541       *preview_image;
12542
12543     PreviewType
12544       preview_type;
12545
12546     struct PackageInfo
12547       *info;
12548
12549     SV
12550       *av_reference,
12551       *perl_exception,
12552       *reference,
12553       *rv,
12554       *sv;
12555
12556     PERL_UNUSED_VAR(ref);
12557     PERL_UNUSED_VAR(ix);
12558     exception=AcquireExceptionInfo();
12559     perl_exception=newSVpv("",0);
12560     sv=NULL;
12561     av=NULL;
12562     if (sv_isobject(ST(0)) == 0)
12563       {
12564         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12565           PackageName);
12566         goto PerlException;
12567       }
12568     reference=SvRV(ST(0));
12569     hv=SvSTASH(reference);
12570     av=newAV();
12571     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12572     SvREFCNT_dec(av);
12573     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12574     if (image == (Image *) NULL)
12575       {
12576         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12577           PackageName);
12578         goto PerlException;
12579       }
12580     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12581     preview_type=GammaPreview;
12582     if (items > 1)
12583       preview_type=(PreviewType) ParseCommandOption(MagickPreviewOptions,
12584         MagickFalse,SvPV(ST(1),na));
12585     for ( ; image; image=image->next)
12586     {
12587       preview_image=PreviewImage(image,preview_type,exception);
12588       if (preview_image == (Image *) NULL)
12589         goto PerlException;
12590       AddImageToRegistry(sv,preview_image);
12591       rv=newRV(sv);
12592       av_push(av,sv_bless(rv,hv));
12593       SvREFCNT_dec(sv);
12594     }
12595     exception=DestroyExceptionInfo(exception);
12596     ST(0)=av_reference;
12597     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12598     XSRETURN(1);
12599
12600   PerlException:
12601     InheritPerlException(exception,perl_exception);
12602     exception=DestroyExceptionInfo(exception);
12603     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12604     SvPOK_on(perl_exception);
12605     ST(0)=sv_2mortal(perl_exception);
12606     XSRETURN(1);
12607   }
12608 \f
12609 #
12610 ###############################################################################
12611 #                                                                             #
12612 #                                                                             #
12613 #                                                                             #
12614 #   Q u e r y C o l o r                                                       #
12615 #                                                                             #
12616 #                                                                             #
12617 #                                                                             #
12618 ###############################################################################
12619 #
12620 #
12621 void
12622 QueryColor(ref,...)
12623   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12624   ALIAS:
12625     querycolor = 1
12626   PPCODE:
12627   {
12628     char
12629       *name;
12630
12631     ExceptionInfo
12632       *exception;
12633
12634     PixelInfo
12635       color;
12636
12637     register ssize_t
12638       i;
12639
12640     SV
12641       *perl_exception;
12642
12643     PERL_UNUSED_VAR(ref);
12644     PERL_UNUSED_VAR(ix);
12645     exception=AcquireExceptionInfo();
12646     perl_exception=newSVpv("",0);
12647     if (items == 1)
12648       {
12649         const ColorInfo
12650           **colorlist;
12651
12652         size_t
12653           colors;
12654
12655         colorlist=GetColorInfoList("*",&colors,exception);
12656         EXTEND(sp,colors);
12657         for (i=0; i < (ssize_t) colors; i++)
12658         {
12659           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12660         }
12661         colorlist=(const ColorInfo **)
12662           RelinquishMagickMemory((ColorInfo **) colorlist);
12663         goto PerlException;
12664       }
12665     EXTEND(sp,5*items);
12666     for (i=1; i < items; i++)
12667     {
12668       name=(char *) SvPV(ST(i),na);
12669       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12670         {
12671           PUSHs(&sv_undef);
12672           continue;
12673         }
12674       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12675       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12676       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12677       if (color.colorspace == CMYKColorspace)
12678         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12679       if (color.alpha_trait != UndefinedPixelTrait)
12680         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12681     }
12682
12683   PerlException:
12684     InheritPerlException(exception,perl_exception);
12685     exception=DestroyExceptionInfo(exception);
12686     SvREFCNT_dec(perl_exception);
12687   }
12688 \f
12689 #
12690 ###############################################################################
12691 #                                                                             #
12692 #                                                                             #
12693 #                                                                             #
12694 #   Q u e r y C o l o r N a m e                                               #
12695 #                                                                             #
12696 #                                                                             #
12697 #                                                                             #
12698 ###############################################################################
12699 #
12700 #
12701 void
12702 QueryColorname(ref,...)
12703   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12704   ALIAS:
12705     querycolorname = 1
12706   PPCODE:
12707   {
12708     AV
12709       *av;
12710
12711     char
12712       message[MagickPathExtent];
12713
12714     ExceptionInfo
12715       *exception;
12716
12717     Image
12718       *image;
12719
12720     PixelInfo
12721       target_color;
12722
12723     register ssize_t
12724       i;
12725
12726     struct PackageInfo
12727       *info;
12728
12729     SV
12730       *perl_exception,
12731       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12732
12733     PERL_UNUSED_VAR(ref);
12734     PERL_UNUSED_VAR(ix);
12735     exception=AcquireExceptionInfo();
12736     perl_exception=newSVpv("",0);
12737     reference=SvRV(ST(0));
12738     av=(AV *) reference;
12739     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12740       exception);
12741     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12742     if (image == (Image *) NULL)
12743       {
12744         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12745           PackageName);
12746         goto PerlException;
12747       }
12748     EXTEND(sp,items);
12749     for (i=1; i < items; i++)
12750     {
12751       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12752         exception);
12753       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12754         exception);
12755       PUSHs(sv_2mortal(newSVpv(message,0)));
12756     }
12757
12758   PerlException:
12759     InheritPerlException(exception,perl_exception);
12760     exception=DestroyExceptionInfo(exception);
12761     SvREFCNT_dec(perl_exception);
12762   }
12763 \f
12764 #
12765 ###############################################################################
12766 #                                                                             #
12767 #                                                                             #
12768 #                                                                             #
12769 #   Q u e r y F o n t                                                         #
12770 #                                                                             #
12771 #                                                                             #
12772 #                                                                             #
12773 ###############################################################################
12774 #
12775 #
12776 void
12777 QueryFont(ref,...)
12778   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12779   ALIAS:
12780     queryfont = 1
12781   PPCODE:
12782   {
12783     char
12784       *name,
12785       message[MagickPathExtent];
12786
12787     ExceptionInfo
12788       *exception;
12789
12790     register ssize_t
12791       i;
12792
12793     SV
12794       *perl_exception;
12795
12796     volatile const TypeInfo
12797       *type_info;
12798
12799     PERL_UNUSED_VAR(ref);
12800     PERL_UNUSED_VAR(ix);
12801     exception=AcquireExceptionInfo();
12802     perl_exception=newSVpv("",0);
12803     if (items == 1)
12804       {
12805         const TypeInfo
12806           **typelist;
12807
12808         size_t
12809           types;
12810
12811         typelist=GetTypeInfoList("*",&types,exception);
12812         EXTEND(sp,types);
12813         for (i=0; i < (ssize_t) types; i++)
12814         {
12815           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12816         }
12817         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12818           typelist);
12819         goto PerlException;
12820       }
12821     EXTEND(sp,10*items);
12822     for (i=1; i < items; i++)
12823     {
12824       name=(char *) SvPV(ST(i),na);
12825       type_info=GetTypeInfo(name,exception);
12826       if (type_info == (TypeInfo *) NULL)
12827         {
12828           PUSHs(&sv_undef);
12829           continue;
12830         }
12831       if (type_info->name == (char *) NULL)
12832         PUSHs(&sv_undef);
12833       else
12834         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12835       if (type_info->description == (char *) NULL)
12836         PUSHs(&sv_undef);
12837       else
12838         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12839       if (type_info->family == (char *) NULL)
12840         PUSHs(&sv_undef);
12841       else
12842         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12843       if (type_info->style == UndefinedStyle)
12844         PUSHs(&sv_undef);
12845       else
12846         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12847           type_info->style),0)));
12848       if (type_info->stretch == UndefinedStretch)
12849         PUSHs(&sv_undef);
12850       else
12851         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12852           type_info->stretch),0)));
12853       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12854         type_info->weight);
12855       PUSHs(sv_2mortal(newSVpv(message,0)));
12856       if (type_info->encoding == (char *) NULL)
12857         PUSHs(&sv_undef);
12858       else
12859         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12860       if (type_info->foundry == (char *) NULL)
12861         PUSHs(&sv_undef);
12862       else
12863         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12864       if (type_info->format == (char *) NULL)
12865         PUSHs(&sv_undef);
12866       else
12867         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12868       if (type_info->metrics == (char *) NULL)
12869         PUSHs(&sv_undef);
12870       else
12871         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12872       if (type_info->glyphs == (char *) NULL)
12873         PUSHs(&sv_undef);
12874       else
12875         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12876     }
12877
12878   PerlException:
12879     InheritPerlException(exception,perl_exception);
12880     exception=DestroyExceptionInfo(exception);
12881     SvREFCNT_dec(perl_exception);
12882   }
12883 \f
12884 #
12885 ###############################################################################
12886 #                                                                             #
12887 #                                                                             #
12888 #                                                                             #
12889 #   Q u e r y F o n t M e t r i c s                                           #
12890 #                                                                             #
12891 #                                                                             #
12892 #                                                                             #
12893 ###############################################################################
12894 #
12895 #
12896 void
12897 QueryFontMetrics(ref,...)
12898   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
12899   ALIAS:
12900     queryfontmetrics = 1
12901   PPCODE:
12902   {
12903     AffineMatrix
12904       affine,
12905       current;
12906
12907     AV
12908       *av;
12909
12910     char
12911       *attribute;
12912
12913     double
12914       x,
12915       y;
12916
12917     DrawInfo
12918       *draw_info;
12919
12920     ExceptionInfo
12921       *exception;
12922
12923     GeometryInfo
12924       geometry_info;
12925
12926     Image
12927       *image;
12928
12929     MagickBooleanType
12930       status;
12931
12932     MagickStatusType
12933       flags;
12934
12935     register ssize_t
12936       i;
12937
12938     ssize_t
12939       type;
12940
12941     struct PackageInfo
12942       *info,
12943       *package_info;
12944
12945     SV
12946       *perl_exception,
12947       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12948
12949     TypeMetric
12950       metrics;
12951
12952     PERL_UNUSED_VAR(ref);
12953     PERL_UNUSED_VAR(ix);
12954     exception=AcquireExceptionInfo();
12955     package_info=(struct PackageInfo *) NULL;
12956     perl_exception=newSVpv("",0);
12957     reference=SvRV(ST(0));
12958     av=(AV *) reference;
12959     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12960       exception);
12961     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12962     if (image == (Image *) NULL)
12963       {
12964         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12965           PackageName);
12966         goto PerlException;
12967       }
12968     package_info=ClonePackageInfo(info,exception);
12969     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12970     CloneString(&draw_info->text,"");
12971     current=draw_info->affine;
12972     GetAffineMatrix(&affine);
12973     x=0.0;
12974     y=0.0;
12975     EXTEND(sp,7*items);
12976     for (i=2; i < items; i+=2)
12977     {
12978       attribute=(char *) SvPV(ST(i-1),na);
12979       switch (*attribute)
12980       {
12981         case 'A':
12982         case 'a':
12983         {
12984           if (LocaleCompare(attribute,"antialias") == 0)
12985             {
12986               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12987                 SvPV(ST(i),na));
12988               if (type < 0)
12989                 {
12990                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12991                     SvPV(ST(i),na));
12992                   break;
12993                 }
12994               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12995               break;
12996             }
12997           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12998             attribute);
12999           break;
13000         }
13001         case 'd':
13002         case 'D':
13003         {
13004           if (LocaleCompare(attribute,"density") == 0)
13005             {
13006               CloneString(&draw_info->density,SvPV(ST(i),na));
13007               break;
13008             }
13009           if (LocaleCompare(attribute,"direction") == 0)
13010             {
13011               draw_info->direction=(DirectionType) ParseCommandOption(
13012                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
13013               break;
13014             }
13015           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13016             attribute);
13017           break;
13018         }
13019         case 'e':
13020         case 'E':
13021         {
13022           if (LocaleCompare(attribute,"encoding") == 0)
13023             {
13024               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13025               break;
13026             }
13027           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13028             attribute);
13029           break;
13030         }
13031         case 'f':
13032         case 'F':
13033         {
13034           if (LocaleCompare(attribute,"family") == 0)
13035             {
13036               CloneString(&draw_info->family,SvPV(ST(i),na));
13037               break;
13038             }
13039           if (LocaleCompare(attribute,"fill") == 0)
13040             {
13041               if (info)
13042                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13043                   &draw_info->fill,exception);
13044               break;
13045             }
13046           if (LocaleCompare(attribute,"font") == 0)
13047             {
13048               CloneString(&draw_info->font,SvPV(ST(i),na));
13049               break;
13050             }
13051           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13052             attribute);
13053           break;
13054         }
13055         case 'g':
13056         case 'G':
13057         {
13058           if (LocaleCompare(attribute,"geometry") == 0)
13059             {
13060               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13061               break;
13062             }
13063           if (LocaleCompare(attribute,"gravity") == 0)
13064             {
13065               draw_info->gravity=(GravityType) ParseCommandOption(
13066                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13067               break;
13068             }
13069           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13070             attribute);
13071           break;
13072         }
13073         case 'i':
13074         case 'I':
13075         {
13076           if (LocaleCompare(attribute,"interline-spacing") == 0)
13077             {
13078               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13079               draw_info->interline_spacing=geometry_info.rho;
13080               break;
13081             }
13082           if (LocaleCompare(attribute,"interword-spacing") == 0)
13083             {
13084               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13085               draw_info->interword_spacing=geometry_info.rho;
13086               break;
13087             }
13088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13089             attribute);
13090           break;
13091         }
13092         case 'k':
13093         case 'K':
13094         {
13095           if (LocaleCompare(attribute,"kerning") == 0)
13096             {
13097               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13098               draw_info->kerning=geometry_info.rho;
13099               break;
13100             }
13101           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13102             attribute);
13103           break;
13104         }
13105         case 'p':
13106         case 'P':
13107         {
13108           if (LocaleCompare(attribute,"pointsize") == 0)
13109             {
13110               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13111               draw_info->pointsize=geometry_info.rho;
13112               break;
13113             }
13114           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13115             attribute);
13116           break;
13117         }
13118         case 'r':
13119         case 'R':
13120         {
13121           if (LocaleCompare(attribute,"rotate") == 0)
13122             {
13123               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13124               affine.rx=geometry_info.rho;
13125               affine.ry=geometry_info.sigma;
13126               if ((flags & SigmaValue) == 0)
13127                 affine.ry=affine.rx;
13128               break;
13129             }
13130           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13131             attribute);
13132           break;
13133         }
13134         case 's':
13135         case 'S':
13136         {
13137           if (LocaleCompare(attribute,"scale") == 0)
13138             {
13139               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13140               affine.sx=geometry_info.rho;
13141               affine.sy=geometry_info.sigma;
13142               if ((flags & SigmaValue) == 0)
13143                 affine.sy=affine.sx;
13144               break;
13145             }
13146           if (LocaleCompare(attribute,"skew") == 0)
13147             {
13148               double
13149                 x_angle,
13150                 y_angle;
13151
13152               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13153               x_angle=geometry_info.rho;
13154               y_angle=geometry_info.sigma;
13155               if ((flags & SigmaValue) == 0)
13156                 y_angle=x_angle;
13157               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13158               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13159               break;
13160             }
13161           if (LocaleCompare(attribute,"stroke") == 0)
13162             {
13163               if (info)
13164                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13165                   &draw_info->stroke,exception);
13166               break;
13167             }
13168           if (LocaleCompare(attribute,"style") == 0)
13169             {
13170               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13171                 SvPV(ST(i),na));
13172               if (type < 0)
13173                 {
13174                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13175                     SvPV(ST(i),na));
13176                   break;
13177                 }
13178               draw_info->style=(StyleType) type;
13179               break;
13180             }
13181           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13182             attribute);
13183           break;
13184         }
13185         case 't':
13186         case 'T':
13187         {
13188           if (LocaleCompare(attribute,"text") == 0)
13189             {
13190               CloneString(&draw_info->text,SvPV(ST(i),na));
13191               break;
13192             }
13193           if (LocaleCompare(attribute,"translate") == 0)
13194             {
13195               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13196               affine.tx=geometry_info.rho;
13197               affine.ty=geometry_info.sigma;
13198               if ((flags & SigmaValue) == 0)
13199                 affine.ty=affine.tx;
13200               break;
13201             }
13202           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13203             attribute);
13204           break;
13205         }
13206         case 'w':
13207         case 'W':
13208         {
13209           if (LocaleCompare(attribute,"weight") == 0)
13210             {
13211               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13212               draw_info->weight=(size_t) geometry_info.rho;
13213               break;
13214             }
13215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13216             attribute);
13217           break;
13218         }
13219         case 'x':
13220         case 'X':
13221         {
13222           if (LocaleCompare(attribute,"x") == 0)
13223             {
13224               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13225               x=geometry_info.rho;
13226               break;
13227             }
13228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13229             attribute);
13230           break;
13231         }
13232         case 'y':
13233         case 'Y':
13234         {
13235           if (LocaleCompare(attribute,"y") == 0)
13236             {
13237               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13238               y=geometry_info.rho;
13239               break;
13240             }
13241           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13242             attribute);
13243           break;
13244         }
13245         default:
13246         {
13247           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13248             attribute);
13249           break;
13250         }
13251       }
13252     }
13253     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13254     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13255     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13256     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13257     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13258     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13259     if (draw_info->geometry == (char *) NULL)
13260       {
13261         draw_info->geometry=AcquireString((char *) NULL);
13262         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13263           "%.20g,%.20g",x,y);
13264       }
13265     status=GetTypeMetrics(image,draw_info,&metrics,exception);
13266     (void) CatchImageException(image);
13267     if (status == MagickFalse)
13268       PUSHs(&sv_undef);
13269     else
13270       {
13271         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13272         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13273         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13274         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13275         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13276         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13277         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13278         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13279         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13280         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13281         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13282         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13283         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13284       }
13285     draw_info=DestroyDrawInfo(draw_info);
13286
13287   PerlException:
13288     if (package_info != (struct PackageInfo *) NULL)
13289       DestroyPackageInfo(package_info);
13290     InheritPerlException(exception,perl_exception);
13291     exception=DestroyExceptionInfo(exception);
13292     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13293   }
13294 \f
13295 #
13296 ###############################################################################
13297 #                                                                             #
13298 #                                                                             #
13299 #                                                                             #
13300 #   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                         #
13301 #                                                                             #
13302 #                                                                             #
13303 #                                                                             #
13304 ###############################################################################
13305 #
13306 #
13307 void
13308 QueryMultilineFontMetrics(ref,...)
13309   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13310   ALIAS:
13311     querymultilinefontmetrics = 1
13312   PPCODE:
13313   {
13314     AffineMatrix
13315       affine,
13316       current;
13317
13318     AV
13319       *av;
13320
13321     char
13322       *attribute;
13323
13324     double
13325       x,
13326       y;
13327
13328     DrawInfo
13329       *draw_info;
13330
13331     ExceptionInfo
13332       *exception;
13333
13334     GeometryInfo
13335       geometry_info;
13336
13337     Image
13338       *image;
13339
13340     MagickBooleanType
13341       status;
13342
13343     MagickStatusType
13344       flags;
13345
13346     register ssize_t
13347       i;
13348
13349     ssize_t
13350       type;
13351
13352     struct PackageInfo
13353       *info,
13354       *package_info;
13355
13356     SV
13357       *perl_exception,
13358       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13359
13360     TypeMetric
13361       metrics;
13362
13363     PERL_UNUSED_VAR(ref);
13364     PERL_UNUSED_VAR(ix);
13365     exception=AcquireExceptionInfo();
13366     package_info=(struct PackageInfo *) NULL;
13367     perl_exception=newSVpv("",0);
13368     reference=SvRV(ST(0));
13369     av=(AV *) reference;
13370     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13371       exception);
13372     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13373     if (image == (Image *) NULL)
13374       {
13375         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13376           PackageName);
13377         goto PerlException;
13378       }
13379     package_info=ClonePackageInfo(info,exception);
13380     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13381     CloneString(&draw_info->text,"");
13382     current=draw_info->affine;
13383     GetAffineMatrix(&affine);
13384     x=0.0;
13385     y=0.0;
13386     EXTEND(sp,7*items);
13387     for (i=2; i < items; i+=2)
13388     {
13389       attribute=(char *) SvPV(ST(i-1),na);
13390       switch (*attribute)
13391       {
13392         case 'A':
13393         case 'a':
13394         {
13395           if (LocaleCompare(attribute,"antialias") == 0)
13396             {
13397               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13398                 SvPV(ST(i),na));
13399               if (type < 0)
13400                 {
13401                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13402                     SvPV(ST(i),na));
13403                   break;
13404                 }
13405               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13406               break;
13407             }
13408           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13409             attribute);
13410           break;
13411         }
13412         case 'd':
13413         case 'D':
13414         {
13415           if (LocaleCompare(attribute,"density") == 0)
13416             {
13417               CloneString(&draw_info->density,SvPV(ST(i),na));
13418               break;
13419             }
13420           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13421             attribute);
13422           break;
13423         }
13424         case 'e':
13425         case 'E':
13426         {
13427           if (LocaleCompare(attribute,"encoding") == 0)
13428             {
13429               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13430               break;
13431             }
13432           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13433             attribute);
13434           break;
13435         }
13436         case 'f':
13437         case 'F':
13438         {
13439           if (LocaleCompare(attribute,"family") == 0)
13440             {
13441               CloneString(&draw_info->family,SvPV(ST(i),na));
13442               break;
13443             }
13444           if (LocaleCompare(attribute,"fill") == 0)
13445             {
13446               if (info)
13447                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13448                   &draw_info->fill,exception);
13449               break;
13450             }
13451           if (LocaleCompare(attribute,"font") == 0)
13452             {
13453               CloneString(&draw_info->font,SvPV(ST(i),na));
13454               break;
13455             }
13456           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13457             attribute);
13458           break;
13459         }
13460         case 'g':
13461         case 'G':
13462         {
13463           if (LocaleCompare(attribute,"geometry") == 0)
13464             {
13465               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13466               break;
13467             }
13468           if (LocaleCompare(attribute,"gravity") == 0)
13469             {
13470               draw_info->gravity=(GravityType) ParseCommandOption(
13471                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13472               break;
13473             }
13474           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13475             attribute);
13476           break;
13477         }
13478         case 'p':
13479         case 'P':
13480         {
13481           if (LocaleCompare(attribute,"pointsize") == 0)
13482             {
13483               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13484               draw_info->pointsize=geometry_info.rho;
13485               break;
13486             }
13487           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13488             attribute);
13489           break;
13490         }
13491         case 'r':
13492         case 'R':
13493         {
13494           if (LocaleCompare(attribute,"rotate") == 0)
13495             {
13496               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13497               affine.rx=geometry_info.rho;
13498               affine.ry=geometry_info.sigma;
13499               if ((flags & SigmaValue) == 0)
13500                 affine.ry=affine.rx;
13501               break;
13502             }
13503           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13504             attribute);
13505           break;
13506         }
13507         case 's':
13508         case 'S':
13509         {
13510           if (LocaleCompare(attribute,"scale") == 0)
13511             {
13512               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13513               affine.sx=geometry_info.rho;
13514               affine.sy=geometry_info.sigma;
13515               if ((flags & SigmaValue) == 0)
13516                 affine.sy=affine.sx;
13517               break;
13518             }
13519           if (LocaleCompare(attribute,"skew") == 0)
13520             {
13521               double
13522                 x_angle,
13523                 y_angle;
13524
13525               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13526               x_angle=geometry_info.rho;
13527               y_angle=geometry_info.sigma;
13528               if ((flags & SigmaValue) == 0)
13529                 y_angle=x_angle;
13530               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13531               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13532               break;
13533             }
13534           if (LocaleCompare(attribute,"stroke") == 0)
13535             {
13536               if (info)
13537                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13538                   &draw_info->stroke,exception);
13539               break;
13540             }
13541           if (LocaleCompare(attribute,"style") == 0)
13542             {
13543               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13544                 SvPV(ST(i),na));
13545               if (type < 0)
13546                 {
13547                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13548                     SvPV(ST(i),na));
13549                   break;
13550                 }
13551               draw_info->style=(StyleType) type;
13552               break;
13553             }
13554           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13555             attribute);
13556           break;
13557         }
13558         case 't':
13559         case 'T':
13560         {
13561           if (LocaleCompare(attribute,"text") == 0)
13562             {
13563               CloneString(&draw_info->text,SvPV(ST(i),na));
13564               break;
13565             }
13566           if (LocaleCompare(attribute,"translate") == 0)
13567             {
13568               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13569               affine.tx=geometry_info.rho;
13570               affine.ty=geometry_info.sigma;
13571               if ((flags & SigmaValue) == 0)
13572                 affine.ty=affine.tx;
13573               break;
13574             }
13575           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13576             attribute);
13577           break;
13578         }
13579         case 'w':
13580         case 'W':
13581         {
13582           if (LocaleCompare(attribute,"weight") == 0)
13583             {
13584               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13585               draw_info->weight=(size_t) geometry_info.rho;
13586               break;
13587             }
13588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13589             attribute);
13590           break;
13591         }
13592         case 'x':
13593         case 'X':
13594         {
13595           if (LocaleCompare(attribute,"x") == 0)
13596             {
13597               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13598               x=geometry_info.rho;
13599               break;
13600             }
13601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13602             attribute);
13603           break;
13604         }
13605         case 'y':
13606         case 'Y':
13607         {
13608           if (LocaleCompare(attribute,"y") == 0)
13609             {
13610               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13611               y=geometry_info.rho;
13612               break;
13613             }
13614           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13615             attribute);
13616           break;
13617         }
13618         default:
13619         {
13620           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13621             attribute);
13622           break;
13623         }
13624       }
13625     }
13626     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13627     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13628     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13629     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13630     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13631     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13632     if (draw_info->geometry == (char *) NULL)
13633       {
13634         draw_info->geometry=AcquireString((char *) NULL);
13635         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13636           "%.20g,%.20g",x,y);
13637       }
13638     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13639     (void) CatchException(exception);
13640     if (status == MagickFalse)
13641       PUSHs(&sv_undef);
13642     else
13643       {
13644         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13645         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13646         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13647         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13648         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13649         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13650         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13651         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13652         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13653         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13654         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13655         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13656         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13657       }
13658     draw_info=DestroyDrawInfo(draw_info);
13659
13660   PerlException:
13661     if (package_info != (struct PackageInfo *) NULL)
13662       DestroyPackageInfo(package_info);
13663     InheritPerlException(exception,perl_exception);
13664     exception=DestroyExceptionInfo(exception);
13665     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13666   }
13667 \f
13668 #
13669 ###############################################################################
13670 #                                                                             #
13671 #                                                                             #
13672 #                                                                             #
13673 #   Q u e r y F o r m a t                                                     #
13674 #                                                                             #
13675 #                                                                             #
13676 #                                                                             #
13677 ###############################################################################
13678 #
13679 #
13680 void
13681 QueryFormat(ref,...)
13682   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13683   ALIAS:
13684     queryformat = 1
13685   PPCODE:
13686   {
13687     char
13688       *name;
13689
13690     ExceptionInfo
13691       *exception;
13692
13693     register ssize_t
13694       i;
13695
13696     SV
13697       *perl_exception;
13698
13699     volatile const MagickInfo
13700       *magick_info;
13701
13702     PERL_UNUSED_VAR(ref);
13703     PERL_UNUSED_VAR(ix);
13704     exception=AcquireExceptionInfo();
13705     perl_exception=newSVpv("",0);
13706     if (items == 1)
13707       {
13708         char
13709           format[MagickPathExtent];
13710
13711         const MagickInfo
13712           **format_list;
13713
13714         size_t
13715           types;
13716
13717         format_list=GetMagickInfoList("*",&types,exception);
13718         EXTEND(sp,types);
13719         for (i=0; i < (ssize_t) types; i++)
13720         {
13721           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13722           LocaleLower(format);
13723           PUSHs(sv_2mortal(newSVpv(format,0)));
13724         }
13725         format_list=(const MagickInfo **)
13726           RelinquishMagickMemory((MagickInfo *) format_list);
13727         goto PerlException;
13728       }
13729     EXTEND(sp,8*items);
13730     for (i=1; i < items; i++)
13731     {
13732       name=(char *) SvPV(ST(i),na);
13733       magick_info=GetMagickInfo(name,exception);
13734       if (magick_info == (const MagickInfo *) NULL)
13735         {
13736           PUSHs(&sv_undef);
13737           continue;
13738         }
13739       if (magick_info->description == (char *) NULL)
13740         PUSHs(&sv_undef);
13741       else
13742         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13743       if (magick_info->module == (char *) NULL)
13744         PUSHs(&sv_undef);
13745       else
13746         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13747     }
13748
13749   PerlException:
13750     InheritPerlException(exception,perl_exception);
13751     exception=DestroyExceptionInfo(exception);
13752     SvREFCNT_dec(perl_exception);
13753   }
13754 \f
13755 #
13756 ###############################################################################
13757 #                                                                             #
13758 #                                                                             #
13759 #                                                                             #
13760 #   Q u e r y O p t i o n                                                     #
13761 #                                                                             #
13762 #                                                                             #
13763 #                                                                             #
13764 ###############################################################################
13765 #
13766 #
13767 void
13768 QueryOption(ref,...)
13769   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13770   ALIAS:
13771     queryoption = 1
13772   PPCODE:
13773   {
13774     char
13775       **options;
13776
13777     ExceptionInfo
13778       *exception;
13779
13780     register ssize_t
13781       i;
13782
13783     ssize_t
13784       j,
13785       option;
13786
13787     SV
13788       *perl_exception;
13789
13790     PERL_UNUSED_VAR(ref);
13791     PERL_UNUSED_VAR(ix);
13792     exception=AcquireExceptionInfo();
13793     perl_exception=newSVpv("",0);
13794     EXTEND(sp,8*items);
13795     for (i=1; i < items; i++)
13796     {
13797       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13798         SvPV(ST(i),na));
13799       options=GetCommandOptions((CommandOption) option);
13800       if (options == (char **) NULL)
13801         PUSHs(&sv_undef);
13802       else
13803         {
13804           for (j=0; options[j] != (char *) NULL; j++)
13805             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13806           options=DestroyStringList(options);
13807         }
13808     }
13809
13810     InheritPerlException(exception,perl_exception);
13811     exception=DestroyExceptionInfo(exception);
13812     SvREFCNT_dec(perl_exception);
13813   }
13814 \f
13815 #
13816 ###############################################################################
13817 #                                                                             #
13818 #                                                                             #
13819 #                                                                             #
13820 #   R e a d                                                                   #
13821 #                                                                             #
13822 #                                                                             #
13823 #                                                                             #
13824 ###############################################################################
13825 #
13826 #
13827 void
13828 Read(ref,...)
13829   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
13830   ALIAS:
13831     ReadImage  = 1
13832     read       = 2
13833     readimage  = 3
13834   PPCODE:
13835   {
13836     AV
13837       *av;
13838
13839     char
13840       **keep,
13841       **list;
13842
13843     ExceptionInfo
13844       *exception;
13845
13846     HV
13847       *hv;
13848
13849     Image
13850       *image;
13851
13852     int
13853       n;
13854
13855     MagickBooleanType
13856       status;
13857
13858     register char
13859       **p;
13860
13861     register ssize_t
13862       i;
13863
13864     ssize_t
13865       ac,
13866       number_images;
13867
13868     STRLEN
13869       *length;
13870
13871     struct PackageInfo
13872       *info,
13873       *package_info;
13874
13875     SV
13876       *perl_exception,  /* Perl variable for storing messages */
13877       *reference,
13878       *rv,
13879       *sv;
13880
13881     PERL_UNUSED_VAR(ref);
13882     PERL_UNUSED_VAR(ix);
13883     exception=AcquireExceptionInfo();
13884     perl_exception=newSVpv("",0);
13885     sv=NULL;
13886     package_info=(struct PackageInfo *) NULL;
13887     number_images=0;
13888     ac=(items < 2) ? 1 : items-1;
13889     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13890     keep=list;
13891     length=(STRLEN *) NULL;
13892     if (list == (char **) NULL)
13893       {
13894         ThrowPerlException(exception,ResourceLimitError,
13895           "MemoryAllocationFailed",PackageName);
13896         goto PerlException;
13897       }
13898     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13899     if (length == (STRLEN *) NULL)
13900       {
13901         ThrowPerlException(exception,ResourceLimitError,
13902           "MemoryAllocationFailed",PackageName);
13903         goto PerlException;
13904       }
13905     if (sv_isobject(ST(0)) == 0)
13906       {
13907         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13908           PackageName);
13909         goto PerlException;
13910       }
13911     reference=SvRV(ST(0));
13912     hv=SvSTASH(reference);
13913     if (SvTYPE(reference) != SVt_PVAV)
13914       {
13915         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13916           PackageName);
13917         goto PerlException;
13918       }
13919     av=(AV *) reference;
13920     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13921       exception);
13922     package_info=ClonePackageInfo(info,exception);
13923     n=1;
13924     if (items <= 1)
13925       *list=(char *) (*package_info->image_info->filename ?
13926         package_info->image_info->filename : "XC:black");
13927     else
13928       for (n=0, i=0; i < ac; i++)
13929       {
13930         list[n]=(char *) SvPV(ST(i+1),length[n]);
13931         if ((items >= 3) && strEQcase(list[n],"blob"))
13932           {
13933             void
13934               *blob;
13935
13936             i++;
13937             blob=(void *) (SvPV(ST(i+1),length[n]));
13938             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13939           }
13940         if ((items >= 3) && strEQcase(list[n],"filename"))
13941           continue;
13942         if ((items >= 3) && strEQcase(list[n],"file"))
13943           {
13944             FILE
13945               *file;
13946
13947             PerlIO
13948               *io_info;
13949
13950             i++;
13951             io_info=IoIFP(sv_2io(ST(i+1)));
13952             if (io_info == (PerlIO *) NULL)
13953               {
13954                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13955                   PackageName);
13956                 continue;
13957               }
13958             file=PerlIO_findFILE(io_info);
13959             if (file == (FILE *) NULL)
13960               {
13961                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13962                   PackageName);
13963                 continue;
13964               }
13965             SetImageInfoFile(package_info->image_info,file);
13966           }
13967         if ((items >= 3) && strEQcase(list[n],"magick"))
13968           continue;
13969         n++;
13970       }
13971     list[n]=(char *) NULL;
13972     keep=list;
13973     status=ExpandFilenames(&n,&list);
13974     if (status == MagickFalse)
13975       {
13976         ThrowPerlException(exception,ResourceLimitError,
13977           "MemoryAllocationFailed",PackageName);
13978         goto PerlException;
13979       }
13980     number_images=0;
13981     for (i=0; i < n; i++)
13982     {
13983       if ((package_info->image_info->file == (FILE *) NULL) &&
13984           (package_info->image_info->blob == (void *) NULL))
13985         image=ReadImages(package_info->image_info,list[i],exception);
13986       else
13987         {
13988           image=ReadImages(package_info->image_info,
13989             package_info->image_info->filename,exception);
13990           if (image != (Image *) NULL)
13991             DisassociateImageStream(image);
13992         }
13993       if (image == (Image *) NULL)
13994         break;
13995       for ( ; image; image=image->next)
13996       {
13997         AddImageToRegistry(sv,image);
13998         rv=newRV(sv);
13999         av_push(av,sv_bless(rv,hv));
14000         SvREFCNT_dec(sv);
14001         number_images++;
14002       }
14003     }
14004     /*
14005       Free resources.
14006     */
14007     for (i=0; i < n; i++)
14008       if (list[i] != (char *) NULL)
14009         for (p=keep; list[i] != *p++; )
14010           if (*p == (char *) NULL)
14011             {
14012               list[i]=(char *) RelinquishMagickMemory(list[i]);
14013               break;
14014             }
14015
14016   PerlException:
14017     if (package_info != (struct PackageInfo *) NULL)
14018       DestroyPackageInfo(package_info);
14019     if (list && (list != keep))
14020       list=(char **) RelinquishMagickMemory(list);
14021     if (keep)
14022       keep=(char **) RelinquishMagickMemory(keep);
14023     if (length)
14024       length=(STRLEN *) RelinquishMagickMemory(length);
14025     InheritPerlException(exception,perl_exception);
14026     exception=DestroyExceptionInfo(exception);
14027     sv_setiv(perl_exception,(IV) number_images);
14028     SvPOK_on(perl_exception);
14029     ST(0)=sv_2mortal(perl_exception);
14030     XSRETURN(1);
14031   }
14032 \f
14033 #
14034 ###############################################################################
14035 #                                                                             #
14036 #                                                                             #
14037 #                                                                             #
14038 #   R e m o t e                                                               #
14039 #                                                                             #
14040 #                                                                             #
14041 #                                                                             #
14042 ###############################################################################
14043 #
14044 #
14045 void
14046 Remote(ref,...)
14047   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14048   ALIAS:
14049     RemoteCommand  = 1
14050     remote         = 2
14051     remoteCommand  = 3
14052   PPCODE:
14053   {
14054     AV
14055       *av;
14056
14057     ExceptionInfo
14058       *exception;
14059
14060     register ssize_t
14061       i;
14062
14063     SV
14064       *perl_exception,
14065       *reference;
14066
14067     struct PackageInfo
14068       *info;
14069
14070     PERL_UNUSED_VAR(ref);
14071     PERL_UNUSED_VAR(ix);
14072     exception=AcquireExceptionInfo();
14073     perl_exception=newSVpv("",0);
14074     reference=SvRV(ST(0));
14075     av=(AV *) reference;
14076     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14077       exception);
14078     for (i=1; i < items; i++)
14079       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
14080         SvPV(ST(i),na),exception);
14081     InheritPerlException(exception,perl_exception);
14082     exception=DestroyExceptionInfo(exception);
14083     SvREFCNT_dec(perl_exception);    /* throw away all errors */
14084   }
14085 \f
14086 #
14087 ###############################################################################
14088 #                                                                             #
14089 #                                                                             #
14090 #                                                                             #
14091 #   S e t                                                                     #
14092 #                                                                             #
14093 #                                                                             #
14094 #                                                                             #
14095 ###############################################################################
14096 #
14097 #
14098 void
14099 Set(ref,...)
14100   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14101   ALIAS:
14102     SetAttributes  = 1
14103     SetAttribute   = 2
14104     set            = 3
14105     setattributes  = 4
14106     setattribute   = 5
14107   PPCODE:
14108   {
14109     ExceptionInfo
14110       *exception;
14111
14112     Image
14113       *image;
14114
14115     register ssize_t
14116       i;
14117
14118     struct PackageInfo
14119       *info;
14120
14121     SV
14122       *perl_exception,
14123       *reference;  /* reference is the SV* of ref=SvIV(reference) */
14124
14125     PERL_UNUSED_VAR(ref);
14126     PERL_UNUSED_VAR(ix);
14127     exception=AcquireExceptionInfo();
14128     perl_exception=newSVpv("",0);
14129     if (sv_isobject(ST(0)) == 0)
14130       {
14131         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14132           PackageName);
14133         goto PerlException;
14134       }
14135     reference=SvRV(ST(0));
14136     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14137     if (items == 2)
14138       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
14139     else
14140       for (i=2; i < items; i+=2)
14141         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
14142
14143   PerlException:
14144     InheritPerlException(exception,perl_exception);
14145     exception=DestroyExceptionInfo(exception);
14146     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
14147     SvPOK_on(perl_exception);
14148     ST(0)=sv_2mortal(perl_exception);
14149     XSRETURN(1);
14150   }
14151 \f
14152 #
14153 ###############################################################################
14154 #                                                                             #
14155 #                                                                             #
14156 #                                                                             #
14157 #   S e t P i x e l                                                           #
14158 #                                                                             #
14159 #                                                                             #
14160 #                                                                             #
14161 ###############################################################################
14162 #
14163 #
14164 void
14165 SetPixel(ref,...)
14166   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14167   ALIAS:
14168     setpixel = 1
14169     setPixel = 2
14170   PPCODE:
14171   {
14172     AV
14173       *av;
14174
14175     char
14176       *attribute;
14177
14178     ChannelType
14179       channel,
14180       channel_mask;
14181
14182     ExceptionInfo
14183       *exception;
14184
14185     Image
14186       *image;
14187
14188     MagickBooleanType
14189       normalize;
14190
14191     RectangleInfo
14192       region;
14193
14194     register ssize_t
14195       i;
14196
14197     register Quantum
14198       *q;
14199
14200     ssize_t
14201       option;
14202
14203     struct PackageInfo
14204       *info;
14205
14206     SV
14207       *perl_exception,
14208       *reference;  /* reference is the SV* of ref=SvIV(reference) */
14209
14210     PERL_UNUSED_VAR(ref);
14211     PERL_UNUSED_VAR(ix);
14212     exception=AcquireExceptionInfo();
14213     perl_exception=newSVpv("",0);
14214     reference=SvRV(ST(0));
14215     av=(AV *) reference;
14216     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14217       exception);
14218     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14219     if (image == (Image *) NULL)
14220       {
14221         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14222           PackageName);
14223         goto PerlException;
14224       }
14225     av=(AV *) NULL;
14226     normalize=MagickTrue;
14227     region.x=0;
14228     region.y=0;
14229     region.width=image->columns;
14230     region.height=1;
14231     if (items == 1)
14232       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14233     channel=DefaultChannels;
14234     for (i=2; i < items; i+=2)
14235     {
14236       attribute=(char *) SvPV(ST(i-1),na);
14237       switch (*attribute)
14238       {
14239         case 'C':
14240         case 'c':
14241         {
14242           if (LocaleCompare(attribute,"channel") == 0)
14243             {
14244               ssize_t
14245                 option;
14246
14247               option=ParseChannelOption(SvPV(ST(i),na));
14248               if (option < 0)
14249                 {
14250                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14251                     SvPV(ST(i),na));
14252                   return;
14253                 }
14254               channel=(ChannelType) option;
14255               break;
14256             }
14257           if (LocaleCompare(attribute,"color") == 0)
14258             {
14259               if (SvTYPE(ST(i)) != SVt_RV)
14260                 {
14261                   char
14262                     message[MagickPathExtent];
14263
14264                   (void) FormatLocaleString(message,MagickPathExtent,
14265                     "invalid %.60s value",attribute);
14266                   ThrowPerlException(exception,OptionError,message,
14267                     SvPV(ST(i),na));
14268                 }
14269               av=(AV *) SvRV(ST(i));
14270               break;
14271             }
14272           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14273             attribute);
14274           break;
14275         }
14276         case 'g':
14277         case 'G':
14278         {
14279           if (LocaleCompare(attribute,"geometry") == 0)
14280             {
14281               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14282               break;
14283             }
14284           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14285             attribute);
14286           break;
14287         }
14288         case 'N':
14289         case 'n':
14290         {
14291           if (LocaleCompare(attribute,"normalize") == 0)
14292             {
14293               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14294                 SvPV(ST(i),na));
14295               if (option < 0)
14296                 {
14297                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14298                     SvPV(ST(i),na));
14299                   break;
14300                 }
14301              normalize=option != 0 ? MagickTrue : MagickFalse;
14302              break;
14303             }
14304           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14305             attribute);
14306           break;
14307         }
14308         case 'x':
14309         case 'X':
14310         {
14311           if (LocaleCompare(attribute,"x") == 0)
14312             {
14313               region.x=SvIV(ST(i));
14314               break;
14315             }
14316           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14317             attribute);
14318           break;
14319         }
14320         case 'y':
14321         case 'Y':
14322         {
14323           if (LocaleCompare(attribute,"y") == 0)
14324             {
14325               region.y=SvIV(ST(i));
14326               break;
14327             }
14328           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14329             attribute);
14330           break;
14331         }
14332         default:
14333         {
14334           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14335             attribute);
14336           break;
14337         }
14338       }
14339     }
14340     (void) SetImageStorageClass(image,DirectClass,exception);
14341     channel_mask=SetImageChannelMask(image,channel);
14342     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14343     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14344         (SvTYPE(av) != SVt_PVAV))
14345       PUSHs(&sv_undef);
14346     else
14347       {
14348         double
14349           scale;
14350
14351         register ssize_t
14352           i;
14353
14354         i=0;
14355         scale=1.0;
14356         if (normalize != MagickFalse)
14357           scale=QuantumRange;
14358         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14359             (i <= av_len(av)))
14360           {
14361             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14362               av_fetch(av,i,0)))),q);
14363             i++;
14364           }
14365         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14366             (i <= av_len(av)))
14367           {
14368             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14369               av_fetch(av,i,0)))),q);
14370             i++;
14371           }
14372         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14373             (i <= av_len(av)))
14374           {
14375             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14376               av_fetch(av,i,0)))),q);
14377             i++;
14378           }
14379         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14380             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14381           {
14382             SetPixelBlack(image,ClampToQuantum(scale*
14383               SvNV(*(av_fetch(av,i,0)))),q);
14384             i++;
14385           }
14386         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14387             (i <= av_len(av)))
14388           {
14389             SetPixelAlpha(image,ClampToQuantum(scale*
14390               SvNV(*(av_fetch(av,i,0)))),q);
14391             i++;
14392           }
14393         (void) SyncAuthenticPixels(image,exception);
14394       }
14395     (void) SetImageChannelMask(image,channel_mask);
14396
14397   PerlException:
14398     InheritPerlException(exception,perl_exception);
14399     exception=DestroyExceptionInfo(exception);
14400     SvREFCNT_dec(perl_exception);
14401   }
14402 \f
14403 #
14404 ###############################################################################
14405 #                                                                             #
14406 #                                                                             #
14407 #                                                                             #
14408 #   S e t P i x e l s                                                         #
14409 #                                                                             #
14410 #                                                                             #
14411 #                                                                             #
14412 ###############################################################################
14413 #
14414 #
14415 void
14416 SetPixels(ref,...)
14417   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14418   ALIAS:
14419     setpixels = 1
14420     setPixels = 2
14421   PPCODE:
14422   {
14423     AV
14424       *av;
14425
14426     char
14427       *attribute;
14428
14429     ChannelType
14430       channel,
14431       channel_mask;
14432
14433     ExceptionInfo
14434       *exception;
14435
14436     Image
14437       *image;
14438
14439     RectangleInfo
14440       region;
14441
14442     register ssize_t
14443       i;
14444
14445     register Quantum
14446       *q;
14447
14448     struct PackageInfo
14449       *info;
14450
14451     SV
14452       *perl_exception,
14453       *reference;  /* reference is the SV* of ref=SvIV(reference) */
14454
14455     PERL_UNUSED_VAR(ref);
14456     PERL_UNUSED_VAR(ix);
14457     exception=AcquireExceptionInfo();
14458     perl_exception=newSVpv("",0);
14459     reference=SvRV(ST(0));
14460     av=(AV *) reference;
14461     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
14462       exception);
14463     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14464     if (image == (Image *) NULL)
14465       {
14466         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14467           PackageName);
14468         goto PerlException;
14469       }
14470     av=(AV *) NULL;
14471     region.x=0;
14472     region.y=0;
14473     region.width=image->columns;
14474     region.height=1;
14475     if (items == 1)
14476       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
14477     channel=DefaultChannels;
14478     for (i=2; i < items; i+=2)
14479     {
14480       attribute=(char *) SvPV(ST(i-1),na);
14481       switch (*attribute)
14482       {
14483         case 'C':
14484         case 'c':
14485         {
14486           if (LocaleCompare(attribute,"channel") == 0)
14487             {
14488               ssize_t
14489                 option;
14490
14491               option=ParseChannelOption(SvPV(ST(i),na));
14492               if (option < 0)
14493                 {
14494                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14495                     SvPV(ST(i),na));
14496                   return;
14497                 }
14498               channel=(ChannelType) option;
14499               break;
14500             }
14501           if (LocaleCompare(attribute,"color") == 0)
14502             {
14503               if (SvTYPE(ST(i)) != SVt_RV)
14504                 {
14505                   char
14506                     message[MagickPathExtent];
14507
14508                   (void) FormatLocaleString(message,MagickPathExtent,
14509                     "invalid %.60s value",attribute);
14510                   ThrowPerlException(exception,OptionError,message,
14511                     SvPV(ST(i),na));
14512                 }
14513               av=(AV *) SvRV(ST(i));
14514               break;
14515             }
14516           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14517             attribute);
14518           break;
14519         }
14520         case 'g':
14521         case 'G':
14522         {
14523           if (LocaleCompare(attribute,"geometry") == 0)
14524             {
14525               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14526               break;
14527             }
14528           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14529             attribute);
14530           break;
14531         }
14532         case 'h':
14533         case 'H':
14534         {
14535           if (LocaleCompare(attribute,"height") == 0)
14536             {
14537               region.height=SvIV(ST(i));
14538               break;
14539             }
14540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14541             attribute);
14542           break;
14543         }
14544         case 'w':
14545         case 'W':
14546         {
14547           if (LocaleCompare(attribute,"width") == 0)
14548             {
14549               region.width=SvIV(ST(i));
14550               break;
14551             }
14552           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14553             attribute);
14554           break;
14555         }
14556         case 'x':
14557         case 'X':
14558         {
14559           if (LocaleCompare(attribute,"x") == 0)
14560             {
14561               region.x=SvIV(ST(i));
14562               break;
14563             }
14564           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14565             attribute);
14566           break;
14567         }
14568         case 'y':
14569         case 'Y':
14570         {
14571           if (LocaleCompare(attribute,"y") == 0)
14572             {
14573               region.y=SvIV(ST(i));
14574               break;
14575             }
14576           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14577             attribute);
14578           break;
14579         }
14580         default:
14581         {
14582           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14583             attribute);
14584           break;
14585         }
14586       }
14587     }
14588     (void) SetImageStorageClass(image,DirectClass,exception);
14589     channel_mask=SetImageChannelMask(image,channel);
14590     q=GetAuthenticPixels(image,region.x,region.y,region.width,region.height,
14591       exception);
14592     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14593         (SvTYPE(av) != SVt_PVAV))
14594       PUSHs(&sv_undef);
14595     else
14596       {
14597         double
14598           scale;
14599
14600         register ssize_t
14601           i,
14602           n,
14603           number_pixels;
14604
14605         i=0;
14606         n=0;
14607         scale=(double) QuantumRange;
14608         number_pixels=region.width*region.height;
14609         while ((n < number_pixels) && (i < av_len(av)))
14610         {
14611           if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14612               (i <= av_len(av)))
14613             {
14614               SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14615                 av_fetch(av,i,0)))),q);
14616               i++;
14617             }
14618           if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14619               (i <= av_len(av)))
14620             {
14621               SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14622                 av_fetch(av,i,0)))),q);
14623               i++;
14624             }
14625           if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14626               (i <= av_len(av)))
14627             {
14628               SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14629                 av_fetch(av,i,0)))),q);
14630               i++;
14631             }
14632           if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14633               (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14634             {
14635              SetPixelBlack(image,ClampToQuantum(scale*
14636                 SvNV(*(av_fetch(av,i,0)))),q);
14637               i++;
14638             }
14639           if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14640               (i <= av_len(av)))
14641             {
14642               SetPixelAlpha(image,ClampToQuantum(scale*
14643                 SvNV(*(av_fetch(av,i,0)))),q);
14644               i++;
14645             }
14646                 n++;
14647                 q+=image->number_channels;
14648         }
14649         (void) SyncAuthenticPixels(image,exception);
14650       }
14651     (void) SetImageChannelMask(image,channel_mask);
14652
14653   PerlException:
14654     InheritPerlException(exception,perl_exception);
14655     exception=DestroyExceptionInfo(exception);
14656     SvREFCNT_dec(perl_exception);
14657   }
14658 \f
14659 #
14660 ###############################################################################
14661 #                                                                             #
14662 #                                                                             #
14663 #                                                                             #
14664 #   S m u s h                                                                 #
14665 #                                                                             #
14666 #                                                                             #
14667 #                                                                             #
14668 ###############################################################################
14669 #
14670 #
14671 void
14672 Smush(ref,...)
14673   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14674   ALIAS:
14675     SmushImage  = 1
14676     smush       = 2
14677     smushimage  = 3
14678   PPCODE:
14679   {
14680     AV
14681       *av;
14682
14683     char
14684       *attribute;
14685
14686     ExceptionInfo
14687       *exception;
14688
14689     HV
14690       *hv;
14691
14692     Image
14693       *image;
14694
14695     register ssize_t
14696       i;
14697
14698     ssize_t
14699       offset,
14700       stack;
14701
14702     struct PackageInfo
14703       *info;
14704
14705     SV
14706       *av_reference,
14707       *perl_exception,
14708       *reference,
14709       *rv,
14710       *sv;
14711
14712     PERL_UNUSED_VAR(ref);
14713     PERL_UNUSED_VAR(ix);
14714     exception=AcquireExceptionInfo();
14715     perl_exception=newSVpv("",0);
14716     sv=NULL;
14717     attribute=NULL;
14718     av=NULL;
14719     if (sv_isobject(ST(0)) == 0)
14720       {
14721         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14722           PackageName);
14723         goto PerlException;
14724       }
14725     reference=SvRV(ST(0));
14726     hv=SvSTASH(reference);
14727     av=newAV();
14728     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14729     SvREFCNT_dec(av);
14730     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14731     if (image == (Image *) NULL)
14732       {
14733         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14734           PackageName);
14735         goto PerlException;
14736       }
14737     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14738     /*
14739       Get options.
14740     */
14741     offset=0;
14742     stack=MagickTrue;
14743     for (i=2; i < items; i+=2)
14744     {
14745       attribute=(char *) SvPV(ST(i-1),na);
14746       switch (*attribute)
14747       {
14748         case 'O':
14749         case 'o':
14750         {
14751           if (LocaleCompare(attribute,"offset") == 0)
14752             {
14753               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14754               break;
14755             }
14756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14757             attribute);
14758           break;
14759         }
14760         case 'S':
14761         case 's':
14762         {
14763           if (LocaleCompare(attribute,"stack") == 0)
14764             {
14765               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14766                 SvPV(ST(i),na));
14767               if (stack < 0)
14768                 {
14769                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14770                     SvPV(ST(i),na));
14771                   return;
14772                 }
14773               break;
14774             }
14775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14776             attribute);
14777           break;
14778         }
14779         default:
14780         {
14781           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14782             attribute);
14783           break;
14784         }
14785       }
14786     }
14787     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14788       exception);
14789     if (image == (Image *) NULL)
14790       goto PerlException;
14791     for ( ; image; image=image->next)
14792     {
14793       AddImageToRegistry(sv,image);
14794       rv=newRV(sv);
14795       av_push(av,sv_bless(rv,hv));
14796       SvREFCNT_dec(sv);
14797     }
14798     exception=DestroyExceptionInfo(exception);
14799     ST(0)=av_reference;
14800     SvREFCNT_dec(perl_exception);
14801     XSRETURN(1);
14802
14803   PerlException:
14804     InheritPerlException(exception,perl_exception);
14805     exception=DestroyExceptionInfo(exception);
14806     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14807     SvPOK_on(perl_exception);
14808     ST(0)=sv_2mortal(perl_exception);
14809     XSRETURN(1);
14810   }
14811 \f
14812 #
14813 ###############################################################################
14814 #                                                                             #
14815 #                                                                             #
14816 #                                                                             #
14817 #   S t a t i s t i c s                                                       #
14818 #                                                                             #
14819 #                                                                             #
14820 #                                                                             #
14821 ###############################################################################
14822 #
14823 #
14824 void
14825 Statistics(ref)
14826   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14827   ALIAS:
14828     StatisticsImage = 1
14829     statistics      = 2
14830     statisticsimage = 3
14831   PPCODE:
14832   {
14833 #define ChannelStatistics(channel) \
14834 { \
14835   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14836     (double) channel_statistics[channel].depth); \
14837   PUSHs(sv_2mortal(newSVpv(message,0))); \
14838   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14839     channel_statistics[channel].minima/QuantumRange); \
14840   PUSHs(sv_2mortal(newSVpv(message,0))); \
14841   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14842     channel_statistics[channel].maxima/QuantumRange); \
14843   PUSHs(sv_2mortal(newSVpv(message,0))); \
14844   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14845     channel_statistics[channel].mean/QuantumRange); \
14846   PUSHs(sv_2mortal(newSVpv(message,0))); \
14847   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14848     channel_statistics[channel].standard_deviation/QuantumRange); \
14849   PUSHs(sv_2mortal(newSVpv(message,0))); \
14850   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14851     channel_statistics[channel].kurtosis); \
14852   PUSHs(sv_2mortal(newSVpv(message,0))); \
14853   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14854     channel_statistics[channel].skewness); \
14855   PUSHs(sv_2mortal(newSVpv(message,0))); \
14856   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14857     channel_statistics[channel].entropy); \
14858   PUSHs(sv_2mortal(newSVpv(message,0))); \
14859 }
14860
14861     AV
14862       *av;
14863
14864     char
14865       message[MagickPathExtent];
14866
14867     ChannelStatistics
14868       *channel_statistics;
14869
14870     ExceptionInfo
14871       *exception;
14872
14873     Image
14874       *image;
14875
14876     ssize_t
14877       count;
14878
14879     struct PackageInfo
14880       *info;
14881
14882     SV
14883       *perl_exception,
14884       *reference;
14885
14886     PERL_UNUSED_VAR(ref);
14887     PERL_UNUSED_VAR(ix);
14888     exception=AcquireExceptionInfo();
14889     perl_exception=newSVpv("",0);
14890     av=NULL;
14891     if (sv_isobject(ST(0)) == 0)
14892       {
14893         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14894           PackageName);
14895         goto PerlException;
14896       }
14897     reference=SvRV(ST(0));
14898     av=newAV();
14899     SvREFCNT_dec(av);
14900     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14901     if (image == (Image *) NULL)
14902       {
14903         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14904           PackageName);
14905         goto PerlException;
14906       }
14907     count=0;
14908     for ( ; image; image=image->next)
14909     {
14910       register size_t
14911         i;
14912
14913       channel_statistics=GetImageStatistics(image,exception);
14914       if (channel_statistics == (ChannelStatistics *) NULL)
14915         continue;
14916       count++;
14917       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14918       {
14919         PixelChannel channel=GetPixelChannelChannel(image,i);
14920         PixelTrait traits=GetPixelChannelTraits(image,channel);
14921         if (traits == UndefinedPixelTrait)
14922           continue;
14923         EXTEND(sp,8*(i+1)*count);
14924         ChannelStatistics(channel);
14925       }
14926       EXTEND(sp,8*(i+1)*count);
14927       ChannelStatistics(CompositePixelChannel);
14928       channel_statistics=(ChannelStatistics *)
14929         RelinquishMagickMemory(channel_statistics);
14930     }
14931
14932   PerlException:
14933     InheritPerlException(exception,perl_exception);
14934     exception=DestroyExceptionInfo(exception);
14935     SvREFCNT_dec(perl_exception);
14936   }
14937 \f
14938 #
14939 ###############################################################################
14940 #                                                                             #
14941 #                                                                             #
14942 #                                                                             #
14943 #   S y n c A u t h e n t i c P i x e l s                                     #
14944 #                                                                             #
14945 #                                                                             #
14946 #                                                                             #
14947 ###############################################################################
14948 #
14949 #
14950 void
14951 SyncAuthenticPixels(ref,...)
14952   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
14953   ALIAS:
14954     Syncauthenticpixels = 1
14955     SyncImagePixels = 2
14956     syncimagepixels = 3
14957   CODE:
14958   {
14959     ExceptionInfo
14960       *exception;
14961
14962     Image
14963       *image;
14964
14965     MagickBooleanType
14966       status;
14967
14968     struct PackageInfo
14969       *info;
14970
14971     SV
14972       *perl_exception,
14973       *reference;
14974
14975     PERL_UNUSED_VAR(ref);
14976     PERL_UNUSED_VAR(ix);
14977     exception=AcquireExceptionInfo();
14978     perl_exception=newSVpv("",0);
14979     if (sv_isobject(ST(0)) == 0)
14980       {
14981         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14982           PackageName);
14983         goto PerlException;
14984       }
14985
14986     reference=SvRV(ST(0));
14987     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14988     if (image == (Image *) NULL)
14989       {
14990         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14991           PackageName);
14992         goto PerlException;
14993       }
14994
14995     status=SyncAuthenticPixels(image,exception);
14996     if (status != MagickFalse)
14997       return;
14998
14999   PerlException:
15000     InheritPerlException(exception,perl_exception);
15001     exception=DestroyExceptionInfo(exception);
15002     SvREFCNT_dec(perl_exception);  /* throw away all errors */
15003   }
15004
15005
15006 #
15007 ###############################################################################
15008 #                                                                             #
15009 #                                                                             #
15010 #                                                                             #
15011 #   W r i t e                                                                 #
15012 #                                                                             #
15013 #                                                                             #
15014 #                                                                             #
15015 ###############################################################################
15016 #
15017 #
15018 void
15019 Write(ref,...)
15020   Image::Magick::@MAGICK_ABI_SUFFIX@ ref = NO_INIT
15021   ALIAS:
15022     WriteImage    = 1
15023     write         = 2
15024     writeimage    = 3
15025   PPCODE:
15026   {
15027     char
15028       filename[MagickPathExtent];
15029
15030     ExceptionInfo
15031       *exception;
15032
15033     Image
15034       *image,
15035       *next;
15036
15037     register ssize_t
15038       i;
15039
15040     ssize_t
15041       number_images,
15042       scene;
15043
15044     struct PackageInfo
15045       *info,
15046       *package_info;
15047
15048     SV
15049       *perl_exception,
15050       *reference;
15051
15052     PERL_UNUSED_VAR(ref);
15053     PERL_UNUSED_VAR(ix);
15054     exception=AcquireExceptionInfo();
15055     perl_exception=newSVpv("",0);
15056     number_images=0;
15057     package_info=(struct PackageInfo *) NULL;
15058     if (sv_isobject(ST(0)) == 0)
15059       {
15060         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
15061           PackageName);
15062         goto PerlException;
15063       }
15064     reference=SvRV(ST(0));
15065     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
15066     if (image == (Image *) NULL)
15067       {
15068         ThrowPerlException(exception,OptionError,"NoImagesDefined",
15069           PackageName);
15070         goto PerlException;
15071       }
15072     scene=0;
15073     for (next=image; next; next=next->next)
15074       next->scene=scene++;
15075     package_info=ClonePackageInfo(info,exception);
15076     if (items == 2)
15077       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
15078     else
15079       if (items > 2)
15080         for (i=2; i < items; i+=2)
15081           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
15082             exception);
15083     (void) CopyMagickString(filename,package_info->image_info->filename,
15084       MagickPathExtent);
15085     for (next=image; next; next=next->next)
15086       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
15087     *package_info->image_info->magick='\0';
15088     SetImageInfo(package_info->image_info,(unsigned int)
15089       GetImageListLength(image),exception);
15090     for (next=image; next; next=next->next)
15091     {
15092       (void) WriteImage(package_info->image_info,next,exception);
15093       number_images++;
15094       if (package_info->image_info->adjoin)
15095         break;
15096     }
15097
15098   PerlException:
15099     if (package_info != (struct PackageInfo *) NULL)
15100       DestroyPackageInfo(package_info);
15101     InheritPerlException(exception,perl_exception);
15102     exception=DestroyExceptionInfo(exception);
15103     sv_setiv(perl_exception,(IV) number_images);
15104     SvPOK_on(perl_exception);
15105     ST(0)=sv_2mortal(perl_exception);
15106     XSRETURN(1);
15107   }