]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
279a89adfe39f57d430ebd508cacb78f4c39e0ae
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MaxArguments  33
78 #ifndef na
79 #define na  PL_na
80 #endif
81 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
82 #define PackageName   "Image::Magick"
83 #if PERL_VERSION <= 6
84 #define PerlIO  FILE
85 #define PerlIO_importFILE(f, fl)  (f)
86 #define PerlIO_findFILE(f)  NULL
87 #endif
88 #ifndef sv_undef
89 #define sv_undef  PL_sv_undef
90 #endif
91
92 #define AddImageToRegistry(sv,image) \
93 { \
94   if (magick_registry != (SplayTreeInfo *) NULL) \
95     { \
96       (void) AddValueToSplayTree(magick_registry,image,image); \
97       (sv)=newSViv(PTR2IV(image)); \
98     } \
99 }
100
101 #define DeleteImageFromRegistry(reference,image) \
102 { \
103   if (magick_registry != (SplayTreeInfo *) NULL) \
104     { \
105       if (GetImageReferenceCount(image) == 1) \
106        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
107       image=DestroyImage(image); \
108       sv_setiv(reference,0); \
109     } \
110 }
111
112 #define InheritPerlException(exception,perl_exception) \
113 { \
114   char \
115     message[MaxTextExtent]; \
116  \
117   if ((exception)->severity != UndefinedException) \
118     { \
119       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
120         (exception)->severity, (exception)->reason ? \
121         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
122         "Unknown", (exception)->description ? " (" : "", \
123         (exception)->description ? GetLocaleExceptionMessage( \
124         (exception)->severity,(exception)->description) : "", \
125         (exception)->description ? ")" : ""); \
126       if ((perl_exception) != (SV *) NULL) \
127         { \
128           if (SvCUR(perl_exception)) \
129             sv_catpv(perl_exception,"\n"); \
130           sv_catpv(perl_exception,message); \
131         } \
132     } \
133 }
134
135 #define ThrowPerlException(exception,severity,tag,reason) \
136   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
137     tag,"`%s'",reason); \
138 \f
139 /*
140   Typedef and structure declarations.
141 */
142 typedef enum
143 {
144   ArrayReference = (~0),
145   RealReference = (~0)-1,
146   FileReference = (~0)-2,
147   ImageReference = (~0)-3,
148   IntegerReference = (~0)-4,
149   StringReference = (~0)-5
150 } MagickReference;
151
152 typedef struct _Arguments
153 {
154   const char
155     *method;
156
157   ssize_t
158     type;
159 } Arguments;
160
161 struct ArgumentList
162 {
163   ssize_t
164     integer_reference;
165
166   double
167     real_reference;
168
169   const char
170     *string_reference;
171
172   Image
173     *image_reference;
174
175   SV
176     *array_reference;
177
178   FILE
179     *file_reference;
180
181   size_t
182     length;
183 };
184
185 struct PackageInfo
186 {
187   ImageInfo
188     *image_info;
189 };
190
191 typedef void
192   *Image__Magick;  /* data type for the Image::Magick package */
193 \f
194 /*
195   Static declarations.
196 */
197 static struct
198   Methods
199   {
200     const char
201       *name;
202
203     Arguments
204       arguments[MaxArguments];
205   } Methods[] =
206   {
207     { "Comment", { {"comment", StringReference} } },
208     { "Label", { {"label", StringReference} } },
209     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
210       {"channel", MagickChannelOptions} } },
211     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
212     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
213       {"height", IntegerReference}, {"fill", StringReference},
214       {"bordercolor", StringReference}, {"color", StringReference},
215       {"compose", MagickComposeOptions} } },
216     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
217       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
218     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
219       {"height", IntegerReference}, {"x", IntegerReference},
220       {"y", IntegerReference} } },
221     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
222       {"height", IntegerReference}, {"x", IntegerReference},
223       {"y", IntegerReference}, {"fuzz", StringReference},
224       {"gravity", MagickGravityOptions} } },
225     { "Despeckle", },
226     { "Edge", { {"radius", RealReference} } },
227     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
228       {"sigma", RealReference} } },
229     { "Enhance", },
230     { "Flip", },
231     { "Flop", },
232     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
233       {"height", IntegerReference}, {"inner", IntegerReference},
234       {"outer", IntegerReference}, {"fill", StringReference},
235       {"color", StringReference}, {"compose", MagickComposeOptions} } },
236     { "Implode", { {"amount", RealReference},
237       {"interpolate", MagickInterpolateOptions} } },
238     { "Magnify", },
239     { "MedianFilter", { {"geometry", StringReference},
240       {"width", IntegerReference}, {"height", IntegerReference},
241       {"channel", MagickChannelOptions} } },
242     { "Minify", },
243     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
244     { "ReduceNoise", { {"geometry", StringReference},
245       {"width", IntegerReference},{"height", IntegerReference},
246       {"channel", MagickChannelOptions} } },
247     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
248       {"y", IntegerReference} } },
249     { "Rotate", { {"degrees", RealReference},
250       {"background", StringReference} } },
251     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
252       {"height", IntegerReference} } },
253     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
254       {"height", IntegerReference} } },
255     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
256       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
257     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
258       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
259     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
260       {"y", RealReference}, { "fill", StringReference},
261       {"color", StringReference} } },
262     { "Spread", { {"radius", RealReference},
263       {"interpolate", MagickInterpolateOptions} } },
264     { "Swirl", { {"degrees", RealReference},
265       {"interpolate", MagickInterpolateOptions} } },
266     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
267       {"height", IntegerReference}, {"filter", MagickFilterOptions},
268       {"support", StringReference } } },
269     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", RealReference } } },
272     { "Annotate", { {"text", StringReference}, {"font", StringReference},
273       {"pointsize", RealReference}, {"density", StringReference},
274       {"undercolor", StringReference}, {"stroke", StringReference},
275       {"fill", StringReference}, {"geometry", StringReference},
276       {"sans", StringReference}, {"x", RealReference},
277       {"y", RealReference}, {"gravity", MagickGravityOptions},
278       {"translate", StringReference}, {"scale", StringReference},
279       {"rotate", RealReference}, {"skewX", RealReference},
280       {"skewY", RealReference}, {"strokewidth", RealReference},
281       {"antialias", MagickBooleanOptions}, {"family", StringReference},
282       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
283       {"weight", IntegerReference}, {"align", MagickAlignOptions},
284       {"encoding", StringReference}, {"affine", ArrayReference},
285       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
286       {"tile", ImageReference}, {"kerning", RealReference},
287       {"interline-spacing", RealReference},
288       {"interword-spacing", RealReference},
289       {"direction", MagickDirectionOptions} } },
290     { "ColorFloodfill", { {"geometry", StringReference},
291       {"x", IntegerReference}, {"y", IntegerReference},
292       {"fill", StringReference}, {"bordercolor", StringReference},
293       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
294     { "Composite", { {"image", ImageReference},
295       {"compose", MagickComposeOptions}, {"geometry", StringReference},
296       {"x", IntegerReference}, {"y", IntegerReference},
297       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
298       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
299       {"color", StringReference}, {"mask", ImageReference},
300       {"channel", MagickChannelOptions},
301       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
302       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
303     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
304     { "CycleColormap", { {"display", IntegerReference} } },
305     { "Draw", { {"primitive", MagickPrimitiveOptions},
306       {"points", StringReference}, {"method", MagickMethodOptions},
307       {"stroke", StringReference}, {"fill", StringReference},
308       {"strokewidth", RealReference}, {"font", StringReference},
309       {"bordercolor", StringReference}, {"x", RealReference},
310       {"y", RealReference}, {"translate", StringReference},
311       {"scale", StringReference}, {"rotate", RealReference},
312       {"skewX", RealReference}, {"skewY", RealReference},
313       {"tile", ImageReference}, {"pointsize", RealReference},
314       {"antialias", MagickBooleanOptions}, {"density", StringReference},
315       {"linewidth", RealReference}, {"affine", ArrayReference},
316       {"stroke-dashoffset", RealReference},
317       {"stroke-dasharray", ArrayReference},
318       {"interpolate", MagickInterpolateOptions},
319       {"origin", StringReference}, {"text", StringReference},
320       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
321       {"vector-graphics", StringReference}, {"kerning", RealReference},
322       {"interline-spacing", RealReference},
323       {"interword-spacing", RealReference},
324       {"direction", MagickDirectionOptions} } },
325     { "Equalize", { {"channel", MagickChannelOptions} } },
326     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
327       {"red", RealReference}, {"green", RealReference},
328       {"blue", RealReference} } },
329     { "Map", { {"image", ImageReference},
330       {"dither-method", MagickDitherOptions} } },
331     { "MatteFloodfill", { {"geometry", StringReference},
332       {"x", IntegerReference}, {"y", IntegerReference},
333       {"opacity", StringReference}, {"bordercolor", StringReference},
334       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
335     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
336       {"saturation", RealReference}, {"whiteness", RealReference},
337       {"brightness", RealReference}, {"lightness", RealReference},
338       {"blackness", RealReference} } },
339     { "Negate", { {"gray", MagickBooleanOptions},
340       {"channel", MagickChannelOptions} } },
341     { "Normalize", { {"channel", MagickChannelOptions} } },
342     { "NumberColors", },
343     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
344       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
345       {"invert", MagickBooleanOptions} } },
346     { "Quantize", { {"colors", IntegerReference},
347       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
348       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
349       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
350       {"dither-method", MagickDitherOptions} } },
351     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
352       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
353     { "Segment", { {"geometry", StringReference},
354       {"cluster-threshold", RealReference},
355       {"smoothing-threshold", RealReference},
356       {"colorspace", MagickColorspaceOptions},
357       {"verbose", MagickBooleanOptions} } },
358     { "Signature", },
359     { "Solarize", { {"geometry", StringReference},
360       {"threshold", StringReference} } },
361     { "Sync", },
362     { "Texture", { {"texture", ImageReference} } },
363     { "Evaluate", { {"value", RealReference},
364       {"operator", MagickEvaluateOptions},
365       {"channel", MagickChannelOptions} } },
366     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
367       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
368     { "Threshold", { {"threshold", StringReference},
369       {"channel", MagickChannelOptions} } },
370     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
371       {"sigma", RealReference} } },
372     { "Trim", { {"fuzz", StringReference} } },
373     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
374       {"wavelength", RealReference},
375       {"interpolate", MagickInterpolateOptions} } },
376     { "Separate", { {"channel", MagickChannelOptions} } },
377     { "Condense", },
378     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
379       {"y", IntegerReference} } },
380     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
381     { "Deconstruct", },
382     { "GaussianBlur", { {"geometry", StringReference},
383       {"radius", RealReference}, {"sigma", RealReference},
384       {"channel", MagickChannelOptions} } },
385     { "Convolve", { {"coefficients", ArrayReference},
386       {"channel", MagickChannelOptions}, {"bias", StringReference},
387       {"kernel", StringReference} } },
388     { "Profile", { {"name", StringReference}, {"profile", StringReference},
389       { "rendering-intent", MagickIntentOptions},
390       { "black-point-compensation", MagickBooleanOptions} } },
391     { "UnsharpMask", { {"geometry", StringReference},
392       {"radius", RealReference}, {"sigma", RealReference},
393       {"gain", RealReference}, {"threshold", RealReference},
394       {"channel", MagickChannelOptions} } },
395     { "MotionBlur", { {"geometry", StringReference},
396       {"radius", RealReference}, {"sigma", RealReference},
397       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
398     { "OrderedDither", { {"threshold", StringReference},
399       {"channel", MagickChannelOptions} } },
400     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
401       {"height", IntegerReference} } },
402     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
403       {"white-point", RealReference}, {"gamma", RealReference},
404       {"channel", MagickChannelOptions}, {"level", StringReference} } },
405     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
406     { "AffineTransform", { {"affine", ArrayReference},
407       {"translate", StringReference}, {"scale", StringReference},
408       {"rotate", RealReference}, {"skewX", RealReference},
409       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
410       {"background", StringReference} } },
411     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
412     { "AdaptiveThreshold", { {"geometry", StringReference},
413       {"width", IntegerReference}, {"height", IntegerReference} } },
414     { "Resample", { {"density", StringReference}, {"x", RealReference},
415       {"y", RealReference}, {"filter", MagickFilterOptions},
416       {"support", RealReference } } },
417     { "Describe", { {"file", FileReference} } },
418     { "BlackThreshold", { {"threshold", StringReference},
419       {"channel", MagickChannelOptions} } },
420     { "WhiteThreshold", { {"threshold", StringReference},
421       {"channel", MagickChannelOptions} } },
422     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
423       {"channel", MagickChannelOptions} } },
424     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
425       {"height", IntegerReference} } },
426     { "Strip", },
427     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
428     { "Channel", { {"channel", MagickChannelOptions} } },
429     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
430       {"height", IntegerReference}, {"x", IntegerReference},
431       {"y", IntegerReference}, {"fuzz", StringReference},
432       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
433     { "Posterize", { {"levels", IntegerReference},
434       {"dither", MagickBooleanOptions} } },
435     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
436       {"sigma", RealReference}, {"x", IntegerReference},
437       {"y", IntegerReference} } },
438     { "Identify", { {"file", FileReference}, {"features", StringReference},
439       {"unique", MagickBooleanOptions} } },
440     { "SepiaTone", { {"threshold", RealReference} } },
441     { "SigmoidalContrast", { {"geometry", StringReference},
442       {"contrast", RealReference}, {"mid-point", RealReference},
443       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
444     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
445       {"height", IntegerReference}, {"x", IntegerReference},
446       {"y", IntegerReference}, {"fuzz", StringReference},
447       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
448     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
449       {"sigma", RealReference}, {"x", IntegerReference},
450       {"y", IntegerReference}, {"background", StringReference} } },
451     { "ContrastStretch", { {"levels", StringReference},
452       {"black-point", RealReference},{"white-point", RealReference},
453       {"channel", MagickChannelOptions} } },
454     { "Sans0", },
455     { "Sans1", },
456     { "AdaptiveSharpen", { {"geometry", StringReference},
457       {"radius", RealReference}, {"sigma", RealReference},
458       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
459     { "Transpose", },
460     { "Transverse", },
461     { "AutoOrient", },
462     { "AdaptiveBlur", { {"geometry", StringReference},
463       {"radius", RealReference}, {"sigma", RealReference},
464       {"channel", MagickChannelOptions} } },
465     { "Sketch", { {"geometry", StringReference},
466       {"radius", RealReference}, {"sigma", RealReference},
467       {"angle", RealReference} } },
468     { "UniqueColors", },
469     { "AdaptiveResize", { {"geometry", StringReference},
470       {"width", IntegerReference}, {"height", IntegerReference},
471       {"filter", MagickFilterOptions}, {"support", StringReference },
472       {"blur", RealReference } } },
473     { "ClipMask", { {"mask", ImageReference} } },
474     { "LinearStretch", { {"levels", StringReference},
475       {"black-point", RealReference},{"white-point", RealReference} } },
476     { "ColorMatrix", { {"matrix", ArrayReference} } },
477     { "Mask", { {"mask", ImageReference} } },
478     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
479       {"font", StringReference}, {"stroke", StringReference},
480       {"fill", StringReference}, {"strokewidth", RealReference},
481       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
482       {"background", StringReference},
483       {"interpolate", MagickInterpolateOptions} } },
484     { "FloodfillPaint", { {"geometry", StringReference},
485       {"x", IntegerReference}, {"y", IntegerReference},
486       {"fill", StringReference}, {"bordercolor", StringReference},
487       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
488       {"invert", MagickBooleanOptions} } },
489     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
490       {"virtual-pixel", MagickVirtualPixelOptions},
491       {"best-fit", MagickBooleanOptions} } },
492     { "Clut", { {"image", ImageReference},
493       {"interpolate", MagickInterpolateOptions},
494       {"channel", MagickChannelOptions} } },
495     { "LiquidRescale", { {"geometry", StringReference},
496       {"width", IntegerReference}, {"height", IntegerReference},
497       {"delta-x", RealReference}, {"rigidity", RealReference } } },
498     { "Encipher", { {"passphrase", StringReference} } },
499     { "Decipher", { {"passphrase", StringReference} } },
500     { "Deskew", { {"geometry", StringReference},
501       {"threshold", StringReference} } },
502     { "Remap", { {"image", ImageReference},
503       {"dither-method", MagickDitherOptions} } },
504     { "SparseColor", { {"points", ArrayReference},
505       {"method", MagickSparseColorOptions},
506       {"virtual-pixel", MagickVirtualPixelOptions},
507       {"channel", MagickChannelOptions} } },
508     { "Function", { {"parameters", ArrayReference},
509       {"function", MagickFunctionOptions},
510       {"virtual-pixel", MagickVirtualPixelOptions} } },
511     { "SelectiveBlur", { {"geometry", StringReference},
512       {"radius", RealReference}, {"sigma", RealReference},
513       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
514     { "HaldClut", { {"image", ImageReference},
515       {"channel", MagickChannelOptions} } },
516     { "BlueShift", { {"factor", StringReference} } },
517     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
518     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "ColorDecisionList", {
520       {"color-correction-collection", StringReference} } },
521     { "AutoGamma", { {"channel", MagickChannelOptions} } },
522     { "AutoLevel", { {"channel", MagickChannelOptions} } },
523     { "LevelColors", { {"invert", MagickBooleanOptions},
524       {"black-point", StringReference}, {"white-point", StringReference},
525       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
526     { "Clamp", { {"channel", MagickChannelOptions} } },
527     { "BrightnessContrast", { {"levels", StringReference},
528       {"brightness", RealReference},{"contrast", RealReference},
529       {"channel", MagickChannelOptions} } },
530     { "Morphology", { {"kernel", StringReference},
531       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
532       {"iterations", IntegerReference} } },
533     { "Sans", { {"matrix", ArrayReference} } },
534     { "Color", { {"color", StringReference} } },
535     { "Mode", { {"geometry", StringReference},
536       {"width", IntegerReference},{"height", IntegerReference},
537       {"channel", MagickChannelOptions} } },
538     { "Statistic", { {"geometry", StringReference},
539       {"width", IntegerReference},{"height", IntegerReference},
540       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
541     { "Perceptible", { {"epsilon", RealReference},
542       {"channel", MagickChannelOptions} } },
543     { "Poly", { {"terms", ArrayReference},
544       {"channel", MagickChannelOptions} } },
545     { "Grayscale", { {"method", MagickNoiseOptions} } },
546   };
547
548 static SplayTreeInfo
549   *magick_registry = (SplayTreeInfo *) NULL;
550 \f
551 /*
552   Forward declarations.
553 */
554 static Image
555   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
556
557 static ssize_t
558   strEQcase(const char *,const char *);
559 \f
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 %                                                                             %
563 %                                                                             %
564 %                                                                             %
565 %   C l o n e P a c k a g e I n f o                                           %
566 %                                                                             %
567 %                                                                             %
568 %                                                                             %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
572 %  a new one.
573 %
574 %  The format of the ClonePackageInfo routine is:
575 %
576 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
577 %        exception)
578 %
579 %  A description of each parameter follows:
580 %
581 %    o info: a structure of type info.
582 %
583 %    o exception: Return any errors or warnings in this structure.
584 %
585 */
586 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
587   ExceptionInfo *exception)
588 {
589   struct PackageInfo
590     *clone_info;
591
592   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
593   if (clone_info == (struct PackageInfo *) NULL)
594     {
595       ThrowPerlException(exception,ResourceLimitError,
596         "UnableToClonePackageInfo",PackageName);
597       return((struct PackageInfo *) NULL);
598     }
599   if (info == (struct PackageInfo *) NULL)
600     {
601       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
602       return(clone_info);
603     }
604   *clone_info=(*info);
605   clone_info->image_info=CloneImageInfo(info->image_info);
606   return(clone_info);
607 }
608 \f
609 /*
610 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
611 %                                                                             %
612 %                                                                             %
613 %                                                                             %
614 %   c o n s t a n t                                                           %
615 %                                                                             %
616 %                                                                             %
617 %                                                                             %
618 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
619 %
620 %  constant() returns a double value for the specified name.
621 %
622 %  The format of the constant routine is:
623 %
624 %      double constant(char *name,ssize_t sans)
625 %
626 %  A description of each parameter follows:
627 %
628 %    o value: Method constant returns a double value for the specified name.
629 %
630 %    o name: The name of the constant.
631 %
632 %    o sans: This integer value is not used.
633 %
634 */
635 static double constant(char *name,ssize_t sans)
636 {
637   (void) sans;
638   errno=0;
639   switch (*name)
640   {
641     case 'B':
642     {
643       if (strEQ(name,"BlobError"))
644         return(BlobError);
645       if (strEQ(name,"BlobWarning"))
646         return(BlobWarning);
647       break;
648     }
649     case 'C':
650     {
651       if (strEQ(name,"CacheError"))
652         return(CacheError);
653       if (strEQ(name,"CacheWarning"))
654         return(CacheWarning);
655       if (strEQ(name,"CoderError"))
656         return(CoderError);
657       if (strEQ(name,"CoderWarning"))
658         return(CoderWarning);
659       if (strEQ(name,"ConfigureError"))
660         return(ConfigureError);
661       if (strEQ(name,"ConfigureWarning"))
662         return(ConfigureWarning);
663       if (strEQ(name,"CorruptImageError"))
664         return(CorruptImageError);
665       if (strEQ(name,"CorruptImageWarning"))
666         return(CorruptImageWarning);
667       break;
668     }
669     case 'D':
670     {
671       if (strEQ(name,"DelegateError"))
672         return(DelegateError);
673       if (strEQ(name,"DelegateWarning"))
674         return(DelegateWarning);
675       if (strEQ(name,"DrawError"))
676         return(DrawError);
677       if (strEQ(name,"DrawWarning"))
678         return(DrawWarning);
679       break;
680     }
681     case 'E':
682     {
683       if (strEQ(name,"ErrorException"))
684         return(ErrorException);
685       if (strEQ(name,"ExceptionError"))
686         return(CoderError);
687       if (strEQ(name,"ExceptionWarning"))
688         return(CoderWarning);
689       break;
690     }
691     case 'F':
692     {
693       if (strEQ(name,"FatalErrorException"))
694         return(FatalErrorException);
695       if (strEQ(name,"FileOpenError"))
696         return(FileOpenError);
697       if (strEQ(name,"FileOpenWarning"))
698         return(FileOpenWarning);
699       break;
700     }
701     case 'I':
702     {
703       if (strEQ(name,"ImageError"))
704         return(ImageError);
705       if (strEQ(name,"ImageWarning"))
706         return(ImageWarning);
707       break;
708     }
709     case 'M':
710     {
711       if (strEQ(name,"MaxRGB"))
712         return(QuantumRange);
713       if (strEQ(name,"MissingDelegateError"))
714         return(MissingDelegateError);
715       if (strEQ(name,"MissingDelegateWarning"))
716         return(MissingDelegateWarning);
717       if (strEQ(name,"ModuleError"))
718         return(ModuleError);
719       if (strEQ(name,"ModuleWarning"))
720         return(ModuleWarning);
721       break;
722     }
723     case 'O':
724     {
725       if (strEQ(name,"Opaque"))
726         return(OpaqueAlpha);
727       if (strEQ(name,"OptionError"))
728         return(OptionError);
729       if (strEQ(name,"OptionWarning"))
730         return(OptionWarning);
731       break;
732     }
733     case 'Q':
734     {
735       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
736         return(MAGICKCORE_QUANTUM_DEPTH);
737       if (strEQ(name,"QuantumDepth"))
738         return(MAGICKCORE_QUANTUM_DEPTH);
739       if (strEQ(name,"QuantumRange"))
740         return(QuantumRange);
741       break;
742     }
743     case 'R':
744     {
745       if (strEQ(name,"ResourceLimitError"))
746         return(ResourceLimitError);
747       if (strEQ(name,"ResourceLimitWarning"))
748         return(ResourceLimitWarning);
749       if (strEQ(name,"RegistryError"))
750         return(RegistryError);
751       if (strEQ(name,"RegistryWarning"))
752         return(RegistryWarning);
753       break;
754     }
755     case 'S':
756     {
757       if (strEQ(name,"StreamError"))
758         return(StreamError);
759       if (strEQ(name,"StreamWarning"))
760         return(StreamWarning);
761       if (strEQ(name,"Success"))
762         return(0);
763       break;
764     }
765     case 'T':
766     {
767       if (strEQ(name,"Transparent"))
768         return(TransparentAlpha);
769       if (strEQ(name,"TypeError"))
770         return(TypeError);
771       if (strEQ(name,"TypeWarning"))
772         return(TypeWarning);
773       break;
774     }
775     case 'W':
776     {
777       if (strEQ(name,"WarningException"))
778         return(WarningException);
779       break;
780     }
781     case 'X':
782     {
783       if (strEQ(name,"XServerError"))
784         return(XServerError);
785       if (strEQ(name,"XServerWarning"))
786         return(XServerWarning);
787       break;
788     }
789   }
790   errno=EINVAL;
791   return(0);
792 }
793 \f
794 /*
795 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
796 %                                                                             %
797 %                                                                             %
798 %                                                                             %
799 %   D e s t r o y P a c k a g e I n f o                                       %
800 %                                                                             %
801 %                                                                             %
802 %                                                                             %
803 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
804 %
805 %  Method DestroyPackageInfo frees a previously created info structure.
806 %
807 %  The format of the DestroyPackageInfo routine is:
808 %
809 %      DestroyPackageInfo(struct PackageInfo *info)
810 %
811 %  A description of each parameter follows:
812 %
813 %    o info: a structure of type info.
814 %
815 */
816 static void DestroyPackageInfo(struct PackageInfo *info)
817 {
818   info->image_info=DestroyImageInfo(info->image_info);
819   info=(struct PackageInfo *) RelinquishMagickMemory(info);
820 }
821 \f
822 /*
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 %                                                                             %
825 %                                                                             %
826 %                                                                             %
827 %   G e t L i s t                                                             %
828 %                                                                             %
829 %                                                                             %
830 %                                                                             %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 %
833 %  Method GetList is recursively called by SetupList to traverse the
834 %  Image__Magick reference.  If building an reference_vector (see SetupList),
835 %  *current is the current position in *reference_vector and *last is the final
836 %  entry in *reference_vector.
837 %
838 %  The format of the GetList routine is:
839 %
840 %      GetList(info)
841 %
842 %  A description of each parameter follows:
843 %
844 %    o info: a structure of type info.
845 %
846 */
847 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
848   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
849 {
850   Image
851     *image;
852
853   if (reference == (SV *) NULL)
854     return(NULL);
855   switch (SvTYPE(reference))
856   {
857     case SVt_PVAV:
858     {
859       AV
860         *av;
861
862       Image
863         *head,
864         *previous;
865
866       register ssize_t
867         i;
868
869       ssize_t
870         n;
871
872       /*
873         Array of images.
874       */
875       previous=(Image *) NULL;
876       head=(Image *) NULL;
877       av=(AV *) reference;
878       n=av_len(av);
879       for (i=0; i <= n; i++)
880       {
881         SV
882           **rv;
883
884         rv=av_fetch(av,i,0);
885         if (rv && *rv && sv_isobject(*rv))
886           {
887             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
888               exception);
889             if (image == (Image *) NULL)
890               continue;
891             if (image == previous)
892               {
893                 image=CloneImage(image,0,0,MagickTrue,exception);
894                 if (image == (Image *) NULL)
895                   return(NULL);
896               }
897             image->previous=previous;
898             *(previous ? &previous->next : &head)=image;
899             for (previous=image; previous->next; previous=previous->next) ;
900           }
901       }
902       return(head);
903     }
904     case SVt_PVMG:
905     {
906       /*
907         Blessed scalar, one image.
908       */
909       image=INT2PTR(Image *,SvIV(reference));
910       if (image == (Image *) NULL)
911         return(NULL);
912       image->previous=(Image *) NULL;
913       image->next=(Image *) NULL;
914       if (reference_vector)
915         {
916           if (*current == *last)
917             {
918               *last+=256;
919               if (*reference_vector == (SV **) NULL)
920                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
921                   sizeof(*reference_vector));
922               else
923                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
924                   *last,sizeof(*reference_vector));
925             }
926           if (*reference_vector == (SV **) NULL)
927             {
928               ThrowPerlException(exception,ResourceLimitError,
929                 "MemoryAllocationFailed",PackageName);
930               return((Image *) NULL);
931             }
932           (*reference_vector)[*current]=reference;
933           (*reference_vector)[++(*current)]=NULL;
934         }
935       return(image);
936     }
937     default:
938       break;
939   }
940   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
941     (double) SvTYPE(reference));
942   return((Image *) NULL);
943 }
944 \f
945 /*
946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 %                                                                             %
948 %                                                                             %
949 %                                                                             %
950 %   G e t P a c k a g e I n f o                                               %
951 %                                                                             %
952 %                                                                             %
953 %                                                                             %
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 %
956 %  Method GetPackageInfo looks up or creates an info structure for the given
957 %  Image__Magick reference.  If it does create a new one, the information in
958 %  package_info is used to initialize it.
959 %
960 %  The format of the GetPackageInfo routine is:
961 %
962 %      struct PackageInfo *GetPackageInfo(void *reference,
963 %        struct PackageInfo *package_info,ExceptionInfo *exception)
964 %
965 %  A description of each parameter follows:
966 %
967 %    o info: a structure of type info.
968 %
969 %    o exception: Return any errors or warnings in this structure.
970 %
971 */
972 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
973   struct PackageInfo *package_info,ExceptionInfo *exception)
974 {
975   char
976     message[MaxTextExtent];
977
978   struct PackageInfo
979     *clone_info;
980
981   SV
982     *sv;
983
984   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
985     PackageName,XS_VERSION,reference);
986   sv=perl_get_sv(message,(TRUE | 0x02));
987   if (sv == (SV *) NULL)
988     {
989       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
990         message);
991       return(package_info);
992     }
993   if (SvREFCNT(sv) == 0)
994     (void) SvREFCNT_inc(sv);
995   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
996     return(clone_info);
997   clone_info=ClonePackageInfo(package_info,exception);
998   sv_setiv(sv,PTR2IV(clone_info));
999   return(clone_info);
1000 }
1001 \f
1002 /*
1003 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %                                                                             %
1005 %                                                                             %
1006 %                                                                             %
1007 %   S e t A t t r i b u t e                                                   %
1008 %                                                                             %
1009 %                                                                             %
1010 %                                                                             %
1011 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012 %
1013 %  SetAttribute() sets the attribute to the value in sval.  This can change
1014 %  either or both of image or info.
1015 %
1016 %  The format of the SetAttribute routine is:
1017 %
1018 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1019 %        SV *sval,ExceptionInfo *exception)
1020 %
1021 %  A description of each parameter follows:
1022 %
1023 %    o list: a list of strings.
1024 %
1025 %    o string: a character string.
1026 %
1027 */
1028
1029 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1030 {
1031   char
1032     *q;
1033
1034   double
1035     value;
1036
1037   value=InterpretSiPrefixValue(string,&q);
1038   if (*q == '%')
1039     value*=interval/100.0;
1040   return(value);
1041 }
1042
1043 static inline double StringToDouble(const char *string,char **sentinal)
1044 {
1045   return(InterpretLocaleValue(string,sentinal));
1046 }
1047
1048 static double StringToDoubleInterval(const char *string,const double interval)
1049 {
1050   char
1051     *q;
1052
1053   double
1054     value;
1055
1056   value=InterpretLocaleValue(string,&q);
1057   if (*q == '%')
1058     value*=interval/100.0;
1059   return(value);
1060 }
1061
1062 static inline ssize_t StringToLong(const char *value)
1063 {
1064   return(strtol(value,(char **) NULL,10));
1065 }
1066
1067 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1068   const char *attribute,SV *sval,ExceptionInfo *exception)
1069 {
1070   GeometryInfo
1071     geometry_info;
1072
1073   long
1074     x,
1075     y;
1076
1077   PixelInfo
1078     pixel;
1079
1080   MagickStatusType
1081     flags;
1082
1083   PixelInfo
1084     *color,
1085     target_color;
1086
1087   ssize_t
1088     sp;
1089
1090   switch (*attribute)
1091   {
1092     case 'A':
1093     case 'a':
1094     {
1095       if (LocaleCompare(attribute,"adjoin") == 0)
1096         {
1097           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1098             SvPV(sval,na)) : SvIV(sval);
1099           if (sp < 0)
1100             {
1101               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1102                 SvPV(sval,na));
1103               break;
1104             }
1105           if (info)
1106             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1107           break;
1108         }
1109       if (LocaleCompare(attribute,"alpha") == 0)
1110         {
1111           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1112             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1113           if (sp < 0)
1114             {
1115               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1116                 SvPV(sval,na));
1117               break;
1118             }
1119           for ( ; image; image=image->next)
1120             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1121               exception);
1122           break;
1123         }
1124       if (LocaleCompare(attribute,"antialias") == 0)
1125         {
1126           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1127             SvPV(sval,na)) : SvIV(sval);
1128           if (sp < 0)
1129             {
1130               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1131                 SvPV(sval,na));
1132               break;
1133             }
1134           if (info)
1135             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1136           break;
1137         }
1138       if (LocaleCompare(attribute,"area-limit") == 0)
1139         {
1140           MagickSizeType
1141             limit;
1142
1143           limit=MagickResourceInfinity;
1144           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1145             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1146               100.0);
1147           (void) SetMagickResourceLimit(AreaResource,limit);
1148           break;
1149         }
1150       if (LocaleCompare(attribute,"attenuate") == 0)
1151         {
1152           if (info)
1153             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1154           break;
1155         }
1156       if (LocaleCompare(attribute,"authenticate") == 0)
1157         {
1158           if (info)
1159             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1160           break;
1161         }
1162       if (info)
1163         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1164       for ( ; image; image=image->next)
1165         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1166       break;
1167     }
1168     case 'B':
1169     case 'b':
1170     {
1171       if (LocaleCompare(attribute,"background") == 0)
1172         {
1173           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1174             exception);
1175           if (info)
1176             info->image_info->background_color=target_color;
1177           for ( ; image; image=image->next)
1178             image->background_color=target_color;
1179           break;
1180         }
1181       if (LocaleCompare(attribute,"blue-primary") == 0)
1182         {
1183           for ( ; image; image=image->next)
1184           {
1185             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1186             image->chromaticity.blue_primary.x=geometry_info.rho;
1187             image->chromaticity.blue_primary.y=geometry_info.sigma;
1188             if ((flags & SigmaValue) == 0)
1189               image->chromaticity.blue_primary.y=
1190                 image->chromaticity.blue_primary.x;
1191           }
1192           break;
1193         }
1194       if (LocaleCompare(attribute,"bordercolor") == 0)
1195         {
1196           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1197             exception);
1198           if (info)
1199             info->image_info->border_color=target_color;
1200           for ( ; image; image=image->next)
1201             image->border_color=target_color;
1202           break;
1203         }
1204       if (info)
1205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1206       for ( ; image; image=image->next)
1207         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1208       break;
1209     }
1210     case 'C':
1211     case 'c':
1212     {
1213       if (LocaleCompare(attribute,"cache-threshold") == 0)
1214         {
1215           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1216             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1217           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1218             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1219           break;
1220         }
1221       if (LocaleCompare(attribute,"clip-mask") == 0)
1222         {
1223           Image
1224             *clip_mask;
1225
1226           clip_mask=(Image *) NULL;
1227           if (SvPOK(sval))
1228             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1229           for ( ; image; image=image->next)
1230             SetImageMask(image,clip_mask,exception);
1231           break;
1232         }
1233       if (LocaleNCompare(attribute,"colormap",8) == 0)
1234         {
1235           for ( ; image; image=image->next)
1236           {
1237             int
1238               items;
1239
1240             long
1241               i;
1242
1243             if (image->storage_class == DirectClass)
1244               continue;
1245             i=0;
1246             items=sscanf(attribute,"%*[^[][%ld",&i);
1247             (void) items;
1248             if (i > (ssize_t) image->colors)
1249               i%=image->colors;
1250             if ((strchr(SvPV(sval,na),',') == 0) ||
1251                 (strchr(SvPV(sval,na),')') != 0))
1252               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1253                 image->colormap+i,exception);
1254             else
1255               {
1256                 color=image->colormap+i;
1257                 pixel.red=color->red;
1258                 pixel.green=color->green;
1259                 pixel.blue=color->blue;
1260                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1261                 pixel.red=geometry_info.rho;
1262                 pixel.green=geometry_info.sigma;
1263                 pixel.blue=geometry_info.xi;
1264                 color->red=ClampToQuantum(pixel.red);
1265                 color->green=ClampToQuantum(pixel.green);
1266                 color->blue=ClampToQuantum(pixel.blue);
1267               }
1268           }
1269           break;
1270         }
1271       if (LocaleCompare(attribute,"colorspace") == 0)
1272         {
1273           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1274             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1275           if (sp < 0)
1276             {
1277               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1278                 SvPV(sval,na));
1279               break;
1280             }
1281           for ( ; image; image=image->next)
1282             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1283               exception);
1284           break;
1285         }
1286       if (LocaleCompare(attribute,"comment") == 0)
1287         {
1288           for ( ; image; image=image->next)
1289             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1290               info ? info->image_info : (ImageInfo *) NULL,image,
1291               SvPV(sval,na),exception),exception);
1292           break;
1293         }
1294       if (LocaleCompare(attribute,"compression") == 0)
1295         {
1296           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1297             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1298           if (sp < 0)
1299             {
1300               ThrowPerlException(exception,OptionError,
1301                 "UnrecognizedImageCompression",SvPV(sval,na));
1302               break;
1303             }
1304           if (info)
1305             info->image_info->compression=(CompressionType) sp;
1306           for ( ; image; image=image->next)
1307             image->compression=(CompressionType) sp;
1308           break;
1309         }
1310       if (info)
1311         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1312       for ( ; image; image=image->next)
1313         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1314       break;
1315     }
1316     case 'D':
1317     case 'd':
1318     {
1319       if (LocaleCompare(attribute,"debug") == 0)
1320         {
1321           SetLogEventMask(SvPV(sval,na));
1322           break;
1323         }
1324       if (LocaleCompare(attribute,"delay") == 0)
1325         {
1326           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1327           for ( ; image; image=image->next)
1328           {
1329             image->delay=(size_t) floor(geometry_info.rho+0.5);
1330             if ((flags & SigmaValue) != 0)
1331               image->ticks_per_second=(ssize_t)
1332                 floor(geometry_info.sigma+0.5);
1333           }
1334           break;
1335         }
1336       if (LocaleCompare(attribute,"disk-limit") == 0)
1337         {
1338           MagickSizeType
1339             limit;
1340
1341           limit=MagickResourceInfinity;
1342           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1343             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1344               100.0);
1345           (void) SetMagickResourceLimit(DiskResource,limit);
1346           break;
1347         }
1348       if (LocaleCompare(attribute,"density") == 0)
1349         {
1350           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1351             {
1352               ThrowPerlException(exception,OptionError,"MissingGeometry",
1353                 SvPV(sval,na));
1354               break;
1355             }
1356           if (info)
1357             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1358           for ( ; image; image=image->next)
1359           {
1360             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1361             image->resolution.x=geometry_info.rho;
1362             image->resolution.y=geometry_info.sigma;
1363             if ((flags & SigmaValue) == 0)
1364               image->resolution.y=image->resolution.x;
1365           }
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"depth") == 0)
1369         {
1370           if (info)
1371             info->image_info->depth=SvIV(sval);
1372           for ( ; image; image=image->next)
1373             (void) SetImageDepth(image,SvIV(sval),exception);
1374           break;
1375         }
1376       if (LocaleCompare(attribute,"dispose") == 0)
1377         {
1378           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1379             SvPV(sval,na)) : SvIV(sval);
1380           if (sp < 0)
1381             {
1382               ThrowPerlException(exception,OptionError,
1383                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1384               break;
1385             }
1386           for ( ; image; image=image->next)
1387             image->dispose=(DisposeType) sp;
1388           break;
1389         }
1390       if (LocaleCompare(attribute,"dither") == 0)
1391         {
1392           if (info)
1393             {
1394               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1395                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1396               if (sp < 0)
1397                 {
1398                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1399                     SvPV(sval,na));
1400                   break;
1401                 }
1402               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1403             }
1404           break;
1405         }
1406       if (LocaleCompare(attribute,"display") == 0)
1407         {
1408           display:
1409           if (info)
1410             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1411           break;
1412         }
1413       if (info)
1414         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1415       for ( ; image; image=image->next)
1416         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1417       break;
1418     }
1419     case 'E':
1420     case 'e':
1421     {
1422       if (LocaleCompare(attribute,"endian") == 0)
1423         {
1424           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1425             SvPV(sval,na)) : SvIV(sval);
1426           if (sp < 0)
1427             {
1428               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1429                 SvPV(sval,na));
1430               break;
1431             }
1432           if (info)
1433             info->image_info->endian=(EndianType) sp;
1434           for ( ; image; image=image->next)
1435             image->endian=(EndianType) sp;
1436           break;
1437         }
1438       if (LocaleCompare(attribute,"extract") == 0)
1439         {
1440           /*
1441             Set image extract geometry.
1442           */
1443           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1444           break;
1445         }
1446       if (info)
1447         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1448       for ( ; image; image=image->next)
1449         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1450       break;
1451     }
1452     case 'F':
1453     case 'f':
1454     {
1455       if (LocaleCompare(attribute,"filename") == 0)
1456         {
1457           if (info)
1458             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1459               MaxTextExtent);
1460           for ( ; image; image=image->next)
1461             (void) CopyMagickString(image->filename,SvPV(sval,na),
1462               MaxTextExtent);
1463           break;
1464         }
1465       if (LocaleCompare(attribute,"file") == 0)
1466         {
1467           FILE
1468             *file;
1469
1470           PerlIO
1471             *io_info;
1472
1473           if (info == (struct PackageInfo *) NULL)
1474             break;
1475           io_info=IoIFP(sv_2io(sval));
1476           if (io_info == (PerlIO *) NULL)
1477             {
1478               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1479                 PackageName);
1480               break;
1481             }
1482           file=PerlIO_findFILE(io_info);
1483           if (file == (FILE *) NULL)
1484             {
1485               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1486                 PackageName);
1487               break;
1488             }
1489           SetImageInfoFile(info->image_info,file);
1490           break;
1491         }
1492       if (LocaleCompare(attribute,"fill") == 0)
1493         {
1494           if (info)
1495             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1496           break;
1497         }
1498       if (LocaleCompare(attribute,"font") == 0)
1499         {
1500           if (info)
1501             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1502           break;
1503         }
1504       if (LocaleCompare(attribute,"foreground") == 0)
1505         break;
1506       if (LocaleCompare(attribute,"fuzz") == 0)
1507         {
1508           if (info)
1509             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1510               QuantumRange+1.0);
1511           for ( ; image; image=image->next)
1512             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1513               QuantumRange+1.0);
1514           break;
1515         }
1516       if (info)
1517         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1518       for ( ; image; image=image->next)
1519         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1520       break;
1521     }
1522     case 'G':
1523     case 'g':
1524     {
1525       if (LocaleCompare(attribute,"gamma") == 0)
1526         {
1527           for ( ; image; image=image->next)
1528             image->gamma=SvNV(sval);
1529           break;
1530         }
1531       if (LocaleCompare(attribute,"gravity") == 0)
1532         {
1533           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1534             SvPV(sval,na)) : SvIV(sval);
1535           if (sp < 0)
1536             {
1537               ThrowPerlException(exception,OptionError,
1538                 "UnrecognizedGravityType",SvPV(sval,na));
1539               break;
1540             }
1541           if (info)
1542             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1543           for ( ; image; image=image->next)
1544             image->gravity=(GravityType) sp;
1545           break;
1546         }
1547       if (LocaleCompare(attribute,"green-primary") == 0)
1548         {
1549           for ( ; image; image=image->next)
1550           {
1551             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1552             image->chromaticity.green_primary.x=geometry_info.rho;
1553             image->chromaticity.green_primary.y=geometry_info.sigma;
1554             if ((flags & SigmaValue) == 0)
1555               image->chromaticity.green_primary.y=
1556                 image->chromaticity.green_primary.x;
1557           }
1558           break;
1559         }
1560       if (info)
1561         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1562       for ( ; image; image=image->next)
1563         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1564       break;
1565     }
1566     case 'I':
1567     case 'i':
1568     {
1569       if (LocaleNCompare(attribute,"index",5) == 0)
1570         {
1571           int
1572             items;
1573
1574           long
1575             index;
1576
1577           register Quantum
1578             *q;
1579
1580           CacheView
1581             *image_view;
1582
1583           for ( ; image; image=image->next)
1584           {
1585             if (image->storage_class != PseudoClass)
1586               continue;
1587             x=0;
1588             y=0;
1589             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1590             (void) items;
1591             image_view=AcquireAuthenticCacheView(image,exception);
1592             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1593             if (q != (Quantum *) NULL)
1594               {
1595                 items=sscanf(SvPV(sval,na),"%ld",&index);
1596                 if ((index >= 0) && (index < (ssize_t) image->colors))
1597                   SetPixelIndex(image,index,q);
1598                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1599               }
1600             image_view=DestroyCacheView(image_view);
1601           }
1602           break;
1603         }
1604       if (LocaleCompare(attribute,"iterations") == 0)
1605         {
1606   iterations:
1607           for ( ; image; image=image->next)
1608             image->iterations=SvIV(sval);
1609           break;
1610         }
1611       if (LocaleCompare(attribute,"interlace") == 0)
1612         {
1613           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1614             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1615           if (sp < 0)
1616             {
1617               ThrowPerlException(exception,OptionError,
1618                 "UnrecognizedInterlaceType",SvPV(sval,na));
1619               break;
1620             }
1621           if (info)
1622             info->image_info->interlace=(InterlaceType) sp;
1623           for ( ; image; image=image->next)
1624             image->interlace=(InterlaceType) sp;
1625           break;
1626         }
1627       if (info)
1628         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1629       for ( ; image; image=image->next)
1630         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1631       break;
1632     }
1633     case 'L':
1634     case 'l':
1635     {
1636       if (LocaleCompare(attribute,"label") == 0)
1637         {
1638           for ( ; image; image=image->next)
1639             (void) SetImageProperty(image,"label",InterpretImageProperties(
1640               info ? info->image_info : (ImageInfo *) NULL,image,
1641               SvPV(sval,na),exception),exception);
1642           break;
1643         }
1644       if (LocaleCompare(attribute,"loop") == 0)
1645         goto iterations;
1646       if (info)
1647         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1648       for ( ; image; image=image->next)
1649         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1650       break;
1651     }
1652     case 'M':
1653     case 'm':
1654     {
1655       if (LocaleCompare(attribute,"magick") == 0)
1656         {
1657           if (info)
1658             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1659               "%s:",SvPV(sval,na));
1660           for ( ; image; image=image->next)
1661             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1662           break;
1663         }
1664       if (LocaleCompare(attribute,"map-limit") == 0)
1665         {
1666           MagickSizeType
1667             limit;
1668
1669           limit=MagickResourceInfinity;
1670           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1671             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1672               100.0);
1673           (void) SetMagickResourceLimit(MapResource,limit);
1674           break;
1675         }
1676       if (LocaleCompare(attribute,"mask") == 0)
1677         {
1678           Image
1679             *mask;
1680
1681           mask=(Image *) NULL;
1682           if (SvPOK(sval))
1683             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1684           for ( ; image; image=image->next)
1685             SetImageMask(image,mask,exception);
1686           break;
1687         }
1688       if (LocaleCompare(attribute,"mattecolor") == 0)
1689         {
1690           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1691             exception);
1692           if (info)
1693             info->image_info->matte_color=target_color;
1694           for ( ; image; image=image->next)
1695             image->matte_color=target_color;
1696           break;
1697         }
1698       if (LocaleCompare(attribute,"matte") == 0)
1699         {
1700           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1701             SvPV(sval,na)) : SvIV(sval);
1702           if (sp < 0)
1703             {
1704               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1705                 SvPV(sval,na));
1706               break;
1707             }
1708           for ( ; image; image=image->next)
1709             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1710           break;
1711         }
1712       if (LocaleCompare(attribute,"memory-limit") == 0)
1713         {
1714           MagickSizeType
1715             limit;
1716
1717           limit=MagickResourceInfinity;
1718           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1719             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1720               100.0);
1721           (void) SetMagickResourceLimit(MemoryResource,limit);
1722           break;
1723         }
1724       if (LocaleCompare(attribute,"monochrome") == 0)
1725         {
1726           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1727             SvPV(sval,na)) : SvIV(sval);
1728           if (sp < 0)
1729             {
1730               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1731                 SvPV(sval,na));
1732               break;
1733             }
1734           if (info)
1735             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1736           for ( ; image; image=image->next)
1737             (void) SetImageType(image,BilevelType,exception);
1738           break;
1739         }
1740       if (info)
1741         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1742       for ( ; image; image=image->next)
1743         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1744       break;
1745     }
1746     case 'O':
1747     case 'o':
1748     {
1749       if (LocaleCompare(attribute,"option") == 0)
1750         {
1751           if (info)
1752             DefineImageOption(info->image_info,SvPV(sval,na));
1753           break;
1754         }
1755       if (LocaleCompare(attribute,"orientation") == 0)
1756         {
1757           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1758             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1759           if (sp < 0)
1760             {
1761               ThrowPerlException(exception,OptionError,
1762                 "UnrecognizedOrientationType",SvPV(sval,na));
1763               break;
1764             }
1765           if (info)
1766             info->image_info->orientation=(OrientationType) sp;
1767           for ( ; image; image=image->next)
1768             image->orientation=(OrientationType) sp;
1769           break;
1770         }
1771       if (info)
1772         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1773       for ( ; image; image=image->next)
1774         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1775       break;
1776     }
1777     case 'P':
1778     case 'p':
1779     {
1780       if (LocaleCompare(attribute,"page") == 0)
1781         {
1782           char
1783             *geometry;
1784
1785           geometry=GetPageGeometry(SvPV(sval,na));
1786           if (info)
1787             (void) CloneString(&info->image_info->page,geometry);
1788           for ( ; image; image=image->next)
1789             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1790           geometry=(char *) RelinquishMagickMemory(geometry);
1791           break;
1792         }
1793       if (LocaleNCompare(attribute,"pixel",5) == 0)
1794         {
1795           int
1796             items;
1797
1798           PixelInfo
1799             pixel;
1800
1801           register Quantum
1802             *q;
1803
1804           CacheView
1805             *image_view;
1806
1807           for ( ; image; image=image->next)
1808           {
1809             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1810               break;
1811             x=0;
1812             y=0;
1813             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1814             (void) items;
1815             image_view=AcquireVirtualCacheView(image,exception);
1816             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1817             if (q != (Quantum *) NULL)
1818               {
1819                 if ((strchr(SvPV(sval,na),',') == 0) ||
1820                     (strchr(SvPV(sval,na),')') != 0))
1821                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1822                     &pixel,exception);
1823                 else
1824                   {
1825                     GetPixelInfo(image,&pixel);
1826                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1827                     pixel.red=geometry_info.rho;
1828                     if ((flags & SigmaValue) != 0)
1829                       pixel.green=geometry_info.sigma;
1830                     if ((flags & XiValue) != 0)
1831                       pixel.blue=geometry_info.xi;
1832                     if ((flags & PsiValue) != 0)
1833                       pixel.alpha=geometry_info.psi;
1834                     if ((flags & ChiValue) != 0)
1835                       pixel.black=geometry_info.chi;
1836                   }
1837                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1838                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1839                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1840                 if (image->colorspace == CMYKColorspace)
1841                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1842                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1843                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1844               }
1845             image_view=DestroyCacheView(image_view);
1846           }
1847           break;
1848         }
1849       if (LocaleCompare(attribute,"pointsize") == 0)
1850         {
1851           if (info)
1852             {
1853               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1854               info->image_info->pointsize=geometry_info.rho;
1855             }
1856           break;
1857         }
1858       if (LocaleCompare(attribute,"preview") == 0)
1859         {
1860           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1861             SvPV(sval,na)) : SvIV(sval);
1862           if (sp < 0)
1863             {
1864               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1865                 SvPV(sval,na));
1866               break;
1867             }
1868           if (info)
1869             info->image_info->preview_type=(PreviewType) sp;
1870           break;
1871         }
1872       if (info)
1873         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1874       for ( ; image; image=image->next)
1875         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1876       break;
1877     }
1878     case 'Q':
1879     case 'q':
1880     {
1881       if (LocaleCompare(attribute,"quality") == 0)
1882         {
1883           if (info)
1884             info->image_info->quality=SvIV(sval);
1885           for ( ; image; image=image->next)
1886             image->quality=SvIV(sval);
1887           break;
1888         }
1889       if (info)
1890         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1891       for ( ; image; image=image->next)
1892         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1893       break;
1894     }
1895     case 'R':
1896     case 'r':
1897     {
1898       if (LocaleCompare(attribute,"red-primary") == 0)
1899         {
1900           for ( ; image; image=image->next)
1901           {
1902             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1903             image->chromaticity.red_primary.x=geometry_info.rho;
1904             image->chromaticity.red_primary.y=geometry_info.sigma;
1905             if ((flags & SigmaValue) == 0)
1906               image->chromaticity.red_primary.y=
1907                 image->chromaticity.red_primary.x;
1908           }
1909           break;
1910         }
1911       if (LocaleCompare(attribute,"render") == 0)
1912         {
1913           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1914             SvPV(sval,na)) : SvIV(sval);
1915           if (sp < 0)
1916             {
1917               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1918                 SvPV(sval,na));
1919               break;
1920             }
1921          for ( ; image; image=image->next)
1922            image->rendering_intent=(RenderingIntent) sp;
1923          break;
1924        }
1925       if (LocaleCompare(attribute,"repage") == 0)
1926         {
1927           RectangleInfo
1928             geometry;
1929
1930           for ( ; image; image=image->next)
1931           {
1932             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1933             if ((flags & WidthValue) != 0)
1934               {
1935                 if ((flags & HeightValue) == 0)
1936                   geometry.height=geometry.width;
1937                 image->page.width=geometry.width;
1938                 image->page.height=geometry.height;
1939               }
1940             if ((flags & AspectValue) != 0)
1941               {
1942                 if ((flags & XValue) != 0)
1943                   image->page.x+=geometry.x;
1944                 if ((flags & YValue) != 0)
1945                   image->page.y+=geometry.y;
1946               }
1947             else
1948               {
1949                 if ((flags & XValue) != 0)
1950                   {
1951                     image->page.x=geometry.x;
1952                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1953                       image->page.width=image->columns+geometry.x;
1954                   }
1955                 if ((flags & YValue) != 0)
1956                   {
1957                     image->page.y=geometry.y;
1958                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1959                       image->page.height=image->rows+geometry.y;
1960                   }
1961               }
1962           }
1963           break;
1964         }
1965       if (info)
1966         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1967       for ( ; image; image=image->next)
1968         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1969       break;
1970     }
1971     case 'S':
1972     case 's':
1973     {
1974       if (LocaleCompare(attribute,"sampling-factor") == 0)
1975         {
1976           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1977             {
1978               ThrowPerlException(exception,OptionError,"MissingGeometry",
1979                 SvPV(sval,na));
1980               break;
1981             }
1982           if (info)
1983             (void) CloneString(&info->image_info->sampling_factor,
1984               SvPV(sval,na));
1985           break;
1986         }
1987       if (LocaleCompare(attribute,"scene") == 0)
1988         {
1989           for ( ; image; image=image->next)
1990             image->scene=SvIV(sval);
1991           break;
1992         }
1993       if (LocaleCompare(attribute,"server") == 0)
1994         goto display;
1995       if (LocaleCompare(attribute,"size") == 0)
1996         {
1997           if (info)
1998             {
1999               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2000                 {
2001                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2002                     SvPV(sval,na));
2003                   break;
2004                 }
2005               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2006             }
2007           break;
2008         }
2009       if (LocaleCompare(attribute,"stroke") == 0)
2010         {
2011           if (info)
2012             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2013           break;
2014         }
2015       if (info)
2016         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2017       for ( ; image; image=image->next)
2018         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2019       break;
2020     }
2021     case 'T':
2022     case 't':
2023     {
2024       if (LocaleCompare(attribute,"texture") == 0)
2025         {
2026           if (info)
2027             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2028           break;
2029         }
2030       if (LocaleCompare(attribute,"thread-limit") == 0)
2031         {
2032           MagickSizeType
2033             limit;
2034
2035           limit=MagickResourceInfinity;
2036           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2037             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2038               100.0);
2039           (void) SetMagickResourceLimit(ThreadResource,limit);
2040           break;
2041         }
2042       if (LocaleCompare(attribute,"tile-offset") == 0)
2043         {
2044           char
2045             *geometry;
2046
2047           geometry=GetPageGeometry(SvPV(sval,na));
2048           if (info)
2049             (void) CloneString(&info->image_info->page,geometry);
2050           for ( ; image; image=image->next)
2051             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2052               exception);
2053           geometry=(char *) RelinquishMagickMemory(geometry);
2054           break;
2055         }
2056       if (LocaleCompare(attribute,"time-limit") == 0)
2057         {
2058           MagickSizeType
2059             limit;
2060
2061           limit=MagickResourceInfinity;
2062           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2063             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2064               100.0);
2065           (void) SetMagickResourceLimit(TimeResource,limit);
2066           break;
2067         }
2068       if (LocaleCompare(attribute,"transparent-color") == 0)
2069         {
2070           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2071             exception);
2072           if (info)
2073             info->image_info->transparent_color=target_color;
2074           for ( ; image; image=image->next)
2075             image->transparent_color=target_color;
2076           break;
2077         }
2078       if (LocaleCompare(attribute,"type") == 0)
2079         {
2080           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2081             SvPV(sval,na)) : SvIV(sval);
2082           if (sp < 0)
2083             {
2084               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2085                 SvPV(sval,na));
2086               break;
2087             }
2088           if (info)
2089             info->image_info->type=(ImageType) sp;
2090           for ( ; image; image=image->next)
2091             SetImageType(image,(ImageType) sp,exception);
2092           break;
2093         }
2094       if (info)
2095         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2096       for ( ; image; image=image->next)
2097         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2098       break;
2099     }
2100     case 'U':
2101     case 'u':
2102     {
2103       if (LocaleCompare(attribute,"units") == 0)
2104         {
2105           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2106             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2107           if (sp < 0)
2108             {
2109               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2110                 SvPV(sval,na));
2111               break;
2112             }
2113           if (info)
2114             info->image_info->units=(ResolutionType) sp;
2115           for ( ; image; image=image->next)
2116           {
2117             ResolutionType
2118               units;
2119
2120             units=(ResolutionType) sp;
2121             if (image->units != units)
2122               switch (image->units)
2123               {
2124                 case UndefinedResolution:
2125                 case PixelsPerInchResolution:
2126                 {
2127                   if (units == PixelsPerCentimeterResolution)
2128                     {
2129                       image->resolution.x*=2.54;
2130                       image->resolution.y*=2.54;
2131                     }
2132                   break;
2133                 }
2134                 case PixelsPerCentimeterResolution:
2135                 {
2136                   if (units == PixelsPerInchResolution)
2137                     {
2138                       image->resolution.x/=2.54;
2139                       image->resolution.y/=2.54;
2140                     }
2141                   break;
2142                 }
2143               }
2144             image->units=units;
2145           }
2146           break;
2147         }
2148       if (info)
2149         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2150       for ( ; image; image=image->next)
2151         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2152       break;
2153     }
2154     case 'V':
2155     case 'v':
2156     {
2157       if (LocaleCompare(attribute,"verbose") == 0)
2158         {
2159           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2160             SvPV(sval,na)) : SvIV(sval);
2161           if (sp < 0)
2162             {
2163               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2164                 SvPV(sval,na));
2165               break;
2166             }
2167           if (info)
2168             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2169           break;
2170         }
2171       if (LocaleCompare(attribute,"view") == 0)
2172         {
2173           if (info)
2174             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2175           break;
2176         }
2177       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2178         {
2179           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2180             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2181           if (sp < 0)
2182             {
2183               ThrowPerlException(exception,OptionError,
2184                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2185               break;
2186             }
2187           for ( ; image; image=image->next)
2188             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2189           break;
2190         }
2191       if (info)
2192         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2193       for ( ; image; image=image->next)
2194         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2195       break;
2196     }
2197     case 'W':
2198     case 'w':
2199     {
2200       if (LocaleCompare(attribute,"white-point") == 0)
2201         {
2202           for ( ; image; image=image->next)
2203           {
2204             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2205             image->chromaticity.white_point.x=geometry_info.rho;
2206             image->chromaticity.white_point.y=geometry_info.sigma;
2207             if ((flags & SigmaValue) == 0)
2208               image->chromaticity.white_point.y=
2209                 image->chromaticity.white_point.x;
2210           }
2211           break;
2212         }
2213       if (info)
2214         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2215       for ( ; image; image=image->next)
2216         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2217       break;
2218     }
2219     default:
2220     {
2221       if (info)
2222         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2223       for ( ; image; image=image->next)
2224         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2225       break;
2226     }
2227   }
2228 }
2229 \f
2230 /*
2231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2232 %                                                                             %
2233 %                                                                             %
2234 %                                                                             %
2235 %   S e t u p L i s t                                                         %
2236 %                                                                             %
2237 %                                                                             %
2238 %                                                                             %
2239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2240 %
2241 %  Method SetupList returns the list of all the images linked by their
2242 %  image->next and image->previous link lists for use with ImageMagick.  If
2243 %  info is non-NULL, an info structure is returned in *info.  If
2244 %  reference_vector is non-NULL,an array of SV* are returned in
2245 %  *reference_vector.  Reference_vector is used when the images are going to be
2246 %  replaced with new Image*'s.
2247 %
2248 %  The format of the SetupList routine is:
2249 %
2250 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2251 %        SV ***reference_vector,ExceptionInfo *exception)
2252 %
2253 %  A description of each parameter follows:
2254 %
2255 %    o list: a list of strings.
2256 %
2257 %    o string: a character string.
2258 %
2259 %    o exception: Return any errors or warnings in this structure.
2260 %
2261 */
2262 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2263   SV ***reference_vector,ExceptionInfo *exception)
2264 {
2265   Image
2266     *image;
2267
2268   ssize_t
2269     current,
2270     last;
2271
2272   if (reference_vector)
2273     *reference_vector=NULL;
2274   if (info)
2275     *info=NULL;
2276   current=0;
2277   last=0;
2278   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2279   if (info && (SvTYPE(reference) == SVt_PVAV))
2280     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2281       exception);
2282   return(image);
2283 }
2284 \f
2285 /*
2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287 %                                                                             %
2288 %                                                                             %
2289 %                                                                             %
2290 %   s t r E Q c a s e                                                         %
2291 %                                                                             %
2292 %                                                                             %
2293 %                                                                             %
2294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2295 %
2296 %  strEQcase() compares two strings and returns 0 if they are the
2297 %  same or if the second string runs out first.  The comparison is case
2298 %  insensitive.
2299 %
2300 %  The format of the strEQcase routine is:
2301 %
2302 %      ssize_t strEQcase(const char *p,const char *q)
2303 %
2304 %  A description of each parameter follows:
2305 %
2306 %    o p: a character string.
2307 %
2308 %    o q: a character string.
2309 %
2310 %
2311 */
2312 static ssize_t strEQcase(const char *p,const char *q)
2313 {
2314   char
2315     c;
2316
2317   register ssize_t
2318     i;
2319
2320   for (i=0 ; (c=(*q)) != 0; i++)
2321   {
2322     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2323         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2324       return(0);
2325     p++;
2326     q++;
2327   }
2328   return(((*q == 0) && (*p == 0)) ? i : 0);
2329 }
2330 \f
2331 /*
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 %                                                                             %
2334 %                                                                             %
2335 %                                                                             %
2336 %   I m a g e : : M a g i c k                                                 %
2337 %                                                                             %
2338 %                                                                             %
2339 %                                                                             %
2340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2341 %
2342 %
2343 */
2344 MODULE = Image::Magick PACKAGE = Image::Magick
2345
2346 PROTOTYPES: ENABLE
2347
2348 BOOT:
2349   MagickCoreGenesis("PerlMagick",MagickFalse);
2350   SetWarningHandler(NULL);
2351   SetErrorHandler(NULL);
2352   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2353     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2354
2355 void
2356 UNLOAD()
2357   PPCODE:
2358   {
2359     if (magick_registry != (SplayTreeInfo *) NULL)
2360       magick_registry=DestroySplayTree(magick_registry);
2361     MagickCoreTerminus();
2362   }
2363
2364 double
2365 constant(name,argument)
2366   char *name
2367   ssize_t argument
2368 \f
2369 #
2370 ###############################################################################
2371 #                                                                             #
2372 #                                                                             #
2373 #                                                                             #
2374 #   A n i m a t e                                                             #
2375 #                                                                             #
2376 #                                                                             #
2377 #                                                                             #
2378 ###############################################################################
2379 #
2380 #
2381 void
2382 Animate(ref,...)
2383   Image::Magick ref=NO_INIT
2384   ALIAS:
2385     AnimateImage  = 1
2386     animate       = 2
2387     animateimage  = 3
2388   PPCODE:
2389   {
2390     ExceptionInfo
2391       *exception;
2392
2393     Image
2394       *image;
2395
2396     register ssize_t
2397       i;
2398
2399     struct PackageInfo
2400       *info,
2401       *package_info;
2402
2403     SV
2404       *perl_exception,
2405       *reference;
2406
2407     PERL_UNUSED_VAR(ref);
2408     PERL_UNUSED_VAR(ix);
2409     exception=AcquireExceptionInfo();
2410     perl_exception=newSVpv("",0);
2411     package_info=(struct PackageInfo *) NULL;
2412     if (sv_isobject(ST(0)) == 0)
2413       {
2414         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2415           PackageName);
2416         goto PerlException;
2417       }
2418     reference=SvRV(ST(0));
2419     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2420     if (image == (Image *) NULL)
2421       {
2422         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2423           PackageName);
2424         goto PerlException;
2425       }
2426     package_info=ClonePackageInfo(info,exception);
2427     if (items == 2)
2428       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2429     else
2430       if (items > 2)
2431         for (i=2; i < items; i+=2)
2432           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2433             exception);
2434     (void) AnimateImages(package_info->image_info,image,exception);
2435     (void) CatchImageException(image);
2436
2437   PerlException:
2438     if (package_info != (struct PackageInfo *) NULL)
2439       DestroyPackageInfo(package_info);
2440     InheritPerlException(exception,perl_exception);
2441     exception=DestroyExceptionInfo(exception);
2442     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2443     SvPOK_on(perl_exception);
2444     ST(0)=sv_2mortal(perl_exception);
2445     XSRETURN(1);
2446   }
2447 \f
2448 #
2449 ###############################################################################
2450 #                                                                             #
2451 #                                                                             #
2452 #                                                                             #
2453 #   A p p e n d                                                               #
2454 #                                                                             #
2455 #                                                                             #
2456 #                                                                             #
2457 ###############################################################################
2458 #
2459 #
2460 void
2461 Append(ref,...)
2462   Image::Magick ref=NO_INIT
2463   ALIAS:
2464     AppendImage  = 1
2465     append       = 2
2466     appendimage  = 3
2467   PPCODE:
2468   {
2469     AV
2470       *av;
2471
2472     char
2473       *attribute;
2474
2475     ExceptionInfo
2476       *exception;
2477
2478     HV
2479       *hv;
2480
2481     Image
2482       *image;
2483
2484     register ssize_t
2485       i;
2486
2487     ssize_t
2488       stack;
2489
2490     struct PackageInfo
2491       *info;
2492
2493     SV
2494       *av_reference,
2495       *perl_exception,
2496       *reference,
2497       *rv,
2498       *sv;
2499
2500     PERL_UNUSED_VAR(ref);
2501     PERL_UNUSED_VAR(ix);
2502     exception=AcquireExceptionInfo();
2503     perl_exception=newSVpv("",0);
2504     sv=NULL;
2505     attribute=NULL;
2506     av=NULL;
2507     if (sv_isobject(ST(0)) == 0)
2508       {
2509         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2510           PackageName);
2511         goto PerlException;
2512       }
2513     reference=SvRV(ST(0));
2514     hv=SvSTASH(reference);
2515     av=newAV();
2516     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2517     SvREFCNT_dec(av);
2518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2519     if (image == (Image *) NULL)
2520       {
2521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2522           PackageName);
2523         goto PerlException;
2524       }
2525     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2526     /*
2527       Get options.
2528     */
2529     stack=MagickTrue;
2530     for (i=2; i < items; i+=2)
2531     {
2532       attribute=(char *) SvPV(ST(i-1),na);
2533       switch (*attribute)
2534       {
2535         case 'S':
2536         case 's':
2537         {
2538           if (LocaleCompare(attribute,"stack") == 0)
2539             {
2540               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2541                 SvPV(ST(i),na));
2542               if (stack < 0)
2543                 {
2544                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2545                     SvPV(ST(i),na));
2546                   return;
2547                 }
2548               break;
2549             }
2550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2551             attribute);
2552           break;
2553         }
2554         default:
2555         {
2556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2557             attribute);
2558           break;
2559         }
2560       }
2561     }
2562     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2563     if (image == (Image *) NULL)
2564       goto PerlException;
2565     for ( ; image; image=image->next)
2566     {
2567       AddImageToRegistry(sv,image);
2568       rv=newRV(sv);
2569       av_push(av,sv_bless(rv,hv));
2570       SvREFCNT_dec(sv);
2571     }
2572     exception=DestroyExceptionInfo(exception);
2573     ST(0)=av_reference;
2574     SvREFCNT_dec(perl_exception);
2575     XSRETURN(1);
2576
2577   PerlException:
2578     InheritPerlException(exception,perl_exception);
2579     exception=DestroyExceptionInfo(exception);
2580     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2581     SvPOK_on(perl_exception);
2582     ST(0)=sv_2mortal(perl_exception);
2583     XSRETURN(1);
2584   }
2585 \f
2586 #
2587 ###############################################################################
2588 #                                                                             #
2589 #                                                                             #
2590 #                                                                             #
2591 #   A v e r a g e                                                             #
2592 #                                                                             #
2593 #                                                                             #
2594 #                                                                             #
2595 ###############################################################################
2596 #
2597 #
2598 void
2599 Average(ref)
2600   Image::Magick ref=NO_INIT
2601   ALIAS:
2602     AverageImage   = 1
2603     average        = 2
2604     averageimage   = 3
2605   PPCODE:
2606   {
2607     AV
2608       *av;
2609
2610     char
2611       *p;
2612
2613     ExceptionInfo
2614       *exception;
2615
2616     HV
2617       *hv;
2618
2619     Image
2620       *image;
2621
2622     struct PackageInfo
2623       *info;
2624
2625     SV
2626       *perl_exception,
2627       *reference,
2628       *rv,
2629       *sv;
2630
2631     PERL_UNUSED_VAR(ref);
2632     PERL_UNUSED_VAR(ix);
2633     exception=AcquireExceptionInfo();
2634     perl_exception=newSVpv("",0);
2635     sv=NULL;
2636     if (sv_isobject(ST(0)) == 0)
2637       {
2638         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2639           PackageName);
2640         goto PerlException;
2641       }
2642     reference=SvRV(ST(0));
2643     hv=SvSTASH(reference);
2644     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2645     if (image == (Image *) NULL)
2646       {
2647         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2648           PackageName);
2649         goto PerlException;
2650       }
2651     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2652     if (image == (Image *) NULL)
2653       goto PerlException;
2654     /*
2655       Create blessed Perl array for the returned image.
2656     */
2657     av=newAV();
2658     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2659     SvREFCNT_dec(av);
2660     AddImageToRegistry(sv,image);
2661     rv=newRV(sv);
2662     av_push(av,sv_bless(rv,hv));
2663     SvREFCNT_dec(sv);
2664     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2665     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2666       "average-%.*s",(int) (MaxTextExtent-9),
2667       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2668     (void) CopyMagickString(image->filename,info->image_info->filename,
2669       MaxTextExtent);
2670     SetImageInfo(info->image_info,0,exception);
2671     exception=DestroyExceptionInfo(exception);
2672     SvREFCNT_dec(perl_exception);
2673     XSRETURN(1);
2674
2675   PerlException:
2676     InheritPerlException(exception,perl_exception);
2677     exception=DestroyExceptionInfo(exception);
2678     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2679     SvPOK_on(perl_exception);
2680     ST(0)=sv_2mortal(perl_exception);
2681     XSRETURN(1);
2682   }
2683 \f
2684 #
2685 ###############################################################################
2686 #                                                                             #
2687 #                                                                             #
2688 #                                                                             #
2689 #   B l o b T o I m a g e                                                     #
2690 #                                                                             #
2691 #                                                                             #
2692 #                                                                             #
2693 ###############################################################################
2694 #
2695 #
2696 void
2697 BlobToImage(ref,...)
2698   Image::Magick ref=NO_INIT
2699   ALIAS:
2700     BlobToImage  = 1
2701     blobtoimage  = 2
2702     blobto       = 3
2703   PPCODE:
2704   {
2705     AV
2706       *av;
2707
2708     char
2709       **keep,
2710       **list;
2711
2712     ExceptionInfo
2713       *exception;
2714
2715     HV
2716       *hv;
2717
2718     Image
2719       *image;
2720
2721     register char
2722       **p;
2723
2724     register ssize_t
2725       i;
2726
2727     ssize_t
2728       ac,
2729       n,
2730       number_images;
2731
2732     STRLEN
2733       *length;
2734
2735     struct PackageInfo
2736       *info;
2737
2738     SV
2739       *perl_exception,
2740       *reference,
2741       *rv,
2742       *sv;
2743
2744     PERL_UNUSED_VAR(ref);
2745     PERL_UNUSED_VAR(ix);
2746     exception=AcquireExceptionInfo();
2747     perl_exception=newSVpv("",0);
2748     sv=NULL;
2749     number_images=0;
2750     ac=(items < 2) ? 1 : items-1;
2751     length=(STRLEN *) NULL;
2752     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2753     if (list == (char **) NULL)
2754       {
2755         ThrowPerlException(exception,ResourceLimitError,
2756           "MemoryAllocationFailed",PackageName);
2757         goto PerlException;
2758       }
2759     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2760     if (length == (STRLEN *) NULL)
2761       {
2762         ThrowPerlException(exception,ResourceLimitError,
2763           "MemoryAllocationFailed",PackageName);
2764         goto PerlException;
2765       }
2766     if (sv_isobject(ST(0)) == 0)
2767       {
2768         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2769           PackageName);
2770         goto PerlException;
2771       }
2772     reference=SvRV(ST(0));
2773     hv=SvSTASH(reference);
2774     if (SvTYPE(reference) != SVt_PVAV)
2775       {
2776         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2777           PackageName);
2778         goto PerlException;
2779       }
2780     av=(AV *) reference;
2781     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2782       exception);
2783     n=1;
2784     if (items <= 1)
2785       {
2786         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2787         goto PerlException;
2788       }
2789     for (n=0, i=0; i < ac; i++)
2790     {
2791       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2792       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2793         {
2794           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2795           continue;
2796         }
2797       n++;
2798     }
2799     list[n]=(char *) NULL;
2800     keep=list;
2801     for (i=number_images=0; i < n; i++)
2802     {
2803       image=BlobToImage(info->image_info,list[i],length[i],exception);
2804       if (image == (Image *) NULL)
2805         break;
2806       for ( ; image; image=image->next)
2807       {
2808         AddImageToRegistry(sv,image);
2809         rv=newRV(sv);
2810         av_push(av,sv_bless(rv,hv));
2811         SvREFCNT_dec(sv);
2812         number_images++;
2813       }
2814     }
2815     /*
2816       Free resources.
2817     */
2818     for (i=0; i < n; i++)
2819       if (list[i] != (char *) NULL)
2820         for (p=keep; list[i] != *p++; )
2821           if (*p == (char *) NULL)
2822             {
2823               list[i]=(char *) RelinquishMagickMemory(list[i]);
2824               break;
2825             }
2826
2827   PerlException:
2828     if (list)
2829       list=(char **) RelinquishMagickMemory(list);
2830     if (length)
2831       length=(STRLEN *) RelinquishMagickMemory(length);
2832     InheritPerlException(exception,perl_exception);
2833     exception=DestroyExceptionInfo(exception);
2834     sv_setiv(perl_exception,(IV) number_images);
2835     SvPOK_on(perl_exception);
2836     ST(0)=sv_2mortal(perl_exception);
2837     XSRETURN(1);
2838   }
2839 \f
2840 #
2841 ###############################################################################
2842 #                                                                             #
2843 #                                                                             #
2844 #                                                                             #
2845 #   C h a n n e l F x                                                         #
2846 #                                                                             #
2847 #                                                                             #
2848 #                                                                             #
2849 ###############################################################################
2850 #
2851 #
2852 void
2853 ChannelFx(ref,...)
2854   Image::Magick ref=NO_INIT
2855   ALIAS:
2856     ChannelFxImage  = 1
2857     channelfx       = 2
2858     channelfximage  = 3
2859   PPCODE:
2860   {
2861     AV
2862       *av;
2863
2864     char
2865       *attribute,
2866       expression[MaxTextExtent];
2867
2868     ChannelType
2869       channel,
2870       channel_mask;
2871
2872     ExceptionInfo
2873       *exception;
2874
2875     HV
2876       *hv;
2877
2878     Image
2879       *image;
2880
2881     register ssize_t
2882       i;
2883
2884     struct PackageInfo
2885       *info;
2886
2887     SV
2888       *av_reference,
2889       *perl_exception,
2890       *reference,
2891       *rv,
2892       *sv;
2893
2894     PERL_UNUSED_VAR(ref);
2895     PERL_UNUSED_VAR(ix);
2896     exception=AcquireExceptionInfo();
2897     perl_exception=newSVpv("",0);
2898     sv=NULL;
2899     attribute=NULL;
2900     av=NULL;
2901     if (sv_isobject(ST(0)) == 0)
2902       {
2903         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2904           PackageName);
2905         goto PerlException;
2906       }
2907     reference=SvRV(ST(0));
2908     hv=SvSTASH(reference);
2909     av=newAV();
2910     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2911     SvREFCNT_dec(av);
2912     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2913     if (image == (Image *) NULL)
2914       {
2915         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2916           PackageName);
2917         goto PerlException;
2918       }
2919     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2920     /*
2921       Get options.
2922     */
2923     channel=DefaultChannels;
2924     (void) CopyMagickString(expression,"u",MaxTextExtent);
2925     if (items == 2)
2926       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2927     else
2928       for (i=2; i < items; i+=2)
2929       {
2930         attribute=(char *) SvPV(ST(i-1),na);
2931         switch (*attribute)
2932         {
2933           case 'C':
2934           case 'c':
2935           {
2936             if (LocaleCompare(attribute,"channel") == 0)
2937               {
2938                 ssize_t
2939                   option;
2940
2941                 option=ParseChannelOption(SvPV(ST(i),na));
2942                 if (option < 0)
2943                   {
2944                     ThrowPerlException(exception,OptionError,
2945                       "UnrecognizedType",SvPV(ST(i),na));
2946                     return;
2947                   }
2948                 channel=(ChannelType) option;
2949                 break;
2950               }
2951             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2952               attribute);
2953             break;
2954           }
2955           case 'E':
2956           case 'e':
2957           {
2958             if (LocaleCompare(attribute,"expression") == 0)
2959               {
2960                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2961                   MaxTextExtent);
2962                 break;
2963               }
2964             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2965               attribute);
2966             break;
2967           }
2968           default:
2969           {
2970             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2971               attribute);
2972             break;
2973           }
2974         }
2975       }
2976     channel_mask=SetImageChannelMask(image,channel);
2977     image=ChannelFxImage(image,expression,exception);
2978     if (image != (Image *) NULL)
2979       (void) SetImageChannelMask(image,channel_mask);
2980     if (image == (Image *) NULL)
2981       goto PerlException;
2982     for ( ; image; image=image->next)
2983     {
2984       AddImageToRegistry(sv,image);
2985       rv=newRV(sv);
2986       av_push(av,sv_bless(rv,hv));
2987       SvREFCNT_dec(sv);
2988     }
2989     exception=DestroyExceptionInfo(exception);
2990     ST(0)=av_reference;
2991     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2992     XSRETURN(1);
2993
2994   PerlException:
2995     InheritPerlException(exception,perl_exception);
2996     exception=DestroyExceptionInfo(exception);
2997     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2998     SvPOK_on(perl_exception);
2999     ST(0)=sv_2mortal(perl_exception);
3000     XSRETURN(1);
3001   }
3002 \f
3003 #
3004 ###############################################################################
3005 #                                                                             #
3006 #                                                                             #
3007 #                                                                             #
3008 #   C l o n e                                                                 #
3009 #                                                                             #
3010 #                                                                             #
3011 #                                                                             #
3012 ###############################################################################
3013 #
3014 #
3015 void
3016 Clone(ref)
3017   Image::Magick ref=NO_INIT
3018   ALIAS:
3019     CopyImage   = 1
3020     copy        = 2
3021     copyimage   = 3
3022     CloneImage  = 4
3023     clone       = 5
3024     cloneimage  = 6
3025     Clone       = 7
3026   PPCODE:
3027   {
3028     AV
3029       *av;
3030
3031     ExceptionInfo
3032       *exception;
3033
3034     HV
3035       *hv;
3036
3037     Image
3038       *clone,
3039       *image;
3040
3041     struct PackageInfo
3042       *info;
3043
3044     SV
3045       *perl_exception,
3046       *reference,
3047       *rv,
3048       *sv;
3049
3050     PERL_UNUSED_VAR(ref);
3051     PERL_UNUSED_VAR(ix);
3052     exception=AcquireExceptionInfo();
3053     perl_exception=newSVpv("",0);
3054     sv=NULL;
3055     if (sv_isobject(ST(0)) == 0)
3056       {
3057         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3058           PackageName);
3059         goto PerlException;
3060       }
3061     reference=SvRV(ST(0));
3062     hv=SvSTASH(reference);
3063     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3064     if (image == (Image *) NULL)
3065       {
3066         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3067           PackageName);
3068         goto PerlException;
3069       }
3070     /*
3071       Create blessed Perl array for the returned image.
3072     */
3073     av=newAV();
3074     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3075     SvREFCNT_dec(av);
3076     for ( ; image; image=image->next)
3077     {
3078       clone=CloneImage(image,0,0,MagickTrue,exception);
3079       if (clone == (Image *) NULL)
3080         break;
3081       AddImageToRegistry(sv,clone);
3082       rv=newRV(sv);
3083       av_push(av,sv_bless(rv,hv));
3084       SvREFCNT_dec(sv);
3085     }
3086     exception=DestroyExceptionInfo(exception);
3087     SvREFCNT_dec(perl_exception);
3088     XSRETURN(1);
3089
3090   PerlException:
3091     InheritPerlException(exception,perl_exception);
3092     exception=DestroyExceptionInfo(exception);
3093     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3094     SvPOK_on(perl_exception);
3095     ST(0)=sv_2mortal(perl_exception);
3096     XSRETURN(1);
3097   }
3098 \f
3099 #
3100 ###############################################################################
3101 #                                                                             #
3102 #                                                                             #
3103 #                                                                             #
3104 #   C L O N E                                                                 #
3105 #                                                                             #
3106 #                                                                             #
3107 #                                                                             #
3108 ###############################################################################
3109 #
3110 #
3111 void
3112 CLONE(ref,...)
3113   SV *ref;
3114   CODE:
3115   {
3116     PERL_UNUSED_VAR(ref);
3117     if (magick_registry != (SplayTreeInfo *) NULL)
3118       {
3119         register Image
3120           *p;
3121
3122         ResetSplayTreeIterator(magick_registry);
3123         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3124         while (p != (Image *) NULL)
3125         {
3126           ReferenceImage(p);
3127           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3128         }
3129       }
3130   }
3131 \f
3132 #
3133 ###############################################################################
3134 #                                                                             #
3135 #                                                                             #
3136 #                                                                             #
3137 #   C o a l e s c e                                                           #
3138 #                                                                             #
3139 #                                                                             #
3140 #                                                                             #
3141 ###############################################################################
3142 #
3143 #
3144 void
3145 Coalesce(ref)
3146   Image::Magick ref=NO_INIT
3147   ALIAS:
3148     CoalesceImage   = 1
3149     coalesce        = 2
3150     coalesceimage   = 3
3151   PPCODE:
3152   {
3153     AV
3154       *av;
3155
3156     ExceptionInfo
3157       *exception;
3158
3159     HV
3160       *hv;
3161
3162     Image
3163       *image;
3164
3165     struct PackageInfo
3166       *info;
3167
3168     SV
3169       *av_reference,
3170       *perl_exception,
3171       *reference,
3172       *rv,
3173       *sv;
3174
3175     PERL_UNUSED_VAR(ref);
3176     PERL_UNUSED_VAR(ix);
3177     exception=AcquireExceptionInfo();
3178     perl_exception=newSVpv("",0);
3179     sv=NULL;
3180     if (sv_isobject(ST(0)) == 0)
3181       {
3182         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3183           PackageName);
3184         goto PerlException;
3185       }
3186     reference=SvRV(ST(0));
3187     hv=SvSTASH(reference);
3188     av=newAV();
3189     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3190     SvREFCNT_dec(av);
3191     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3192     if (image == (Image *) NULL)
3193       {
3194         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3195           PackageName);
3196         goto PerlException;
3197       }
3198     image=CoalesceImages(image,exception);
3199     if (image == (Image *) NULL)
3200       goto PerlException;
3201     for ( ; image; image=image->next)
3202     {
3203       AddImageToRegistry(sv,image);
3204       rv=newRV(sv);
3205       av_push(av,sv_bless(rv,hv));
3206       SvREFCNT_dec(sv);
3207     }
3208     exception=DestroyExceptionInfo(exception);
3209     ST(0)=av_reference;
3210     SvREFCNT_dec(perl_exception);
3211     XSRETURN(1);
3212
3213   PerlException:
3214     InheritPerlException(exception,perl_exception);
3215     exception=DestroyExceptionInfo(exception);
3216     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3217     SvPOK_on(perl_exception);
3218     ST(0)=sv_2mortal(perl_exception);
3219     XSRETURN(1);
3220   }
3221 \f
3222 #
3223 ###############################################################################
3224 #                                                                             #
3225 #                                                                             #
3226 #                                                                             #
3227 #   C o m p a r e                                                             #
3228 #                                                                             #
3229 #                                                                             #
3230 #                                                                             #
3231 ###############################################################################
3232 #
3233 #
3234 void
3235 Compare(ref,...)
3236   Image::Magick ref=NO_INIT
3237   ALIAS:
3238     CompareImages = 1
3239     compare      = 2
3240     compareimage = 3
3241   PPCODE:
3242   {
3243     AV
3244       *av;
3245
3246     char
3247       *attribute;
3248
3249     double
3250       distortion;
3251
3252     ExceptionInfo
3253       *exception;
3254
3255     HV
3256       *hv;
3257
3258     Image
3259       *difference_image,
3260       *image,
3261       *reconstruct_image;
3262
3263     MetricType
3264       metric;
3265
3266     register ssize_t
3267       i;
3268
3269     ssize_t
3270       option;
3271
3272     struct PackageInfo
3273       *info;
3274
3275     SV
3276       *av_reference,
3277       *perl_exception,
3278       *reference,
3279       *rv,
3280       *sv;
3281
3282     PERL_UNUSED_VAR(ref);
3283     PERL_UNUSED_VAR(ix);
3284     exception=AcquireExceptionInfo();
3285     perl_exception=newSVpv("",0);
3286     sv=NULL;
3287     av=NULL;
3288     attribute=NULL;
3289     if (sv_isobject(ST(0)) == 0)
3290       {
3291         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3292           PackageName);
3293         goto PerlException;
3294       }
3295     reference=SvRV(ST(0));
3296     hv=SvSTASH(reference);
3297     av=newAV();
3298     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3299     SvREFCNT_dec(av);
3300     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3301     if (image == (Image *) NULL)
3302       {
3303         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3304           PackageName);
3305         goto PerlException;
3306       }
3307     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3308     /*
3309       Get attribute.
3310     */
3311     reconstruct_image=image;
3312     metric=RootMeanSquaredErrorMetric;
3313     for (i=2; i < items; i+=2)
3314     {
3315       attribute=(char *) SvPV(ST(i-1),na);
3316       switch (*attribute)
3317       {
3318         case 'C':
3319         case 'c':
3320         {
3321           if (LocaleCompare(attribute,"channel") == 0)
3322             {
3323               ssize_t
3324                 option;
3325
3326               option=ParseChannelOption(SvPV(ST(i),na));
3327               if (option < 0)
3328                 {
3329                   ThrowPerlException(exception,OptionError,
3330                     "UnrecognizedType",SvPV(ST(i),na));
3331                   return;
3332                 }
3333               SetPixelChannelMask(image,(ChannelType) option);
3334               break;
3335             }
3336           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3337             attribute);
3338           break;
3339         }
3340         case 'F':
3341         case 'f':
3342         {
3343           if (LocaleCompare(attribute,"fuzz") == 0)
3344             {
3345               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3346               break;
3347             }
3348           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3349             attribute);
3350           break;
3351         }
3352         case 'I':
3353         case 'i':
3354         {
3355           if (LocaleCompare(attribute,"image") == 0)
3356             {
3357               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3358                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3359               break;
3360             }
3361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3362             attribute);
3363           break;
3364         }
3365         case 'M':
3366         case 'm':
3367         {
3368           if (LocaleCompare(attribute,"metric") == 0)
3369             {
3370               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3371                 SvPV(ST(i),na));
3372               if (option < 0)
3373                 {
3374                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3375                     SvPV(ST(i),na));
3376                   break;
3377                 }
3378               metric=(MetricType) option;
3379               break;
3380             }
3381           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3382             attribute);
3383           break;
3384         }
3385         default:
3386         {
3387           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3388             attribute);
3389           break;
3390         }
3391       }
3392     }
3393     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3394       exception);
3395     if (difference_image != (Image *) NULL)
3396       {
3397         difference_image->error.mean_error_per_pixel=distortion;
3398         AddImageToRegistry(sv,difference_image);
3399         rv=newRV(sv);
3400         av_push(av,sv_bless(rv,hv));
3401         SvREFCNT_dec(sv);
3402       }
3403     exception=DestroyExceptionInfo(exception);
3404     ST(0)=av_reference;
3405     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3406     XSRETURN(1);
3407
3408   PerlException:
3409     InheritPerlException(exception,perl_exception);
3410     exception=DestroyExceptionInfo(exception);
3411     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3412     SvPOK_on(perl_exception);
3413     ST(0)=sv_2mortal(perl_exception);
3414     XSRETURN(1);
3415   }
3416 \f
3417 #
3418 ###############################################################################
3419 #                                                                             #
3420 #                                                                             #
3421 #                                                                             #
3422 #   C o m p l e x I m a g e s                                                 #
3423 #                                                                             #
3424 #                                                                             #
3425 #                                                                             #
3426 ###############################################################################
3427 #
3428 #
3429 void
3430 ComplexImages(ref)
3431   Image::Magick ref=NO_INIT
3432   ALIAS:
3433     ComplexImages   = 1
3434     compleximages   = 2
3435   PPCODE:
3436   {
3437     AV
3438       *av;
3439
3440     char
3441       *attribute,
3442       *p;
3443
3444     ComplexOperator
3445       op;
3446
3447     ExceptionInfo
3448       *exception;
3449
3450     HV
3451       *hv;
3452
3453     Image
3454       *image;
3455
3456     register ssize_t
3457       i;
3458
3459     struct PackageInfo
3460       *info;
3461
3462     SV
3463       *perl_exception,
3464       *reference,
3465       *rv,
3466       *sv;
3467
3468     PERL_UNUSED_VAR(ref);
3469     PERL_UNUSED_VAR(ix);
3470     exception=AcquireExceptionInfo();
3471     perl_exception=newSVpv("",0);
3472     sv=NULL;
3473     if (sv_isobject(ST(0)) == 0)
3474       {
3475         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3476           PackageName);
3477         goto PerlException;
3478       }
3479     reference=SvRV(ST(0));
3480     hv=SvSTASH(reference);
3481     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3482     if (image == (Image *) NULL)
3483       {
3484         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3485           PackageName);
3486         goto PerlException;
3487       }
3488     op=UndefinedComplexOperator;
3489     if (items == 2)
3490       {
3491         ssize_t
3492           in;
3493
3494         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3495           SvPV(ST(1),na));
3496         if (in < 0)
3497           {
3498             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3499               SvPV(ST(1),na));
3500             return;
3501           }
3502         op=(ComplexOperator) in;
3503       }
3504     else
3505       for (i=2; i < items; i+=2)
3506       {
3507         attribute=(char *) SvPV(ST(i-1),na);
3508         switch (*attribute)
3509         {
3510           case 'O':
3511           case 'o':
3512           {
3513             if (LocaleCompare(attribute,"operator") == 0)
3514               {
3515                 ssize_t
3516                   in;
3517
3518                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3519                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3520                 if (in < 0)
3521                   {
3522                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3523                       SvPV(ST(i),na));
3524                     return;
3525                   }
3526                 op=(ComplexOperator) in;
3527                 break;
3528               }
3529             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3530               attribute);
3531             break;
3532           }
3533           default:
3534           {
3535             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3536               attribute);
3537             break;
3538           }
3539         }
3540       }
3541     image=ComplexImages(image,op,exception);
3542     if (image == (Image *) NULL)
3543       goto PerlException;
3544     /*
3545       Create blessed Perl array for the returned image.
3546     */
3547     av=newAV();
3548     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3549     SvREFCNT_dec(av);
3550     AddImageToRegistry(sv,image);
3551     rv=newRV(sv);
3552     av_push(av,sv_bless(rv,hv));
3553     SvREFCNT_dec(sv);
3554     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3555     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3556       "complex-%.*s",(int) (MaxTextExtent-9),
3557       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3558     (void) CopyMagickString(image->filename,info->image_info->filename,
3559       MaxTextExtent);
3560     SetImageInfo(info->image_info,0,exception);
3561     exception=DestroyExceptionInfo(exception);
3562     SvREFCNT_dec(perl_exception);
3563     XSRETURN(1);
3564
3565   PerlException:
3566     InheritPerlException(exception,perl_exception);
3567     exception=DestroyExceptionInfo(exception);
3568     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3569     SvPOK_on(perl_exception);
3570     ST(0)=sv_2mortal(perl_exception);
3571     XSRETURN(1);
3572   }
3573 \f
3574 #
3575 ###############################################################################
3576 #                                                                             #
3577 #                                                                             #
3578 #                                                                             #
3579 #   C o m p a r e L a y e r s                                                 #
3580 #                                                                             #
3581 #                                                                             #
3582 #                                                                             #
3583 ###############################################################################
3584 #
3585 #
3586 void
3587 CompareLayers(ref)
3588   Image::Magick ref=NO_INIT
3589   ALIAS:
3590     CompareImagesLayers   = 1
3591     comparelayers        = 2
3592     compareimagelayers   = 3
3593   PPCODE:
3594   {
3595     AV
3596       *av;
3597
3598     char
3599       *attribute;
3600
3601     ExceptionInfo
3602       *exception;
3603
3604     HV
3605       *hv;
3606
3607     Image
3608       *image;
3609
3610     LayerMethod
3611       method;
3612
3613     register ssize_t
3614       i;
3615
3616     ssize_t
3617       option;
3618
3619     struct PackageInfo
3620       *info;
3621
3622     SV
3623       *av_reference,
3624       *perl_exception,
3625       *reference,
3626       *rv,
3627       *sv;
3628
3629     PERL_UNUSED_VAR(ref);
3630     PERL_UNUSED_VAR(ix);
3631     exception=AcquireExceptionInfo();
3632     perl_exception=newSVpv("",0);
3633     sv=NULL;
3634     if (sv_isobject(ST(0)) == 0)
3635       {
3636         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3637           PackageName);
3638         goto PerlException;
3639       }
3640     reference=SvRV(ST(0));
3641     hv=SvSTASH(reference);
3642     av=newAV();
3643     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3644     SvREFCNT_dec(av);
3645     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3646     if (image == (Image *) NULL)
3647       {
3648         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3649           PackageName);
3650         goto PerlException;
3651       }
3652     method=CompareAnyLayer;
3653     for (i=2; i < items; i+=2)
3654     {
3655       attribute=(char *) SvPV(ST(i-1),na);
3656       switch (*attribute)
3657       {
3658         case 'M':
3659         case 'm':
3660         {
3661           if (LocaleCompare(attribute,"method") == 0)
3662             {
3663               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3664                 SvPV(ST(i),na));
3665               if (option < 0)
3666                 {
3667                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3668                     SvPV(ST(i),na));
3669                   break;
3670                 }
3671                method=(LayerMethod) option;
3672               break;
3673             }
3674           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3675             attribute);
3676           break;
3677         }
3678         default:
3679         {
3680           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3681             attribute);
3682           break;
3683         }
3684       }
3685     }
3686     image=CompareImagesLayers(image,method,exception);
3687     if (image == (Image *) NULL)
3688       goto PerlException;
3689     for ( ; image; image=image->next)
3690     {
3691       AddImageToRegistry(sv,image);
3692       rv=newRV(sv);
3693       av_push(av,sv_bless(rv,hv));
3694       SvREFCNT_dec(sv);
3695     }
3696     exception=DestroyExceptionInfo(exception);
3697     ST(0)=av_reference;
3698     SvREFCNT_dec(perl_exception);
3699     XSRETURN(1);
3700
3701   PerlException:
3702     InheritPerlException(exception,perl_exception);
3703     exception=DestroyExceptionInfo(exception);
3704     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3705     SvPOK_on(perl_exception);
3706     ST(0)=sv_2mortal(perl_exception);
3707     XSRETURN(1);
3708   }
3709 \f
3710 #
3711 ###############################################################################
3712 #                                                                             #
3713 #                                                                             #
3714 #                                                                             #
3715 #   D e s t r o y                                                             #
3716 #                                                                             #
3717 #                                                                             #
3718 #                                                                             #
3719 ###############################################################################
3720 #
3721 #
3722 void
3723 DESTROY(ref)
3724   Image::Magick ref=NO_INIT
3725   PPCODE:
3726   {
3727     SV
3728       *reference;
3729
3730     PERL_UNUSED_VAR(ref);
3731     if (sv_isobject(ST(0)) == 0)
3732       croak("ReferenceIsNotMyType");
3733     reference=SvRV(ST(0));
3734     switch (SvTYPE(reference))
3735     {
3736       case SVt_PVAV:
3737       {
3738         char
3739           message[MaxTextExtent];
3740
3741         const SV
3742           *key;
3743
3744         HV
3745           *hv;
3746
3747         GV
3748           **gvp;
3749
3750         struct PackageInfo
3751           *info;
3752
3753         SV
3754           *sv;
3755
3756         /*
3757           Array (AV *) reference
3758         */
3759         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3760           XS_VERSION,reference);
3761         hv=gv_stashpv(PackageName, FALSE);
3762         if (!hv)
3763           break;
3764         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3765         if (!gvp)
3766           break;
3767         sv=GvSV(*gvp);
3768         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3769           {
3770             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3771             DestroyPackageInfo(info);
3772           }
3773         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3774         (void) key;
3775         break;
3776       }
3777       case SVt_PVMG:
3778       {
3779         Image
3780           *image;
3781
3782         /*
3783           Blessed scalar = (Image *) SvIV(reference)
3784         */
3785         image=INT2PTR(Image *,SvIV(reference));
3786         if (image != (Image *) NULL)
3787           DeleteImageFromRegistry(reference,image);
3788         break;
3789       }
3790       default:
3791         break;
3792     }
3793   }
3794 \f
3795 #
3796 ###############################################################################
3797 #                                                                             #
3798 #                                                                             #
3799 #                                                                             #
3800 #   D i s p l a y                                                             #
3801 #                                                                             #
3802 #                                                                             #
3803 #                                                                             #
3804 ###############################################################################
3805 #
3806 #
3807 void
3808 Display(ref,...)
3809   Image::Magick ref=NO_INIT
3810   ALIAS:
3811     DisplayImage  = 1
3812     display       = 2
3813     displayimage  = 3
3814   PPCODE:
3815   {
3816     ExceptionInfo
3817       *exception;
3818
3819     Image
3820       *image;
3821
3822     register ssize_t
3823       i;
3824
3825     struct PackageInfo
3826       *info,
3827       *package_info;
3828
3829     SV
3830       *perl_exception,
3831       *reference;
3832
3833     PERL_UNUSED_VAR(ref);
3834     PERL_UNUSED_VAR(ix);
3835     exception=AcquireExceptionInfo();
3836     perl_exception=newSVpv("",0);
3837     package_info=(struct PackageInfo *) NULL;
3838     if (sv_isobject(ST(0)) == 0)
3839       {
3840         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3841           PackageName);
3842         goto PerlException;
3843       }
3844     reference=SvRV(ST(0));
3845     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3846     if (image == (Image *) NULL)
3847       {
3848         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3849           PackageName);
3850         goto PerlException;
3851       }
3852     package_info=ClonePackageInfo(info,exception);
3853     if (items == 2)
3854       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3855     else
3856       if (items > 2)
3857         for (i=2; i < items; i+=2)
3858           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3859             exception);
3860     (void) DisplayImages(package_info->image_info,image,exception);
3861     (void) CatchImageException(image);
3862
3863   PerlException:
3864     if (package_info != (struct PackageInfo *) NULL)
3865       DestroyPackageInfo(package_info);
3866     InheritPerlException(exception,perl_exception);
3867     exception=DestroyExceptionInfo(exception);
3868     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3869     SvPOK_on(perl_exception);
3870     ST(0)=sv_2mortal(perl_exception);
3871     XSRETURN(1);
3872   }
3873 \f
3874 #
3875 ###############################################################################
3876 #                                                                             #
3877 #                                                                             #
3878 #                                                                             #
3879 #   E v a l u a t e I m a g e s                                               #
3880 #                                                                             #
3881 #                                                                             #
3882 #                                                                             #
3883 ###############################################################################
3884 #
3885 #
3886 void
3887 EvaluateImages(ref)
3888   Image::Magick ref=NO_INIT
3889   ALIAS:
3890     EvaluateImages   = 1
3891     evaluateimages   = 2
3892   PPCODE:
3893   {
3894     AV
3895       *av;
3896
3897     char
3898       *attribute,
3899       *p;
3900
3901     ExceptionInfo
3902       *exception;
3903
3904     HV
3905       *hv;
3906
3907     Image
3908       *image;
3909
3910     MagickEvaluateOperator
3911       op;
3912
3913     register ssize_t
3914       i;
3915
3916     struct PackageInfo
3917       *info;
3918
3919     SV
3920       *perl_exception,
3921       *reference,
3922       *rv,
3923       *sv;
3924
3925     PERL_UNUSED_VAR(ref);
3926     PERL_UNUSED_VAR(ix);
3927     exception=AcquireExceptionInfo();
3928     perl_exception=newSVpv("",0);
3929     sv=NULL;
3930     if (sv_isobject(ST(0)) == 0)
3931       {
3932         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3933           PackageName);
3934         goto PerlException;
3935       }
3936     reference=SvRV(ST(0));
3937     hv=SvSTASH(reference);
3938     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3939     if (image == (Image *) NULL)
3940       {
3941         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3942           PackageName);
3943         goto PerlException;
3944       }
3945     op=MeanEvaluateOperator;
3946     if (items == 2)
3947       {
3948         ssize_t
3949           in;
3950
3951         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3952           SvPV(ST(1),na));
3953         if (in < 0)
3954           {
3955             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3956               SvPV(ST(1),na));
3957             return;
3958           }
3959         op=(MagickEvaluateOperator) in;
3960       }
3961     else
3962       for (i=2; i < items; i+=2)
3963       {
3964         attribute=(char *) SvPV(ST(i-1),na);
3965         switch (*attribute)
3966         {
3967           case 'O':
3968           case 'o':
3969           {
3970             if (LocaleCompare(attribute,"operator") == 0)
3971               {
3972                 ssize_t
3973                   in;
3974
3975                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3976                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3977                 if (in < 0)
3978                   {
3979                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3980                       SvPV(ST(i),na));
3981                     return;
3982                   }
3983                 op=(MagickEvaluateOperator) in;
3984                 break;
3985               }
3986             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3987               attribute);
3988             break;
3989           }
3990           default:
3991           {
3992             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3993               attribute);
3994             break;
3995           }
3996         }
3997       }
3998     image=EvaluateImages(image,op,exception);
3999     if (image == (Image *) NULL)
4000       goto PerlException;
4001     /*
4002       Create blessed Perl array for the returned image.
4003     */
4004     av=newAV();
4005     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4006     SvREFCNT_dec(av);
4007     AddImageToRegistry(sv,image);
4008     rv=newRV(sv);
4009     av_push(av,sv_bless(rv,hv));
4010     SvREFCNT_dec(sv);
4011     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4012     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4013       "evaluate-%.*s",(int) (MaxTextExtent-9),
4014       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4015     (void) CopyMagickString(image->filename,info->image_info->filename,
4016       MaxTextExtent);
4017     SetImageInfo(info->image_info,0,exception);
4018     exception=DestroyExceptionInfo(exception);
4019     SvREFCNT_dec(perl_exception);
4020     XSRETURN(1);
4021
4022   PerlException:
4023     InheritPerlException(exception,perl_exception);
4024     exception=DestroyExceptionInfo(exception);
4025     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4026     SvPOK_on(perl_exception);
4027     ST(0)=sv_2mortal(perl_exception);
4028     XSRETURN(1);
4029   }
4030 \f
4031 #
4032 ###############################################################################
4033 #                                                                             #
4034 #                                                                             #
4035 #                                                                             #
4036 #   F e a t u r e s                                                           #
4037 #                                                                             #
4038 #                                                                             #
4039 #                                                                             #
4040 ###############################################################################
4041 #
4042 #
4043 void
4044 Features(ref,...)
4045   Image::Magick ref=NO_INIT
4046   ALIAS:
4047     FeaturesImage = 1
4048     features      = 2
4049     featuresimage = 3
4050   PPCODE:
4051   {
4052 #define ChannelFeatures(channel,direction) \
4053 { \
4054   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4055     channel_features[channel].angular_second_moment[direction]); \
4056   PUSHs(sv_2mortal(newSVpv(message,0))); \
4057   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4058     channel_features[channel].contrast[direction]); \
4059   PUSHs(sv_2mortal(newSVpv(message,0))); \
4060   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4061     channel_features[channel].contrast[direction]); \
4062   PUSHs(sv_2mortal(newSVpv(message,0))); \
4063   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4064     channel_features[channel].variance_sum_of_squares[direction]); \
4065   PUSHs(sv_2mortal(newSVpv(message,0))); \
4066   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4067     channel_features[channel].inverse_difference_moment[direction]); \
4068   PUSHs(sv_2mortal(newSVpv(message,0))); \
4069   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4070     channel_features[channel].sum_average[direction]); \
4071   PUSHs(sv_2mortal(newSVpv(message,0))); \
4072   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4073     channel_features[channel].sum_variance[direction]); \
4074   PUSHs(sv_2mortal(newSVpv(message,0))); \
4075   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4076     channel_features[channel].sum_entropy[direction]); \
4077   PUSHs(sv_2mortal(newSVpv(message,0))); \
4078   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4079     channel_features[channel].entropy[direction]); \
4080   PUSHs(sv_2mortal(newSVpv(message,0))); \
4081   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4082     channel_features[channel].difference_variance[direction]); \
4083   PUSHs(sv_2mortal(newSVpv(message,0))); \
4084   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4085     channel_features[channel].difference_entropy[direction]); \
4086   PUSHs(sv_2mortal(newSVpv(message,0))); \
4087   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4088     channel_features[channel].measure_of_correlation_1[direction]); \
4089   PUSHs(sv_2mortal(newSVpv(message,0))); \
4090   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4091     channel_features[channel].measure_of_correlation_2[direction]); \
4092   PUSHs(sv_2mortal(newSVpv(message,0))); \
4093   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4094     channel_features[channel].maximum_correlation_coefficient[direction]); \
4095   PUSHs(sv_2mortal(newSVpv(message,0))); \
4096 }
4097
4098     AV
4099       *av;
4100
4101     char
4102       *attribute,
4103       message[MaxTextExtent];
4104
4105     ChannelFeatures
4106       *channel_features;
4107
4108     double
4109       distance;
4110
4111     ExceptionInfo
4112       *exception;
4113
4114     Image
4115       *image;
4116
4117     register ssize_t
4118       i;
4119
4120     ssize_t
4121       count;
4122
4123     struct PackageInfo
4124       *info;
4125
4126     SV
4127       *perl_exception,
4128       *reference;
4129
4130     PERL_UNUSED_VAR(ref);
4131     PERL_UNUSED_VAR(ix);
4132     exception=AcquireExceptionInfo();
4133     perl_exception=newSVpv("",0);
4134     av=NULL;
4135     if (sv_isobject(ST(0)) == 0)
4136       {
4137         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4138           PackageName);
4139         goto PerlException;
4140       }
4141     reference=SvRV(ST(0));
4142     av=newAV();
4143     SvREFCNT_dec(av);
4144     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4145     if (image == (Image *) NULL)
4146       {
4147         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4148           PackageName);
4149         goto PerlException;
4150       }
4151     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4152     distance=1;
4153     for (i=2; i < items; i+=2)
4154     {
4155       attribute=(char *) SvPV(ST(i-1),na);
4156       switch (*attribute)
4157       {
4158         case 'D':
4159         case 'd':
4160         {
4161           if (LocaleCompare(attribute,"distance") == 0)
4162             {
4163               distance=StringToLong((char *) SvPV(ST(1),na));
4164               break;
4165             }
4166           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4167             attribute);
4168           break;
4169         }
4170         default:
4171         {
4172           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4173             attribute);
4174           break;
4175         }
4176       }
4177     }
4178     count=0;
4179     for ( ; image; image=image->next)
4180     {
4181       channel_features=GetImageFeatures(image,distance,exception);
4182       if (channel_features == (ChannelFeatures *) NULL)
4183         continue;
4184       count++;
4185       EXTEND(sp,75*count);
4186       for (i=0; i < 4; i++)
4187       {
4188         ChannelFeatures(RedChannel,i);
4189         ChannelFeatures(GreenChannel,i);
4190         ChannelFeatures(BlueChannel,i);
4191         if (image->colorspace == CMYKColorspace)
4192           ChannelFeatures(BlackChannel,i);
4193         if (image->alpha_trait == BlendPixelTrait)
4194           ChannelFeatures(AlphaChannel,i);
4195       }
4196       channel_features=(ChannelFeatures *)
4197         RelinquishMagickMemory(channel_features);
4198     }
4199
4200   PerlException:
4201     InheritPerlException(exception,perl_exception);
4202     exception=DestroyExceptionInfo(exception);
4203     SvREFCNT_dec(perl_exception);
4204   }
4205 \f
4206 #
4207 ###############################################################################
4208 #                                                                             #
4209 #                                                                             #
4210 #                                                                             #
4211 #   F l a t t e n                                                             #
4212 #                                                                             #
4213 #                                                                             #
4214 #                                                                             #
4215 ###############################################################################
4216 #
4217 #
4218 void
4219 Flatten(ref)
4220   Image::Magick ref=NO_INIT
4221   ALIAS:
4222     FlattenImage   = 1
4223     flatten        = 2
4224     flattenimage   = 3
4225   PPCODE:
4226   {
4227     AV
4228       *av;
4229
4230     char
4231       *attribute,
4232       *p;
4233
4234     ExceptionInfo
4235       *exception;
4236
4237     HV
4238       *hv;
4239
4240     Image
4241       *image;
4242
4243     PixelInfo
4244       background_color;
4245
4246     register ssize_t
4247       i;
4248
4249     struct PackageInfo
4250       *info;
4251
4252     SV
4253       *perl_exception,
4254       *reference,
4255       *rv,
4256       *sv;
4257
4258     PERL_UNUSED_VAR(ref);
4259     PERL_UNUSED_VAR(ix);
4260     exception=AcquireExceptionInfo();
4261     perl_exception=newSVpv("",0);
4262     sv=NULL;
4263     if (sv_isobject(ST(0)) == 0)
4264       {
4265         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4266           PackageName);
4267         goto PerlException;
4268       }
4269     reference=SvRV(ST(0));
4270     hv=SvSTASH(reference);
4271     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4272     if (image == (Image *) NULL)
4273       {
4274         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4275           PackageName);
4276         goto PerlException;
4277       }
4278     background_color=image->background_color;
4279     if (items == 2)
4280       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4281         &background_color,exception);
4282     else
4283       for (i=2; i < items; i+=2)
4284       {
4285         attribute=(char *) SvPV(ST(i-1),na);
4286         switch (*attribute)
4287         {
4288           case 'B':
4289           case 'b':
4290           {
4291             if (LocaleCompare(attribute,"background") == 0)
4292               {
4293                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4294                   AllCompliance,&background_color,exception);
4295                 break;
4296               }
4297             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4298               attribute);
4299             break;
4300           }
4301           default:
4302           {
4303             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4304               attribute);
4305             break;
4306           }
4307         }
4308       }
4309     image->background_color=background_color;
4310     image=MergeImageLayers(image,FlattenLayer,exception);
4311     if (image == (Image *) NULL)
4312       goto PerlException;
4313     /*
4314       Create blessed Perl array for the returned image.
4315     */
4316     av=newAV();
4317     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4318     SvREFCNT_dec(av);
4319     AddImageToRegistry(sv,image);
4320     rv=newRV(sv);
4321     av_push(av,sv_bless(rv,hv));
4322     SvREFCNT_dec(sv);
4323     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4324     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4325       "flatten-%.*s",(int) (MaxTextExtent-9),
4326       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4327     (void) CopyMagickString(image->filename,info->image_info->filename,
4328       MaxTextExtent);
4329     SetImageInfo(info->image_info,0,exception);
4330     exception=DestroyExceptionInfo(exception);
4331     SvREFCNT_dec(perl_exception);
4332     XSRETURN(1);
4333
4334   PerlException:
4335     InheritPerlException(exception,perl_exception);
4336     exception=DestroyExceptionInfo(exception);
4337     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4338     SvPOK_on(perl_exception);  /* return messages in string context */
4339     ST(0)=sv_2mortal(perl_exception);
4340     XSRETURN(1);
4341   }
4342 \f
4343 #
4344 ###############################################################################
4345 #                                                                             #
4346 #                                                                             #
4347 #                                                                             #
4348 #   F x                                                                       #
4349 #                                                                             #
4350 #                                                                             #
4351 #                                                                             #
4352 ###############################################################################
4353 #
4354 #
4355 void
4356 Fx(ref,...)
4357   Image::Magick ref=NO_INIT
4358   ALIAS:
4359     FxImage  = 1
4360     fx       = 2
4361     fximage  = 3
4362   PPCODE:
4363   {
4364     AV
4365       *av;
4366
4367     char
4368       *attribute,
4369       expression[MaxTextExtent];
4370
4371     ChannelType
4372       channel,
4373       channel_mask;
4374
4375     ExceptionInfo
4376       *exception;
4377
4378     HV
4379       *hv;
4380
4381     Image
4382       *image;
4383
4384     register ssize_t
4385       i;
4386
4387     struct PackageInfo
4388       *info;
4389
4390     SV
4391       *av_reference,
4392       *perl_exception,
4393       *reference,
4394       *rv,
4395       *sv;
4396
4397     PERL_UNUSED_VAR(ref);
4398     PERL_UNUSED_VAR(ix);
4399     exception=AcquireExceptionInfo();
4400     perl_exception=newSVpv("",0);
4401     sv=NULL;
4402     attribute=NULL;
4403     av=NULL;
4404     if (sv_isobject(ST(0)) == 0)
4405       {
4406         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4407           PackageName);
4408         goto PerlException;
4409       }
4410     reference=SvRV(ST(0));
4411     hv=SvSTASH(reference);
4412     av=newAV();
4413     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4414     SvREFCNT_dec(av);
4415     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4416     if (image == (Image *) NULL)
4417       {
4418         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4419           PackageName);
4420         goto PerlException;
4421       }
4422     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4423     /*
4424       Get options.
4425     */
4426     channel=DefaultChannels;
4427     (void) CopyMagickString(expression,"u",MaxTextExtent);
4428     if (items == 2)
4429       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4430     else
4431       for (i=2; i < items; i+=2)
4432       {
4433         attribute=(char *) SvPV(ST(i-1),na);
4434         switch (*attribute)
4435         {
4436           case 'C':
4437           case 'c':
4438           {
4439             if (LocaleCompare(attribute,"channel") == 0)
4440               {
4441                 ssize_t
4442                   option;
4443
4444                 option=ParseChannelOption(SvPV(ST(i),na));
4445                 if (option < 0)
4446                   {
4447                     ThrowPerlException(exception,OptionError,
4448                       "UnrecognizedType",SvPV(ST(i),na));
4449                     return;
4450                   }
4451                 channel=(ChannelType) option;
4452                 break;
4453               }
4454             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4455               attribute);
4456             break;
4457           }
4458           case 'E':
4459           case 'e':
4460           {
4461             if (LocaleCompare(attribute,"expression") == 0)
4462               {
4463                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4464                   MaxTextExtent);
4465                 break;
4466               }
4467             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4468               attribute);
4469             break;
4470           }
4471           default:
4472           {
4473             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4474               attribute);
4475             break;
4476           }
4477         }
4478       }
4479     channel_mask=SetImageChannelMask(image,channel);
4480     image=FxImage(image,expression,exception);
4481     if (image != (Image *) NULL)
4482       (void) SetImageChannelMask(image,channel_mask);
4483     if (image == (Image *) NULL)
4484       goto PerlException;
4485     for ( ; image; image=image->next)
4486     {
4487       AddImageToRegistry(sv,image);
4488       rv=newRV(sv);
4489       av_push(av,sv_bless(rv,hv));
4490       SvREFCNT_dec(sv);
4491     }
4492     exception=DestroyExceptionInfo(exception);
4493     ST(0)=av_reference;
4494     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4495     XSRETURN(1);
4496
4497   PerlException:
4498     InheritPerlException(exception,perl_exception);
4499     exception=DestroyExceptionInfo(exception);
4500     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4501     SvPOK_on(perl_exception);
4502     ST(0)=sv_2mortal(perl_exception);
4503     XSRETURN(1);
4504   }
4505 \f
4506 #
4507 ###############################################################################
4508 #                                                                             #
4509 #                                                                             #
4510 #                                                                             #
4511 #   G e t                                                                     #
4512 #                                                                             #
4513 #                                                                             #
4514 #                                                                             #
4515 ###############################################################################
4516 #
4517 #
4518 void
4519 Get(ref,...)
4520   Image::Magick ref=NO_INIT
4521   ALIAS:
4522     GetAttributes = 1
4523     GetAttribute  = 2
4524     get           = 3
4525     getattributes = 4
4526     getattribute  = 5
4527   PPCODE:
4528   {
4529     char
4530       *attribute,
4531       color[MaxTextExtent];
4532
4533     const char
4534       *value;
4535
4536     ExceptionInfo
4537       *exception;
4538
4539     Image
4540       *image;
4541
4542     long
4543       j;
4544
4545     register ssize_t
4546       i;
4547
4548     struct PackageInfo
4549       *info;
4550
4551     SV
4552       *perl_exception,
4553       *reference,
4554       *s;
4555
4556     PERL_UNUSED_VAR(ref);
4557     PERL_UNUSED_VAR(ix);
4558     exception=AcquireExceptionInfo();
4559     perl_exception=newSVpv("",0);
4560     if (sv_isobject(ST(0)) == 0)
4561       {
4562         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4563           PackageName);
4564         XSRETURN_EMPTY;
4565       }
4566     reference=SvRV(ST(0));
4567     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4568     if (image == (Image *) NULL && !info)
4569       XSRETURN_EMPTY;
4570     EXTEND(sp,items);
4571     for (i=1; i < items; i++)
4572     {
4573       attribute=(char *) SvPV(ST(i),na);
4574       s=NULL;
4575       switch (*attribute)
4576       {
4577         case 'A':
4578         case 'a':
4579         {
4580           if (LocaleCompare(attribute,"adjoin") == 0)
4581             {
4582               if (info)
4583                 s=newSViv((ssize_t) info->image_info->adjoin);
4584               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4585               continue;
4586             }
4587           if (LocaleCompare(attribute,"antialias") == 0)
4588             {
4589               if (info)
4590                 s=newSViv((ssize_t) info->image_info->antialias);
4591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4592               continue;
4593             }
4594           if (LocaleCompare(attribute,"area") == 0)
4595             {
4596               s=newSViv(GetMagickResource(AreaResource));
4597               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4598               continue;
4599             }
4600           if (LocaleCompare(attribute,"attenuate") == 0)
4601             {
4602               const char
4603                 *value;
4604
4605               value=GetImageProperty(image,attribute,exception);
4606               if (value != (const char *) NULL)
4607                 s=newSVpv(value,0);
4608               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4609               continue;
4610             }
4611           if (LocaleCompare(attribute,"authenticate") == 0)
4612             {
4613               if (info)
4614                 {
4615                   const char
4616                     *option;
4617
4618                   option=GetImageOption(info->image_info,attribute);
4619                   if (option != (const char *) NULL)
4620                     s=newSVpv(option,0);
4621                 }
4622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4623               continue;
4624             }
4625           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4626             attribute);
4627           break;
4628         }
4629         case 'B':
4630         case 'b':
4631         {
4632           if (LocaleCompare(attribute,"background") == 0)
4633             {
4634               if (image == (Image *) NULL)
4635                 break;
4636               (void) FormatLocaleString(color,MaxTextExtent,
4637                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4638                 image->background_color.green,image->background_color.blue,
4639                 image->background_color.alpha);
4640               s=newSVpv(color,0);
4641               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4642               continue;
4643             }
4644           if (LocaleCompare(attribute,"base-columns") == 0)
4645             {
4646               if (image != (Image *) NULL)
4647                 s=newSViv((ssize_t) image->magick_columns);
4648               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4649               continue;
4650             }
4651           if (LocaleCompare(attribute,"base-filename") == 0)
4652             {
4653               if (image != (Image *) NULL)
4654                 s=newSVpv(image->magick_filename,0);
4655               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4656               continue;
4657             }
4658           if (LocaleCompare(attribute,"base-height") == 0)
4659             {
4660               if (image != (Image *) NULL)
4661                 s=newSViv((ssize_t) image->magick_rows);
4662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4663               continue;
4664             }
4665           if (LocaleCompare(attribute,"base-rows") == 0)
4666             {
4667               if (image != (Image *) NULL)
4668                 s=newSViv((ssize_t) image->magick_rows);
4669               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4670               continue;
4671             }
4672           if (LocaleCompare(attribute,"base-width") == 0)
4673             {
4674               if (image != (Image *) NULL)
4675                 s=newSViv((ssize_t) image->magick_columns);
4676               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4677               continue;
4678             }
4679           if (LocaleCompare(attribute,"blue-primary") == 0)
4680             {
4681               if (image == (Image *) NULL)
4682                 break;
4683               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4684                 image->chromaticity.blue_primary.x,
4685                 image->chromaticity.blue_primary.y);
4686               s=newSVpv(color,0);
4687               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4688               continue;
4689             }
4690           if (LocaleCompare(attribute,"bordercolor") == 0)
4691             {
4692               if (image == (Image *) NULL)
4693                 break;
4694               (void) FormatLocaleString(color,MaxTextExtent,
4695                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4696                 image->border_color.green,image->border_color.blue,
4697                 image->border_color.alpha);
4698               s=newSVpv(color,0);
4699               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4700               continue;
4701             }
4702           if (LocaleCompare(attribute,"bounding-box") == 0)
4703             {
4704               char
4705                 geometry[MaxTextExtent];
4706
4707               RectangleInfo
4708                 page;
4709
4710               if (image == (Image *) NULL)
4711                 break;
4712               page=GetImageBoundingBox(image,exception);
4713               (void) FormatLocaleString(geometry,MaxTextExtent,
4714                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4715                 page.height,(double) page.x,(double) page.y);
4716               s=newSVpv(geometry,0);
4717               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4718               continue;
4719             }
4720           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4721             attribute);
4722           break;
4723         }
4724         case 'C':
4725         case 'c':
4726         {
4727           if (LocaleCompare(attribute,"class") == 0)
4728             {
4729               if (image == (Image *) NULL)
4730                 break;
4731               s=newSViv(image->storage_class);
4732               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4733                 image->storage_class));
4734               SvIOK_on(s);
4735               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4736               continue;
4737             }
4738           if (LocaleCompare(attribute,"clip-mask") == 0)
4739             {
4740               if (image != (Image *) NULL)
4741                 {
4742                   Image
4743                     *mask_image;
4744
4745                   SV
4746                     *sv;
4747
4748                   sv=NULL;
4749                   if (image->read_mask == MagickFalse)
4750                     ClipImage(image,exception);
4751                   mask_image=GetImageMask(image,exception);
4752                   if (mask_image != (Image *) NULL)
4753                     {
4754                       AddImageToRegistry(sv,mask_image);
4755                       s=sv_bless(newRV(sv),SvSTASH(reference));
4756                     }
4757                 }
4758               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4759               continue;
4760             }
4761           if (LocaleCompare(attribute,"clip-path") == 0)
4762             {
4763               if (image != (Image *) NULL)
4764                 {
4765                   Image
4766                     *mask_image;
4767
4768                   SV
4769                     *sv;
4770
4771                   sv=NULL;
4772                   if (image->read_mask != MagickFalse)
4773                     ClipImage(image,exception);
4774                   mask_image=GetImageMask(image,exception);
4775                   if (mask_image != (Image *) NULL)
4776                     {
4777                       AddImageToRegistry(sv,mask_image);
4778                       s=sv_bless(newRV(sv),SvSTASH(reference));
4779                     }
4780                 }
4781               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4782               continue;
4783             }
4784           if (LocaleCompare(attribute,"compression") == 0)
4785             {
4786               j=info ? info->image_info->compression : image ?
4787                 image->compression : UndefinedCompression;
4788               if (info)
4789                 if (info->image_info->compression == UndefinedCompression)
4790                   j=image->compression;
4791               s=newSViv(j);
4792               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4793                 j));
4794               SvIOK_on(s);
4795               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4796               continue;
4797             }
4798           if (LocaleCompare(attribute,"colorspace") == 0)
4799             {
4800               j=image ? image->colorspace : RGBColorspace;
4801               s=newSViv(j);
4802               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4803                 j));
4804               SvIOK_on(s);
4805               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4806               continue;
4807             }
4808           if (LocaleCompare(attribute,"colors") == 0)
4809             {
4810               if (image != (Image *) NULL)
4811                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4812                   exception));
4813               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4814               continue;
4815             }
4816           if (LocaleNCompare(attribute,"colormap",8) == 0)
4817             {
4818               int
4819                 items;
4820
4821               if (image == (Image *) NULL || !image->colormap)
4822                 break;
4823               j=0;
4824               items=sscanf(attribute,"%*[^[][%ld",&j);
4825               (void) items;
4826               if (j > (ssize_t) image->colors)
4827                 j%=image->colors;
4828               (void) FormatLocaleString(color,MaxTextExtent,
4829                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4830                 image->colormap[j].green,image->colormap[j].blue,
4831                 image->colormap[j].alpha);
4832               s=newSVpv(color,0);
4833               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4834               continue;
4835             }
4836           if (LocaleCompare(attribute,"columns") == 0)
4837             {
4838               if (image != (Image *) NULL)
4839                 s=newSViv((ssize_t) image->columns);
4840               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4841               continue;
4842             }
4843           if (LocaleCompare(attribute,"comment") == 0)
4844             {
4845               const char
4846                 *value;
4847
4848               value=GetImageProperty(image,attribute,exception);
4849               if (value != (const char *) NULL)
4850                 s=newSVpv(value,0);
4851               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4852               continue;
4853             }
4854           if (LocaleCompare(attribute,"copyright") == 0)
4855             {
4856               s=newSVpv(GetMagickCopyright(),0);
4857               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4858               continue;
4859             }
4860           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4861             attribute);
4862           break;
4863         }
4864         case 'D':
4865         case 'd':
4866         {
4867           if (LocaleCompare(attribute,"density") == 0)
4868             {
4869               char
4870                 geometry[MaxTextExtent];
4871
4872               if (image == (Image *) NULL)
4873                 break;
4874               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4875                 image->resolution.x,image->resolution.y);
4876               s=newSVpv(geometry,0);
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           if (LocaleCompare(attribute,"delay") == 0)
4881             {
4882               if (image != (Image *) NULL)
4883                 s=newSViv((ssize_t) image->delay);
4884               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885               continue;
4886             }
4887           if (LocaleCompare(attribute,"depth") == 0)
4888             {
4889               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4890               if (image != (Image *) NULL)
4891                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4892               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4893               continue;
4894             }
4895           if (LocaleCompare(attribute,"directory") == 0)
4896             {
4897               if (image && image->directory)
4898                 s=newSVpv(image->directory,0);
4899               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4900               continue;
4901             }
4902           if (LocaleCompare(attribute,"dispose") == 0)
4903             {
4904               if (image == (Image *) NULL)
4905                 break;
4906
4907               s=newSViv(image->dispose);
4908               (void) sv_setpv(s,
4909                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4910               SvIOK_on(s);
4911               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4912               continue;
4913             }
4914           if (LocaleCompare(attribute,"disk") == 0)
4915             {
4916               s=newSViv(GetMagickResource(DiskResource));
4917               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4918               continue;
4919             }
4920           if (LocaleCompare(attribute,"dither") == 0)
4921             {
4922               if (info)
4923                 s=newSViv((ssize_t) info->image_info->dither);
4924               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4925               continue;
4926             }
4927           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4928             {
4929               if (info && info->image_info->server_name)
4930                 s=newSVpv(info->image_info->server_name,0);
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4935             attribute);
4936           break;
4937         }
4938         case 'E':
4939         case 'e':
4940         {
4941           if (LocaleCompare(attribute,"elapsed-time") == 0)
4942             {
4943               if (image != (Image *) NULL)
4944                 s=newSVnv(GetElapsedTime(&image->timer));
4945               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4946               continue;
4947             }
4948           if (LocaleCompare(attribute,"endian") == 0)
4949             {
4950               j=info ? info->image_info->endian : image ? image->endian :
4951                 UndefinedEndian;
4952               s=newSViv(j);
4953               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4954               SvIOK_on(s);
4955               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4956               continue;
4957             }
4958           if (LocaleCompare(attribute,"error") == 0)
4959             {
4960               if (image != (Image *) NULL)
4961                 s=newSVnv(image->error.mean_error_per_pixel);
4962               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4963               continue;
4964             }
4965           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4966             attribute);
4967           break;
4968         }
4969         case 'F':
4970         case 'f':
4971         {
4972           if (LocaleCompare(attribute,"filesize") == 0)
4973             {
4974               if (image != (Image *) NULL)
4975                 s=newSViv((ssize_t) GetBlobSize(image));
4976               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4977               continue;
4978             }
4979           if (LocaleCompare(attribute,"filename") == 0)
4980             {
4981               if (info && info->image_info->filename &&
4982                   *info->image_info->filename)
4983                 s=newSVpv(info->image_info->filename,0);
4984               if (image != (Image *) NULL)
4985                 s=newSVpv(image->filename,0);
4986               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4987               continue;
4988             }
4989           if (LocaleCompare(attribute,"filter") == 0)
4990             {
4991               s=image ? newSViv(image->filter) : newSViv(0);
4992               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4993                 image->filter));
4994               SvIOK_on(s);
4995               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4996               continue;
4997             }
4998           if (LocaleCompare(attribute,"font") == 0)
4999             {
5000               if (info && info->image_info->font)
5001                 s=newSVpv(info->image_info->font,0);
5002               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5003               continue;
5004             }
5005           if (LocaleCompare(attribute,"foreground") == 0)
5006             continue;
5007           if (LocaleCompare(attribute,"format") == 0)
5008             {
5009               const MagickInfo
5010                 *magick_info;
5011
5012               magick_info=(const MagickInfo *) NULL;
5013               if (info && (*info->image_info->magick != '\0'))
5014                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5015               if (image != (Image *) NULL)
5016                 magick_info=GetMagickInfo(image->magick,exception);
5017               if ((magick_info != (const MagickInfo *) NULL) &&
5018                   (*magick_info->description != '\0'))
5019                 s=newSVpv((char *) magick_info->description,0);
5020               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5021               continue;
5022             }
5023           if (LocaleCompare(attribute,"fuzz") == 0)
5024             {
5025               if (info)
5026                 s=newSVnv(info->image_info->fuzz);
5027               if (image != (Image *) NULL)
5028                 s=newSVnv(image->fuzz);
5029               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5030               continue;
5031             }
5032           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5033             attribute);
5034           break;
5035         }
5036         case 'G':
5037         case 'g':
5038         {
5039           if (LocaleCompare(attribute,"gamma") == 0)
5040             {
5041               if (image != (Image *) NULL)
5042                 s=newSVnv(image->gamma);
5043               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5044               continue;
5045             }
5046           if (LocaleCompare(attribute,"geometry") == 0)
5047             {
5048               if (image && image->geometry)
5049                 s=newSVpv(image->geometry,0);
5050               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5051               continue;
5052             }
5053           if (LocaleCompare(attribute,"gravity") == 0)
5054             {
5055               s=image ? newSViv(image->gravity) : newSViv(0);
5056               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5057                 image->gravity));
5058               SvIOK_on(s);
5059               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5060               continue;
5061             }
5062           if (LocaleCompare(attribute,"green-primary") == 0)
5063             {
5064               if (image == (Image *) NULL)
5065                 break;
5066               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5067                 image->chromaticity.green_primary.x,
5068                 image->chromaticity.green_primary.y);
5069               s=newSVpv(color,0);
5070               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5071               continue;
5072             }
5073           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5074             attribute);
5075           break;
5076         }
5077         case 'H':
5078         case 'h':
5079         {
5080           if (LocaleCompare(attribute,"height") == 0)
5081             {
5082               if (image != (Image *) NULL)
5083                 s=newSViv((ssize_t) image->rows);
5084               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5085               continue;
5086             }
5087           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5088             attribute);
5089           break;
5090         }
5091         case 'I':
5092         case 'i':
5093         {
5094           if (LocaleCompare(attribute,"icc") == 0)
5095             {
5096               if (image != (Image *) NULL)
5097                 {
5098                   const StringInfo
5099                     *profile;
5100
5101                   profile=GetImageProfile(image,"icc");
5102                   if (profile != (StringInfo *) NULL)
5103                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5104                       GetStringInfoLength(profile));
5105                 }
5106               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5107               continue;
5108             }
5109           if (LocaleCompare(attribute,"icm") == 0)
5110             {
5111               if (image != (Image *) NULL)
5112                 {
5113                   const StringInfo
5114                     *profile;
5115
5116                   profile=GetImageProfile(image,"icm");
5117                   if (profile != (const StringInfo *) NULL)
5118                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5119                       GetStringInfoLength(profile));
5120                 }
5121               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122               continue;
5123             }
5124           if (LocaleCompare(attribute,"id") == 0)
5125             {
5126               if (image != (Image *) NULL)
5127                 {
5128                   char
5129                     key[MaxTextExtent];
5130
5131                   MagickBooleanType
5132                     status;
5133
5134                   static ssize_t
5135                     id = 0;
5136
5137                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
5138                     id);
5139                   status=SetImageRegistry(ImageRegistryType,key,image,
5140                     exception);
5141                   (void) status;
5142                   s=newSViv(id++);
5143                 }
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           if (LocaleNCompare(attribute,"index",5) == 0)
5148             {
5149               char
5150                 name[MaxTextExtent];
5151
5152               int
5153                 items;
5154
5155               long
5156                 x,
5157                 y;
5158
5159               register const Quantum
5160                 *p;
5161
5162               CacheView
5163                 *image_view;
5164
5165               if (image == (Image *) NULL)
5166                 break;
5167               if (image->storage_class != PseudoClass)
5168                 break;
5169               x=0;
5170               y=0;
5171               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5172               (void) items;
5173               image_view=AcquireVirtualCacheView(image,exception);
5174               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5175               if (p != (const Quantum *) NULL)
5176                 {
5177                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5178                     GetPixelIndex(image,p));
5179                   s=newSVpv(name,0);
5180                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5181                 }
5182               image_view=DestroyCacheView(image_view);
5183               continue;
5184             }
5185           if (LocaleCompare(attribute,"iptc") == 0)
5186             {
5187               if (image != (Image *) NULL)
5188                 {
5189                   const StringInfo
5190                     *profile;
5191
5192                   profile=GetImageProfile(image,"iptc");
5193                   if (profile != (const StringInfo *) NULL)
5194                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5195                       GetStringInfoLength(profile));
5196                 }
5197               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5198               continue;
5199             }
5200           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5201             {
5202               if (image != (Image *) NULL)
5203                 s=newSViv((ssize_t) image->iterations);
5204               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5205               continue;
5206             }
5207           if (LocaleCompare(attribute,"interlace") == 0)
5208             {
5209               j=info ? info->image_info->interlace : image ? image->interlace :
5210                 UndefinedInterlace;
5211               s=newSViv(j);
5212               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5213                 j));
5214               SvIOK_on(s);
5215               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5216               continue;
5217             }
5218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5219             attribute);
5220           break;
5221         }
5222         case 'L':
5223         case 'l':
5224         {
5225           if (LocaleCompare(attribute,"label") == 0)
5226             {
5227               const char
5228                 *value;
5229
5230               if (image == (Image *) NULL)
5231                 break;
5232               value=GetImageProperty(image,"Label",exception);
5233               if (value != (const char *) NULL)
5234                 s=newSVpv(value,0);
5235               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5236               continue;
5237             }
5238           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5239             {
5240               if (image != (Image *) NULL)
5241                 s=newSViv((ssize_t) image->iterations);
5242               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5243               continue;
5244             }
5245           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5246             attribute);
5247           break;
5248         }
5249         case 'M':
5250         case 'm':
5251         {
5252           if (LocaleCompare(attribute,"magick") == 0)
5253             {
5254               if (info && *info->image_info->magick)
5255                 s=newSVpv(info->image_info->magick,0);
5256               if (image != (Image *) NULL)
5257                 s=newSVpv(image->magick,0);
5258               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5259               continue;
5260             }
5261           if (LocaleCompare(attribute,"map") == 0)
5262             {
5263               s=newSViv(GetMagickResource(MapResource));
5264               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5265               continue;
5266             }
5267           if (LocaleCompare(attribute,"maximum-error") == 0)
5268             {
5269               if (image != (Image *) NULL)
5270                 s=newSVnv(image->error.normalized_maximum_error);
5271               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5272               continue;
5273             }
5274           if (LocaleCompare(attribute,"memory") == 0)
5275             {
5276               s=newSViv(GetMagickResource(MemoryResource));
5277               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5278               continue;
5279             }
5280           if (LocaleCompare(attribute,"mean-error") == 0)
5281             {
5282               if (image != (Image *) NULL)
5283                 s=newSVnv(image->error.normalized_mean_error);
5284               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5285               continue;
5286             }
5287           if (LocaleCompare(attribute,"mime") == 0)
5288             {
5289               if (info && *info->image_info->magick)
5290                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5291               if (image != (Image *) NULL)
5292                 s=newSVpv(MagickToMime(image->magick),0);
5293               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5294               continue;
5295             }
5296           if (LocaleCompare(attribute,"mattecolor") == 0)
5297             {
5298               if (image == (Image *) NULL)
5299                 break;
5300               (void) FormatLocaleString(color,MaxTextExtent,
5301                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5302                 image->matte_color.green,image->matte_color.blue,
5303                 image->matte_color.alpha);
5304               s=newSVpv(color,0);
5305               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5306               continue;
5307             }
5308           if (LocaleCompare(attribute,"matte") == 0)
5309             {
5310               if (image != (Image *) NULL)
5311                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5312                   1 : 0);
5313               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5314               continue;
5315             }
5316           if (LocaleCompare(attribute,"mime") == 0)
5317             {
5318               const char
5319                 *magick;
5320
5321               magick=NULL;
5322               if (info && *info->image_info->magick)
5323                 magick=info->image_info->magick;
5324               if (image != (Image *) NULL)
5325                 magick=image->magick;
5326               if (magick)
5327                 {
5328                   char
5329                     *mime;
5330
5331                   mime=MagickToMime(magick);
5332                   s=newSVpv(mime,0);
5333                   mime=(char *) RelinquishMagickMemory(mime);
5334                 }
5335               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5336               continue;
5337             }
5338           if (LocaleCompare(attribute,"monochrome") == 0)
5339             {
5340               if (image == (Image *) NULL)
5341                 continue;
5342               j=info ? info->image_info->monochrome :
5343                 IsImageMonochrome(image,exception);
5344               s=newSViv(j);
5345               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5346               continue;
5347             }
5348           if (LocaleCompare(attribute,"montage") == 0)
5349             {
5350               if (image && image->montage)
5351                 s=newSVpv(image->montage,0);
5352               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5353               continue;
5354             }
5355           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5356             attribute);
5357           break;
5358         }
5359         case 'O':
5360         case 'o':
5361         {
5362           if (LocaleCompare(attribute,"orientation") == 0)
5363             {
5364               j=info ? info->image_info->orientation : image ?
5365                 image->orientation : UndefinedOrientation;
5366               s=newSViv(j);
5367               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5368                 j));
5369               SvIOK_on(s);
5370               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5371               continue;
5372             }
5373           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5374             attribute);
5375           break;
5376         }
5377         case 'P':
5378         case 'p':
5379         {
5380           if (LocaleCompare(attribute,"page") == 0)
5381             {
5382               if (info && info->image_info->page)
5383                 s=newSVpv(info->image_info->page,0);
5384               if (image != (Image *) NULL)
5385                 {
5386                   char
5387                     geometry[MaxTextExtent];
5388
5389                   (void) FormatLocaleString(geometry,MaxTextExtent,
5390                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5391                     (double) image->page.height,(double) image->page.x,(double)
5392                     image->page.y);
5393                   s=newSVpv(geometry,0);
5394                 }
5395               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5396               continue;
5397             }
5398           if (LocaleCompare(attribute,"page.x") == 0)
5399             {
5400               if (image != (Image *) NULL)
5401                 s=newSViv((ssize_t) image->page.x);
5402               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403               continue;
5404             }
5405           if (LocaleCompare(attribute,"page.y") == 0)
5406             {
5407               if (image != (Image *) NULL)
5408                 s=newSViv((ssize_t) image->page.y);
5409               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5410               continue;
5411             }
5412           if (LocaleNCompare(attribute,"pixel",5) == 0)
5413             {
5414               char
5415                 tuple[MaxTextExtent];
5416
5417               int
5418                 items;
5419
5420               long
5421                 x,
5422                 y;
5423
5424               register const Quantum
5425                 *p;
5426
5427               if (image == (Image *) NULL)
5428                 break;
5429               x=0;
5430               y=0;
5431               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5432               (void) items;
5433               p=GetVirtualPixels(image,x,y,1,1,exception);
5434               if (image->colorspace != CMYKColorspace)
5435                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5436                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5437                   GetPixelRed(image,p),GetPixelGreen(image,p),
5438                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5439               else
5440                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5441                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5442                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5443                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5444                   GetPixelAlpha(image,p));
5445               s=newSVpv(tuple,0);
5446               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5447               continue;
5448             }
5449           if (LocaleCompare(attribute,"pointsize") == 0)
5450             {
5451               if (info)
5452                 s=newSViv((ssize_t) info->image_info->pointsize);
5453               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5454               continue;
5455             }
5456           if (LocaleCompare(attribute,"preview") == 0)
5457             {
5458               s=newSViv(info->image_info->preview_type);
5459               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5460                 info->image_info->preview_type));
5461               SvIOK_on(s);
5462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5463               continue;
5464             }
5465           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5466             attribute);
5467           break;
5468         }
5469         case 'Q':
5470         case 'q':
5471         {
5472           if (LocaleCompare(attribute,"quality") == 0)
5473             {
5474               if (info)
5475                 s=newSViv((ssize_t) info->image_info->quality);
5476               if (image != (Image *) NULL)
5477                 s=newSViv((ssize_t) image->quality);
5478               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5479               continue;
5480             }
5481           if (LocaleCompare(attribute,"quantum") == 0)
5482             {
5483               if (info)
5484                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5485               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5486               continue;
5487             }
5488           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5489             attribute);
5490           break;
5491         }
5492         case 'R':
5493         case 'r':
5494         {
5495           if (LocaleCompare(attribute,"rendering-intent") == 0)
5496             {
5497               s=newSViv(image->rendering_intent);
5498               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5499                 image->rendering_intent));
5500               SvIOK_on(s);
5501               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5502               continue;
5503             }
5504           if (LocaleCompare(attribute,"red-primary") == 0)
5505             {
5506               if (image == (Image *) NULL)
5507                 break;
5508               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5509                 image->chromaticity.red_primary.x,
5510                 image->chromaticity.red_primary.y);
5511               s=newSVpv(color,0);
5512               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5513               continue;
5514             }
5515           if (LocaleCompare(attribute,"rows") == 0)
5516             {
5517               if (image != (Image *) NULL)
5518                 s=newSViv((ssize_t) image->rows);
5519               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5520               continue;
5521             }
5522           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5523             attribute);
5524           break;
5525         }
5526         case 'S':
5527         case 's':
5528         {
5529           if (LocaleCompare(attribute,"sampling-factor") == 0)
5530             {
5531               if (info && info->image_info->sampling_factor)
5532                 s=newSVpv(info->image_info->sampling_factor,0);
5533               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5534               continue;
5535             }
5536           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5537             {
5538               if (info && info->image_info->server_name)
5539                 s=newSVpv(info->image_info->server_name,0);
5540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5541               continue;
5542             }
5543           if (LocaleCompare(attribute,"size") == 0)
5544             {
5545               if (info && info->image_info->size)
5546                 s=newSVpv(info->image_info->size,0);
5547               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5548               continue;
5549             }
5550           if (LocaleCompare(attribute,"scene") == 0)
5551             {
5552               if (image != (Image *) NULL)
5553                 s=newSViv((ssize_t) image->scene);
5554               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5555               continue;
5556             }
5557           if (LocaleCompare(attribute,"scenes") == 0)
5558             {
5559               if (image != (Image *) NULL)
5560                 s=newSViv((ssize_t) info->image_info->number_scenes);
5561               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5562               continue;
5563             }
5564           if (LocaleCompare(attribute,"signature") == 0)
5565             {
5566               const char
5567                 *value;
5568
5569               if (image == (Image *) NULL)
5570                 break;
5571               (void) SignatureImage(image,exception);
5572               value=GetImageProperty(image,"Signature",exception);
5573               if (value != (const char *) NULL)
5574                 s=newSVpv(value,0);
5575               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5576               continue;
5577             }
5578           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5579             attribute);
5580           break;
5581         }
5582         case 'T':
5583         case 't':
5584         {
5585           if (LocaleCompare(attribute,"taint") == 0)
5586             {
5587               if (image != (Image *) NULL)
5588                 s=newSViv((ssize_t) IsTaintImage(image));
5589               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5590               continue;
5591             }
5592           if (LocaleCompare(attribute,"texture") == 0)
5593             {
5594               if (info && info->image_info->texture)
5595                 s=newSVpv(info->image_info->texture,0);
5596               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5597               continue;
5598             }
5599           if (LocaleCompare(attribute,"total-ink-density") == 0)
5600             {
5601               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5602               if (image != (Image *) NULL)
5603                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5604               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5605               continue;
5606             }
5607           if (LocaleCompare(attribute,"transparent-color") == 0)
5608             {
5609               if (image == (Image *) NULL)
5610                 break;
5611               (void) FormatLocaleString(color,MaxTextExtent,
5612                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5613                 image->transparent_color.green,image->transparent_color.blue,
5614                 image->transparent_color.alpha);
5615               s=newSVpv(color,0);
5616               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5617               continue;
5618             }
5619           if (LocaleCompare(attribute,"type") == 0)
5620             {
5621               if (image == (Image *) NULL)
5622                 break;
5623               j=(ssize_t) GetImageType(image,exception);
5624               s=newSViv(j);
5625               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5626               SvIOK_on(s);
5627               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5628               continue;
5629             }
5630           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5631             attribute);
5632           break;
5633         }
5634         case 'U':
5635         case 'u':
5636         {
5637           if (LocaleCompare(attribute,"units") == 0)
5638             {
5639               j=info ? info->image_info->units : image ? image->units :
5640                 UndefinedResolution;
5641               if (info && (info->image_info->units == UndefinedResolution))
5642                 if (image)
5643                   j=image->units;
5644               if (j == UndefinedResolution)
5645                 s=newSVpv("undefined units",0);
5646               else
5647                 if (j == PixelsPerInchResolution)
5648                   s=newSVpv("pixels / inch",0);
5649                 else
5650                   s=newSVpv("pixels / centimeter",0);
5651               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5652               continue;
5653             }
5654           if (LocaleCompare(attribute,"user-time") == 0)
5655             {
5656               if (image != (Image *) NULL)
5657                 s=newSVnv(GetUserTime(&image->timer));
5658               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5659               continue;
5660             }
5661           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5662             attribute);
5663           break;
5664         }
5665         case 'V':
5666         case 'v':
5667         {
5668           if (LocaleCompare(attribute,"verbose") == 0)
5669             {
5670               if (info)
5671                 s=newSViv((ssize_t) info->image_info->verbose);
5672               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5673               continue;
5674             }
5675           if (LocaleCompare(attribute,"version") == 0)
5676             {
5677               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5678               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5679               continue;
5680             }
5681           if (LocaleCompare(attribute,"view") == 0)
5682             {
5683               if (info && info->image_info->view)
5684                 s=newSVpv(info->image_info->view,0);
5685               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5686               continue;
5687             }
5688           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5689             {
5690               if (image == (Image *) NULL)
5691                 break;
5692               j=(ssize_t) GetImageVirtualPixelMethod(image);
5693               s=newSViv(j);
5694               (void) sv_setpv(s,CommandOptionToMnemonic(
5695                 MagickVirtualPixelOptions,j));
5696               SvIOK_on(s);
5697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5698               continue;
5699             }
5700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5701             attribute);
5702           break;
5703         }
5704         case 'W':
5705         case 'w':
5706         {
5707           if (LocaleCompare(attribute,"white-point") == 0)
5708             {
5709               if (image == (Image *) NULL)
5710                 break;
5711               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5712                 image->chromaticity.white_point.x,
5713                 image->chromaticity.white_point.y);
5714               s=newSVpv(color,0);
5715               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5716               continue;
5717             }
5718           if (LocaleCompare(attribute,"width") == 0)
5719             {
5720               if (image != (Image *) NULL)
5721                 s=newSViv((ssize_t) image->columns);
5722               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5723               continue;
5724             }
5725           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5726              attribute);
5727           break;
5728         }
5729         case 'X':
5730         case 'x':
5731         {
5732           if (LocaleCompare(attribute,"x-resolution") == 0)
5733             {
5734               if (image != (Image *) NULL)
5735                 s=newSVnv(image->resolution.x);
5736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5737               continue;
5738             }
5739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5740             attribute);
5741           break;
5742         }
5743         case 'Y':
5744         case 'y':
5745         {
5746           if (LocaleCompare(attribute,"y-resolution") == 0)
5747             {
5748               if (image != (Image *) NULL)
5749                 s=newSVnv(image->resolution.y);
5750               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5751               continue;
5752             }
5753           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5754             attribute);
5755           break;
5756         }
5757         default:
5758           break;
5759       }
5760       if (image == (Image *) NULL)
5761         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5762           attribute)
5763       else
5764         {
5765           value=GetImageProperty(image,attribute,exception);
5766           if (value != (const char *) NULL)
5767             {
5768               s=newSVpv(value,0);
5769               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5770             }
5771           else
5772             if (*attribute != '%')
5773               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5774                 attribute)
5775             else
5776               {
5777                  char
5778                    *meta;
5779
5780                  meta=InterpretImageProperties(info ? info->image_info :
5781                    (ImageInfo *) NULL,image,attribute,exception);
5782                  s=newSVpv(meta,0);
5783                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5784                  meta=(char *) RelinquishMagickMemory(meta);
5785               }
5786         }
5787     }
5788     exception=DestroyExceptionInfo(exception);
5789     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5790   }
5791 \f
5792 #
5793 ###############################################################################
5794 #                                                                             #
5795 #                                                                             #
5796 #                                                                             #
5797 #   G e t A u t h e n t i c P i x e l s                                       #
5798 #                                                                             #
5799 #                                                                             #
5800 #                                                                             #
5801 ###############################################################################
5802 #
5803 #
5804 void *
5805 GetAuthenticPixels(ref,...)
5806   Image::Magick ref = NO_INIT
5807   ALIAS:
5808     getauthenticpixels = 1
5809     GetImagePixels = 2
5810     getimagepixels = 3
5811   CODE:
5812   {
5813     char
5814       *attribute;
5815
5816     ExceptionInfo
5817       *exception;
5818
5819     Image
5820       *image;
5821
5822     RectangleInfo
5823       region;
5824
5825     ssize_t
5826       i;
5827
5828     struct PackageInfo
5829       *info;
5830
5831     SV
5832       *perl_exception,
5833       *reference;
5834
5835     void
5836       *blob = NULL;
5837
5838     PERL_UNUSED_VAR(ref);
5839     PERL_UNUSED_VAR(ix);
5840     exception=AcquireExceptionInfo();
5841     perl_exception=newSVpv("",0);
5842     if (sv_isobject(ST(0)) == 0)
5843       {
5844         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5845           PackageName);
5846         goto PerlException;
5847       }
5848     reference=SvRV(ST(0));
5849
5850     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5851     if (image == (Image *) NULL)
5852       {
5853         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5854           PackageName);
5855         goto PerlException;
5856       }
5857
5858     region.x=0;
5859     region.y=0;
5860     region.width=image->columns;
5861     region.height=1;
5862     if (items == 1)
5863       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5864     for (i=2; i < items; i+=2)
5865     {
5866       attribute=(char *) SvPV(ST(i-1),na);
5867       switch (*attribute)
5868       {
5869         case 'g':
5870         case 'G':
5871         {
5872           if (LocaleCompare(attribute,"geometry") == 0)
5873             {
5874               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5875               break;
5876             }
5877           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5878             attribute);
5879           break;
5880         }
5881         case 'H':
5882         case 'h':
5883         {
5884           if (LocaleCompare(attribute,"height") == 0)
5885             {
5886               region.height=SvIV(ST(i));
5887               continue;
5888             }
5889           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5890             attribute);
5891           break;
5892         }
5893         case 'X':
5894         case 'x':
5895         {
5896           if (LocaleCompare(attribute,"x") == 0)
5897             {
5898               region.x=SvIV(ST(i));
5899               continue;
5900             }
5901           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5902             attribute);
5903           break;
5904         }
5905         case 'Y':
5906         case 'y':
5907         {
5908           if (LocaleCompare(attribute,"y") == 0)
5909             {
5910               region.y=SvIV(ST(i));
5911               continue;
5912             }
5913           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5914             attribute);
5915           break;
5916         }
5917         case 'W':
5918         case 'w':
5919         {
5920           if (LocaleCompare(attribute,"width") == 0)
5921             {
5922               region.width=SvIV(ST(i));
5923               continue;
5924             }
5925           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5926             attribute);
5927           break;
5928         }
5929       }
5930     }
5931     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5932       region.height,exception);
5933     if (blob != (void *) NULL)
5934       goto PerlEnd;
5935
5936   PerlException:
5937     InheritPerlException(exception,perl_exception);
5938     exception=DestroyExceptionInfo(exception);
5939     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5940
5941   PerlEnd:
5942     RETVAL = blob;
5943   }
5944   OUTPUT:
5945     RETVAL
5946 \f
5947 #
5948 ###############################################################################
5949 #                                                                             #
5950 #                                                                             #
5951 #                                                                             #
5952 #   G e t V i r t u a l P i x e l s                                           #
5953 #                                                                             #
5954 #                                                                             #
5955 #                                                                             #
5956 ###############################################################################
5957 #
5958 #
5959 void *
5960 GetVirtualPixels(ref,...)
5961   Image::Magick ref = NO_INIT
5962   ALIAS:
5963     getvirtualpixels = 1
5964     AcquireImagePixels = 2
5965     acquireimagepixels = 3
5966   CODE:
5967   {
5968     char
5969       *attribute;
5970
5971     const void
5972       *blob = NULL;
5973
5974     ExceptionInfo
5975       *exception;
5976
5977     Image
5978       *image;
5979
5980     RectangleInfo
5981       region;
5982
5983     ssize_t
5984       i;
5985
5986     struct PackageInfo
5987       *info;
5988
5989     SV
5990       *perl_exception,
5991       *reference;
5992
5993     PERL_UNUSED_VAR(ref);
5994     PERL_UNUSED_VAR(ix);
5995     exception=AcquireExceptionInfo();
5996     perl_exception=newSVpv("",0);
5997     if (sv_isobject(ST(0)) == 0)
5998       {
5999         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6000           PackageName);
6001         goto PerlException;
6002       }
6003     reference=SvRV(ST(0));
6004
6005     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6006     if (image == (Image *) NULL)
6007       {
6008         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6009           PackageName);
6010         goto PerlException;
6011       }
6012
6013     region.x=0;
6014     region.y=0;
6015     region.width=image->columns;
6016     region.height=1;
6017     if (items == 1)
6018       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6019     for (i=2; i < items; i+=2)
6020     {
6021       attribute=(char *) SvPV(ST(i-1),na);
6022       switch (*attribute)
6023       {
6024         case 'g':
6025         case 'G':
6026         {
6027           if (LocaleCompare(attribute,"geometry") == 0)
6028             {
6029               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6030               break;
6031             }
6032           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6033             attribute);
6034           break;
6035         }
6036         case 'H':
6037         case 'h':
6038         {
6039           if (LocaleCompare(attribute,"height") == 0)
6040             {
6041               region.height=SvIV(ST(i));
6042               continue;
6043             }
6044           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6045             attribute);
6046           break;
6047         }
6048         case 'X':
6049         case 'x':
6050         {
6051           if (LocaleCompare(attribute,"x") == 0)
6052             {
6053               region.x=SvIV(ST(i));
6054               continue;
6055             }
6056           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6057             attribute);
6058           break;
6059         }
6060         case 'Y':
6061         case 'y':
6062         {
6063           if (LocaleCompare(attribute,"y") == 0)
6064             {
6065               region.y=SvIV(ST(i));
6066               continue;
6067             }
6068           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6069             attribute);
6070           break;
6071         }
6072         case 'W':
6073         case 'w':
6074         {
6075           if (LocaleCompare(attribute,"width") == 0)
6076             {
6077               region.width=SvIV(ST(i));
6078               continue;
6079             }
6080           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6081             attribute);
6082           break;
6083         }
6084       }
6085     }
6086     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6087       region.height,exception);
6088     if (blob != (void *) NULL)
6089       goto PerlEnd;
6090
6091   PerlException:
6092     InheritPerlException(exception,perl_exception);
6093     exception=DestroyExceptionInfo(exception);
6094     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6095
6096   PerlEnd:
6097     RETVAL = (void *) blob;
6098   }
6099   OUTPUT:
6100     RETVAL
6101 \f
6102 #
6103 ###############################################################################
6104 #                                                                             #
6105 #                                                                             #
6106 #                                                                             #
6107 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6108 #                                                                             #
6109 #                                                                             #
6110 #                                                                             #
6111 ###############################################################################
6112 #
6113 #
6114 void *
6115 GetAuthenticMetacontent(ref,...)
6116   Image::Magick ref = NO_INIT
6117   ALIAS:
6118     getauthenticmetacontent = 1
6119     GetMetacontent = 2
6120     getmetacontent = 3
6121   CODE:
6122   {
6123     ExceptionInfo
6124       *exception;
6125
6126     Image
6127       *image;
6128
6129     struct PackageInfo
6130       *info;
6131
6132     SV
6133       *perl_exception,
6134       *reference;
6135
6136     void
6137       *blob = NULL;
6138
6139     PERL_UNUSED_VAR(ref);
6140     PERL_UNUSED_VAR(ix);
6141     exception=AcquireExceptionInfo();
6142     perl_exception=newSVpv("",0);
6143     if (sv_isobject(ST(0)) == 0)
6144       {
6145         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6146           PackageName);
6147         goto PerlException;
6148       }
6149     reference=SvRV(ST(0));
6150
6151     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6152     if (image == (Image *) NULL)
6153       {
6154         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6155           PackageName);
6156         goto PerlException;
6157       }
6158
6159     blob=(void *) GetAuthenticMetacontent(image);
6160     if (blob != (void *) NULL)
6161       goto PerlEnd;
6162
6163   PerlException:
6164     InheritPerlException(exception,perl_exception);
6165     exception=DestroyExceptionInfo(exception);
6166     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6167
6168   PerlEnd:
6169     RETVAL = blob;
6170   }
6171   OUTPUT:
6172     RETVAL
6173 \f
6174 #
6175 ###############################################################################
6176 #                                                                             #
6177 #                                                                             #
6178 #                                                                             #
6179 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6180 #                                                                             #
6181 #                                                                             #
6182 #                                                                             #
6183 ###############################################################################
6184 #
6185 #
6186 void *
6187 GetVirtualMetacontent(ref,...)
6188   Image::Magick ref = NO_INIT
6189   ALIAS:
6190     getvirtualmetacontent = 1
6191   CODE:
6192   {
6193     ExceptionInfo
6194       *exception;
6195
6196     Image
6197       *image;
6198
6199     struct PackageInfo
6200       *info;
6201
6202     SV
6203       *perl_exception,
6204       *reference;
6205
6206     void
6207       *blob = NULL;
6208
6209     PERL_UNUSED_VAR(ref);
6210     PERL_UNUSED_VAR(ix);
6211     exception=AcquireExceptionInfo();
6212     perl_exception=newSVpv("",0);
6213     if (sv_isobject(ST(0)) == 0)
6214       {
6215         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6216           PackageName);
6217         goto PerlException;
6218       }
6219     reference=SvRV(ST(0));
6220
6221     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6222     if (image == (Image *) NULL)
6223       {
6224         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6225           PackageName);
6226         goto PerlException;
6227       }
6228
6229     blob=(void *) GetVirtualMetacontent(image);
6230     if (blob != (void *) NULL)
6231       goto PerlEnd;
6232
6233   PerlException:
6234     InheritPerlException(exception,perl_exception);
6235     exception=DestroyExceptionInfo(exception);
6236     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6237
6238   PerlEnd:
6239     RETVAL = blob;
6240   }
6241   OUTPUT:
6242     RETVAL
6243 \f
6244 #
6245 ###############################################################################
6246 #                                                                             #
6247 #                                                                             #
6248 #                                                                             #
6249 #   H i s t o g r a m                                                         #
6250 #                                                                             #
6251 #                                                                             #
6252 #                                                                             #
6253 ###############################################################################
6254 #
6255 #
6256 void
6257 Histogram(ref,...)
6258   Image::Magick ref=NO_INIT
6259   ALIAS:
6260     HistogramImage = 1
6261     histogram      = 2
6262     histogramimage = 3
6263   PPCODE:
6264   {
6265     AV
6266       *av;
6267
6268     char
6269       message[MaxTextExtent];
6270
6271     PixelInfo
6272       *histogram;
6273
6274     ExceptionInfo
6275       *exception;
6276
6277     Image
6278       *image;
6279
6280     register ssize_t
6281       i;
6282
6283     ssize_t
6284       count;
6285
6286     struct PackageInfo
6287       *info;
6288
6289     SV
6290       *perl_exception,
6291       *reference;
6292
6293     size_t
6294       number_colors;
6295
6296     PERL_UNUSED_VAR(ref);
6297     PERL_UNUSED_VAR(ix);
6298     exception=AcquireExceptionInfo();
6299     perl_exception=newSVpv("",0);
6300     av=NULL;
6301     if (sv_isobject(ST(0)) == 0)
6302       {
6303         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6304           PackageName);
6305         goto PerlException;
6306       }
6307     reference=SvRV(ST(0));
6308     av=newAV();
6309     SvREFCNT_dec(av);
6310     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6311     if (image == (Image *) NULL)
6312       {
6313         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6314           PackageName);
6315         goto PerlException;
6316       }
6317     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6318     count=0;
6319     for ( ; image; image=image->next)
6320     {
6321       histogram=GetImageHistogram(image,&number_colors,exception);
6322       if (histogram == (PixelInfo *) NULL)
6323         continue;
6324       count+=(ssize_t) number_colors;
6325       EXTEND(sp,6*count);
6326       for (i=0; i < (ssize_t) number_colors; i++)
6327       {
6328         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6329           histogram[i].red);
6330         PUSHs(sv_2mortal(newSVpv(message,0)));
6331         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6332           histogram[i].green);
6333         PUSHs(sv_2mortal(newSVpv(message,0)));
6334         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6335           histogram[i].blue);
6336         PUSHs(sv_2mortal(newSVpv(message,0)));
6337         if (image->colorspace == CMYKColorspace)
6338           {
6339             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6340               histogram[i].black);
6341             PUSHs(sv_2mortal(newSVpv(message,0)));
6342           }
6343         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6344           histogram[i].alpha);
6345         PUSHs(sv_2mortal(newSVpv(message,0)));
6346         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6347           histogram[i].count);
6348         PUSHs(sv_2mortal(newSVpv(message,0)));
6349       }
6350       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6351     }
6352
6353   PerlException:
6354     InheritPerlException(exception,perl_exception);
6355     exception=DestroyExceptionInfo(exception);
6356     SvREFCNT_dec(perl_exception);
6357   }
6358 \f
6359 #
6360 ###############################################################################
6361 #                                                                             #
6362 #                                                                             #
6363 #                                                                             #
6364 #   G e t P i x e l                                                           #
6365 #                                                                             #
6366 #                                                                             #
6367 #                                                                             #
6368 ###############################################################################
6369 #
6370 #
6371 void
6372 GetPixel(ref,...)
6373   Image::Magick ref=NO_INIT
6374   ALIAS:
6375     getpixel = 1
6376     getPixel = 2
6377   PPCODE:
6378   {
6379     AV
6380       *av;
6381
6382     char
6383       *attribute;
6384
6385     ExceptionInfo
6386       *exception;
6387
6388     Image
6389       *image;
6390
6391     MagickBooleanType
6392       normalize;
6393
6394     RectangleInfo
6395       region;
6396
6397     register const Quantum
6398       *p;
6399
6400     register ssize_t
6401       i;
6402
6403     ssize_t
6404       option;
6405
6406     struct PackageInfo
6407       *info;
6408
6409     SV
6410       *perl_exception,
6411       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6412
6413     PERL_UNUSED_VAR(ref);
6414     PERL_UNUSED_VAR(ix);
6415     exception=AcquireExceptionInfo();
6416     perl_exception=newSVpv("",0);
6417     reference=SvRV(ST(0));
6418     av=(AV *) reference;
6419     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6420       exception);
6421     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6422     if (image == (Image *) NULL)
6423       {
6424         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6425           PackageName);
6426         goto PerlException;
6427       }
6428     normalize=MagickTrue;
6429     region.x=0;
6430     region.y=0;
6431     region.width=image->columns;
6432     region.height=1;
6433     if (items == 1)
6434       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6435     for (i=2; i < items; i+=2)
6436     {
6437       attribute=(char *) SvPV(ST(i-1),na);
6438       switch (*attribute)
6439       {
6440         case 'C':
6441         case 'c':
6442         {
6443           if (LocaleCompare(attribute,"channel") == 0)
6444             {
6445               ssize_t
6446                 option;
6447
6448               option=ParseChannelOption(SvPV(ST(i),na));
6449               if (option < 0)
6450                 {
6451                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6452                     SvPV(ST(i),na));
6453                   return;
6454                 }
6455               SetPixelChannelMask(image,(ChannelType) option);
6456               break;
6457             }
6458           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6459             attribute);
6460           break;
6461         }
6462         case 'g':
6463         case 'G':
6464         {
6465           if (LocaleCompare(attribute,"geometry") == 0)
6466             {
6467               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6468               break;
6469             }
6470           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6471             attribute);
6472           break;
6473         }
6474         case 'N':
6475         case 'n':
6476         {
6477           if (LocaleCompare(attribute,"normalize") == 0)
6478             {
6479               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6480                 SvPV(ST(i),na));
6481               if (option < 0)
6482                 {
6483                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6484                     SvPV(ST(i),na));
6485                   break;
6486                 }
6487              normalize=option != 0 ? MagickTrue : MagickFalse;
6488              break;
6489             }
6490           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6491             attribute);
6492           break;
6493         }
6494         case 'x':
6495         case 'X':
6496         {
6497           if (LocaleCompare(attribute,"x") == 0)
6498             {
6499               region.x=SvIV(ST(i));
6500               break;
6501             }
6502           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6503             attribute);
6504           break;
6505         }
6506         case 'y':
6507         case 'Y':
6508         {
6509           if (LocaleCompare(attribute,"y") == 0)
6510             {
6511               region.y=SvIV(ST(i));
6512               break;
6513             }
6514           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6515             attribute);
6516           break;
6517         }
6518         default:
6519         {
6520           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6521             attribute);
6522           break;
6523         }
6524       }
6525     }
6526     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6527     if (p == (const Quantum *) NULL)
6528       PUSHs(&sv_undef);
6529     else
6530       {
6531         double
6532           scale;
6533
6534         scale=1.0;
6535         if (normalize != MagickFalse)
6536           scale=1.0/QuantumRange;
6537         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6538           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6539         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6540           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6541         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6542           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6543         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6544             (image->colorspace == CMYKColorspace))
6545           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6546         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6547           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6548       }
6549
6550   PerlException:
6551     InheritPerlException(exception,perl_exception);
6552     exception=DestroyExceptionInfo(exception);
6553     SvREFCNT_dec(perl_exception);
6554   }
6555 \f
6556 #
6557 ###############################################################################
6558 #                                                                             #
6559 #                                                                             #
6560 #                                                                             #
6561 #   G e t P i x e l s                                                         #
6562 #                                                                             #
6563 #                                                                             #
6564 #                                                                             #
6565 ###############################################################################
6566 #
6567 #
6568 void
6569 GetPixels(ref,...)
6570   Image::Magick ref=NO_INIT
6571   ALIAS:
6572     getpixels = 1
6573     getPixels = 2
6574   PPCODE:
6575   {
6576     AV
6577       *av;
6578
6579     char
6580       *attribute;
6581
6582     const char
6583       *map;
6584
6585     ExceptionInfo
6586       *exception;
6587
6588     Image
6589       *image;
6590
6591     MagickBooleanType
6592       normalize,
6593       status;
6594
6595     RectangleInfo
6596       region;
6597
6598     register ssize_t
6599       i;
6600
6601     ssize_t
6602       option;
6603
6604     struct PackageInfo
6605       *info;
6606
6607     SV
6608       *perl_exception,
6609       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6610
6611     PERL_UNUSED_VAR(ref);
6612     PERL_UNUSED_VAR(ix);
6613     exception=AcquireExceptionInfo();
6614     perl_exception=newSVpv("",0);
6615     reference=SvRV(ST(0));
6616     av=(AV *) reference;
6617     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6618       exception);
6619     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6620     if (image == (Image *) NULL)
6621       {
6622         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6623           PackageName);
6624         goto PerlException;
6625       }
6626     map="RGB";
6627     if (image->alpha_trait == BlendPixelTrait)
6628       map="RGBA";
6629     if (image->colorspace == CMYKColorspace)
6630       {
6631         map="CMYK";
6632         if (image->alpha_trait == BlendPixelTrait)
6633           map="CMYKA";
6634       }
6635     normalize=MagickFalse;
6636     region.x=0;
6637     region.y=0;
6638     region.width=image->columns;
6639     region.height=1;
6640     if (items == 1)
6641       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6642     for (i=2; i < items; i+=2)
6643     {
6644       attribute=(char *) SvPV(ST(i-1),na);
6645       switch (*attribute)
6646       {
6647         case 'g':
6648         case 'G':
6649         {
6650           if (LocaleCompare(attribute,"geometry") == 0)
6651             {
6652               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6653               break;
6654             }
6655           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6656             attribute);
6657           break;
6658         }
6659         case 'H':
6660         case 'h':
6661         {
6662           if (LocaleCompare(attribute,"height") == 0)
6663             {
6664               region.height=SvIV(ST(i));
6665               break;
6666             }
6667           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6668             attribute);
6669           break;
6670         }
6671         case 'M':
6672         case 'm':
6673         {
6674           if (LocaleCompare(attribute,"map") == 0)
6675             {
6676               map=SvPV(ST(i),na);
6677               break;
6678             }
6679           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6680             attribute);
6681           break;
6682         }
6683         case 'N':
6684         case 'n':
6685         {
6686           if (LocaleCompare(attribute,"normalize") == 0)
6687             {
6688               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6689                 SvPV(ST(i),na));
6690               if (option < 0)
6691                 {
6692                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6693                     SvPV(ST(i),na));
6694                   break;
6695                 }
6696              normalize=option != 0 ? MagickTrue : MagickFalse;
6697              break;
6698             }
6699           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6700             attribute);
6701           break;
6702         }
6703         case 'W':
6704         case 'w':
6705         {
6706           if (LocaleCompare(attribute,"width") == 0)
6707             {
6708               region.width=SvIV(ST(i));
6709               break;
6710             }
6711           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6712             attribute);
6713           break;
6714         }
6715         case 'x':
6716         case 'X':
6717         {
6718           if (LocaleCompare(attribute,"x") == 0)
6719             {
6720               region.x=SvIV(ST(i));
6721               break;
6722             }
6723           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6724             attribute);
6725           break;
6726         }
6727         case 'y':
6728         case 'Y':
6729         {
6730           if (LocaleCompare(attribute,"y") == 0)
6731             {
6732               region.y=SvIV(ST(i));
6733               break;
6734             }
6735           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6736             attribute);
6737           break;
6738         }
6739         default:
6740         {
6741           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6742             attribute);
6743           break;
6744         }
6745       }
6746     }
6747     if (normalize != MagickFalse)
6748       {
6749         float
6750           *pixels;
6751
6752         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6753           region.height*sizeof(*pixels));
6754         if (pixels == (float *) NULL)
6755           {
6756             ThrowPerlException(exception,ResourceLimitError,
6757               "MemoryAllocationFailed",PackageName);
6758             goto PerlException;
6759           }
6760         status=ExportImagePixels(image,region.x,region.y,region.width,
6761           region.height,map,FloatPixel,pixels,exception);
6762         if (status == MagickFalse)
6763           PUSHs(&sv_undef);
6764         else
6765           {
6766             EXTEND(sp,strlen(map)*region.width*region.height);
6767             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6768               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6769           }
6770         pixels=(float *) RelinquishMagickMemory(pixels);
6771       }
6772     else
6773       {
6774         Quantum
6775           *pixels;
6776
6777         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6778           region.height*sizeof(*pixels));
6779         if (pixels == (Quantum *) NULL)
6780           {
6781             ThrowPerlException(exception,ResourceLimitError,
6782               "MemoryAllocationFailed",PackageName);
6783             goto PerlException;
6784           }
6785         status=ExportImagePixels(image,region.x,region.y,region.width,
6786           region.height,map,QuantumPixel,pixels,exception);
6787         if (status == MagickFalse)
6788           PUSHs(&sv_undef);
6789         else
6790           {
6791             EXTEND(sp,strlen(map)*region.width*region.height);
6792             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6793               PUSHs(sv_2mortal(newSViv(pixels[i])));
6794           }
6795         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6796       }
6797
6798   PerlException:
6799     InheritPerlException(exception,perl_exception);
6800     exception=DestroyExceptionInfo(exception);
6801     SvREFCNT_dec(perl_exception);
6802   }
6803 \f
6804 #
6805 ###############################################################################
6806 #                                                                             #
6807 #                                                                             #
6808 #                                                                             #
6809 #   I m a g e T o B l o b                                                     #
6810 #                                                                             #
6811 #                                                                             #
6812 #                                                                             #
6813 ###############################################################################
6814 #
6815 #
6816 void
6817 ImageToBlob(ref,...)
6818   Image::Magick ref=NO_INIT
6819   ALIAS:
6820     ImageToBlob  = 1
6821     imagetoblob  = 2
6822     toblob       = 3
6823     blob         = 4
6824   PPCODE:
6825   {
6826     char
6827       filename[MaxTextExtent];
6828
6829     ExceptionInfo
6830       *exception;
6831
6832     Image
6833       *image,
6834       *next;
6835
6836     register ssize_t
6837       i;
6838
6839     struct PackageInfo
6840       *info,
6841       *package_info;
6842
6843     size_t
6844       length;
6845
6846     ssize_t
6847       scene;
6848
6849     SV
6850       *perl_exception,
6851       *reference;
6852
6853     void
6854       *blob;
6855
6856     PERL_UNUSED_VAR(ref);
6857     PERL_UNUSED_VAR(ix);
6858     exception=AcquireExceptionInfo();
6859     perl_exception=newSVpv("",0);
6860     package_info=(struct PackageInfo *) NULL;
6861     if (sv_isobject(ST(0)) == 0)
6862       {
6863         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6864           PackageName);
6865         goto PerlException;
6866       }
6867     reference=SvRV(ST(0));
6868     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6869     if (image == (Image *) NULL)
6870       {
6871         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6872           PackageName);
6873         goto PerlException;
6874       }
6875     package_info=ClonePackageInfo(info,exception);
6876     for (i=2; i < items; i+=2)
6877       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6878     (void) CopyMagickString(filename,package_info->image_info->filename,
6879       MaxTextExtent);
6880     scene=0;
6881     for (next=image; next; next=next->next)
6882     {
6883       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6884       next->scene=scene++;
6885     }
6886     SetImageInfo(package_info->image_info,(unsigned int)
6887       GetImageListLength(image),exception);
6888     EXTEND(sp,(ssize_t) GetImageListLength(image));
6889     for ( ; image; image=image->next)
6890     {
6891       length=0;
6892       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6893       if (blob != (char *) NULL)
6894         {
6895           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6896           blob=(unsigned char *) RelinquishMagickMemory(blob);
6897         }
6898       if (package_info->image_info->adjoin)
6899         break;
6900     }
6901
6902   PerlException:
6903     if (package_info != (struct PackageInfo *) NULL)
6904       DestroyPackageInfo(package_info);
6905     InheritPerlException(exception,perl_exception);
6906     exception=DestroyExceptionInfo(exception);
6907     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6908   }
6909 \f
6910 #
6911 ###############################################################################
6912 #                                                                             #
6913 #                                                                             #
6914 #                                                                             #
6915 #   L a y e r s                                                               #
6916 #                                                                             #
6917 #                                                                             #
6918 #                                                                             #
6919 ###############################################################################
6920 #
6921 #
6922 void
6923 Layers(ref,...)
6924   Image::Magick ref=NO_INIT
6925   ALIAS:
6926     Layers                = 1
6927     layers           = 2
6928     OptimizeImageLayers   = 3
6929     optimizelayers        = 4
6930     optimizeimagelayers   = 5
6931   PPCODE:
6932   {
6933     AV
6934       *av;
6935
6936     char
6937       *attribute;
6938
6939     CompositeOperator
6940       compose;
6941
6942     ExceptionInfo
6943       *exception;
6944
6945     HV
6946       *hv;
6947
6948     Image
6949       *image,
6950       *layers;
6951
6952     LayerMethod
6953       method;
6954
6955     register ssize_t
6956       i;
6957
6958     ssize_t
6959       option,
6960       sp;
6961
6962     struct PackageInfo
6963       *info;
6964
6965     SV
6966       *av_reference,
6967       *perl_exception,
6968       *reference,
6969       *rv,
6970       *sv;
6971
6972     PERL_UNUSED_VAR(ref);
6973     PERL_UNUSED_VAR(ix);
6974     exception=AcquireExceptionInfo();
6975     perl_exception=newSVpv("",0);
6976     sv=NULL;
6977     if (sv_isobject(ST(0)) == 0)
6978       {
6979         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6980           PackageName);
6981         goto PerlException;
6982       }
6983     reference=SvRV(ST(0));
6984     hv=SvSTASH(reference);
6985     av=newAV();
6986     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6987     SvREFCNT_dec(av);
6988     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6989     if (image == (Image *) NULL)
6990       {
6991         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6992           PackageName);
6993         goto PerlException;
6994       }
6995     compose=image->compose;
6996     method=OptimizeLayer;
6997     for (i=2; i < items; i+=2)
6998     {
6999       attribute=(char *) SvPV(ST(i-1),na);
7000       switch (*attribute)
7001       {
7002         case 'C':
7003         case 'c':
7004         {
7005           if (LocaleCompare(attribute,"compose") == 0)
7006             {
7007               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7008                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7009               if (sp < 0)
7010                 {
7011                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7012                     SvPV(ST(i),na));
7013                   break;
7014                 }
7015               compose=(CompositeOperator) sp;
7016               break;
7017             }
7018           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7019             attribute);
7020           break;
7021         }
7022         case 'M':
7023         case 'm':
7024         {
7025           if (LocaleCompare(attribute,"method") == 0)
7026             {
7027               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7028                 SvPV(ST(i),na));
7029               if (option < 0)
7030                 {
7031                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7032                     SvPV(ST(i),na));
7033                   break;
7034                 }
7035               method=(LayerMethod) option;
7036               break;
7037             }
7038           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7039             attribute);
7040           break;
7041         }
7042         default:
7043         {
7044           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7045             attribute);
7046           break;
7047         }
7048       }
7049     }
7050     layers=(Image *) NULL;
7051     switch (method)
7052     {
7053       case CompareAnyLayer:
7054       case CompareClearLayer:
7055       case CompareOverlayLayer:
7056       default:
7057       {
7058         layers=CompareImagesLayers(image,method,exception);
7059         break;
7060       }
7061       case MergeLayer:
7062       case FlattenLayer:
7063       case MosaicLayer:
7064       {
7065         layers=MergeImageLayers(image,method,exception);
7066         break;
7067       }
7068       case DisposeLayer:
7069       {
7070         layers=DisposeImages(image,exception);
7071         break;
7072       }
7073       case OptimizeImageLayer:
7074       {
7075         layers=OptimizeImageLayers(image,exception);
7076         break;
7077       }
7078       case OptimizePlusLayer:
7079       {
7080         layers=OptimizePlusImageLayers(image,exception);
7081         break;
7082       }
7083       case OptimizeTransLayer:
7084       {
7085         OptimizeImageTransparency(image,exception);
7086         break;
7087       }
7088       case RemoveDupsLayer:
7089       {
7090         RemoveDuplicateLayers(&image,exception);
7091         break;
7092       }
7093       case RemoveZeroLayer:
7094       {
7095         RemoveZeroDelayLayers(&image,exception);
7096         break;
7097       }
7098       case OptimizeLayer:
7099       {
7100         QuantizeInfo
7101           *quantize_info;
7102
7103         /*
7104           General Purpose, GIF Animation Optimizer.
7105         */
7106         layers=CoalesceImages(image,exception);
7107         if (layers == (Image *) NULL)
7108           break;
7109         image=layers;
7110         layers=OptimizeImageLayers(image,exception);
7111         if (layers == (Image *) NULL)
7112           break;
7113         image=DestroyImageList(image);
7114         image=layers;
7115         layers=(Image *) NULL;
7116         OptimizeImageTransparency(image,exception);
7117         quantize_info=AcquireQuantizeInfo(info->image_info);
7118         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7119         quantize_info=DestroyQuantizeInfo(quantize_info);
7120         break;
7121       }
7122       case CompositeLayer:
7123       {
7124         Image
7125           *source;
7126
7127         RectangleInfo
7128           geometry;
7129
7130         /*
7131           Split image sequence at the first 'NULL:' image.
7132         */
7133         source=image;
7134         while (source != (Image *) NULL)
7135         {
7136           source=GetNextImageInList(source);
7137           if ((source != (Image *) NULL) &&
7138               (LocaleCompare(source->magick,"NULL") == 0))
7139             break;
7140         }
7141         if (source != (Image *) NULL)
7142           {
7143             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7144                 (GetNextImageInList(source) == (Image *) NULL))
7145               source=(Image *) NULL;
7146             else
7147               {
7148                 /*
7149                   Separate the two lists, junk the null: image.
7150                 */
7151                 source=SplitImageList(source->previous);
7152                 DeleteImageFromList(&source);
7153               }
7154           }
7155         if (source == (Image *) NULL)
7156           {
7157             (void) ThrowMagickException(exception,GetMagickModule(),
7158               OptionError,"MissingNullSeparator","layers Composite");
7159             break;
7160           }
7161         /*
7162           Adjust offset with gravity and virtual canvas.
7163         */
7164         SetGeometry(image,&geometry);
7165         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7166         geometry.width=source->page.width != 0 ? source->page.width :
7167           source->columns;
7168         geometry.height=source->page.height != 0 ? source->page.height :
7169           source->rows;
7170         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7171           image->columns,image->page.height != 0 ? image->page.height :
7172           image->rows,image->gravity,&geometry);
7173         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7174         source=DestroyImageList(source);
7175         break;
7176       }
7177     }
7178     if (layers != (Image *) NULL)
7179       image=layers;
7180     else
7181       image=CloneImage(image,0,0,MagickTrue,exception);
7182     if (image == (Image *) NULL)
7183       goto PerlException;
7184     for ( ; image; image=image->next)
7185     {
7186       AddImageToRegistry(sv,image);
7187       rv=newRV(sv);
7188       av_push(av,sv_bless(rv,hv));
7189       SvREFCNT_dec(sv);
7190     }
7191     exception=DestroyExceptionInfo(exception);
7192     ST(0)=av_reference;
7193     SvREFCNT_dec(perl_exception);
7194     XSRETURN(1);
7195
7196   PerlException:
7197     InheritPerlException(exception,perl_exception);
7198     exception=DestroyExceptionInfo(exception);
7199     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7200     SvPOK_on(perl_exception);
7201     ST(0)=sv_2mortal(perl_exception);
7202     XSRETURN(1);
7203   }
7204 \f
7205 #
7206 ###############################################################################
7207 #                                                                             #
7208 #                                                                             #
7209 #                                                                             #
7210 #   M a g i c k T o M i m e                                                   #
7211 #                                                                             #
7212 #                                                                             #
7213 #                                                                             #
7214 ###############################################################################
7215 #
7216 #
7217 SV *
7218 MagickToMime(ref,name)
7219   Image::Magick ref=NO_INIT
7220   char *name
7221   ALIAS:
7222     magicktomime = 1
7223   CODE:
7224   {
7225     char
7226       *mime;
7227
7228     PERL_UNUSED_VAR(ref);
7229     PERL_UNUSED_VAR(ix);
7230     mime=MagickToMime(name);
7231     RETVAL=newSVpv(mime,0);
7232     mime=(char *) RelinquishMagickMemory(mime);
7233   }
7234   OUTPUT:
7235     RETVAL
7236 \f
7237 #
7238 ###############################################################################
7239 #                                                                             #
7240 #                                                                             #
7241 #                                                                             #
7242 #   M o g r i f y                                                             #
7243 #                                                                             #
7244 #                                                                             #
7245 #                                                                             #
7246 ###############################################################################
7247 #
7248 #
7249 void
7250 Mogrify(ref,...)
7251   Image::Magick ref=NO_INIT
7252   ALIAS:
7253     Comment            =   1
7254     CommentImage       =   2
7255     Label              =   3
7256     LabelImage         =   4
7257     AddNoise           =   5
7258     AddNoiseImage      =   6
7259     Colorize           =   7
7260     ColorizeImage      =   8
7261     Border             =   9
7262     BorderImage        =  10
7263     Blur               =  11
7264     BlurImage          =  12
7265     Chop               =  13
7266     ChopImage          =  14
7267     Crop               =  15
7268     CropImage          =  16
7269     Despeckle          =  17
7270     DespeckleImage     =  18
7271     Edge               =  19
7272     EdgeImage          =  20
7273     Emboss             =  21
7274     EmbossImage        =  22
7275     Enhance            =  23
7276     EnhanceImage       =  24
7277     Flip               =  25
7278     FlipImage          =  26
7279     Flop               =  27
7280     FlopImage          =  28
7281     Frame              =  29
7282     FrameImage         =  30
7283     Implode            =  31
7284     ImplodeImage       =  32
7285     Magnify            =  33
7286     MagnifyImage       =  34
7287     MedianFilter       =  35
7288     MedianConvolveImage  =  36
7289     Minify             =  37
7290     MinifyImage        =  38
7291     OilPaint           =  39
7292     OilPaintImage      =  40
7293     ReduceNoise        =  41
7294     ReduceNoiseImage   =  42
7295     Roll               =  43
7296     RollImage          =  44
7297     Rotate             =  45
7298     RotateImage        =  46
7299     Sample             =  47
7300     SampleImage        =  48
7301     Scale              =  49
7302     ScaleImage         =  50
7303     Shade              =  51
7304     ShadeImage         =  52
7305     Sharpen            =  53
7306     SharpenImage       =  54
7307     Shear              =  55
7308     ShearImage         =  56
7309     Spread             =  57
7310     SpreadImage        =  58
7311     Swirl              =  59
7312     SwirlImage         =  60
7313     Resize             =  61
7314     ResizeImage        =  62
7315     Zoom               =  63
7316     ZoomImage          =  64
7317     Annotate           =  65
7318     AnnotateImage      =  66
7319     ColorFloodfill     =  67
7320     ColorFloodfillImage=  68
7321     Composite          =  69
7322     CompositeImage     =  70
7323     Contrast           =  71
7324     ContrastImage      =  72
7325     CycleColormap      =  73
7326     CycleColormapImage =  74
7327     Draw               =  75
7328     DrawImage          =  76
7329     Equalize           =  77
7330     EqualizeImage      =  78
7331     Gamma              =  79
7332     GammaImage         =  80
7333     Map                =  81
7334     MapImage           =  82
7335     MatteFloodfill     =  83
7336     MatteFloodfillImage=  84
7337     Modulate           =  85
7338     ModulateImage      =  86
7339     Negate             =  87
7340     NegateImage        =  88
7341     Normalize          =  89
7342     NormalizeImage     =  90
7343     NumberColors       =  91
7344     NumberColorsImage  =  92
7345     Opaque             =  93
7346     OpaqueImage        =  94
7347     Quantize           =  95
7348     QuantizeImage      =  96
7349     Raise              =  97
7350     RaiseImage         =  98
7351     Segment            =  99
7352     SegmentImage       = 100
7353     Signature          = 101
7354     SignatureImage     = 102
7355     Solarize           = 103
7356     SolarizeImage      = 104
7357     Sync               = 105
7358     SyncImage          = 106
7359     Texture            = 107
7360     TextureImage       = 108
7361     Evaluate           = 109
7362     EvaluateImage      = 110
7363     Transparent        = 111
7364     TransparentImage   = 112
7365     Threshold          = 113
7366     ThresholdImage     = 114
7367     Charcoal           = 115
7368     CharcoalImage      = 116
7369     Trim               = 117
7370     TrimImage          = 118
7371     Wave               = 119
7372     WaveImage          = 120
7373     Separate           = 121
7374     SeparateImage      = 122
7375     Stereo             = 125
7376     StereoImage        = 126
7377     Stegano            = 127
7378     SteganoImage       = 128
7379     Deconstruct        = 129
7380     DeconstructImage   = 130
7381     GaussianBlur       = 131
7382     GaussianBlurImage  = 132
7383     Convolve           = 133
7384     ConvolveImage      = 134
7385     Profile            = 135
7386     ProfileImage       = 136
7387     UnsharpMask        = 137
7388     UnsharpMaskImage   = 138
7389     MotionBlur         = 139
7390     MotionBlurImage    = 140
7391     OrderedDither      = 141
7392     OrderedDitherImage = 142
7393     Shave              = 143
7394     ShaveImage         = 144
7395     Level              = 145
7396     LevelImage         = 146
7397     Clip               = 147
7398     ClipImage          = 148
7399     AffineTransform    = 149
7400     AffineTransformImage = 150
7401     Difference         = 151
7402     DifferenceImage    = 152
7403     AdaptiveThreshold  = 153
7404     AdaptiveThresholdImage = 154
7405     Resample           = 155
7406     ResampleImage      = 156
7407     Describe           = 157
7408     DescribeImage      = 158
7409     BlackThreshold     = 159
7410     BlackThresholdImage= 160
7411     WhiteThreshold     = 161
7412     WhiteThresholdImage= 162
7413     RadialBlur         = 163
7414     RadialBlurImage    = 164
7415     Thumbnail          = 165
7416     ThumbnailImage     = 166
7417     Strip              = 167
7418     StripImage         = 168
7419     Tint               = 169
7420     TintImage          = 170
7421     Channel            = 171
7422     ChannelImage       = 172
7423     Splice             = 173
7424     SpliceImage        = 174
7425     Posterize          = 175
7426     PosterizeImage     = 176
7427     Shadow             = 177
7428     ShadowImage        = 178
7429     Identify           = 179
7430     IdentifyImage      = 180
7431     SepiaTone          = 181
7432     SepiaToneImage     = 182
7433     SigmoidalContrast  = 183
7434     SigmoidalContrastImage = 184
7435     Extent             = 185
7436     ExtentImage        = 186
7437     Vignette           = 187
7438     VignetteImage      = 188
7439     ContrastStretch    = 189
7440     ContrastStretchImage = 190
7441     Sans0              = 191
7442     Sans0Image         = 192
7443     Sans1              = 193
7444     Sans1Image         = 194
7445     AdaptiveSharpen    = 195
7446     AdaptiveSharpenImage = 196
7447     Transpose          = 197
7448     TransposeImage     = 198
7449     Transverse         = 199
7450     TransverseImage    = 200
7451     AutoOrient         = 201
7452     AutoOrientImage    = 202
7453     AdaptiveBlur       = 203
7454     AdaptiveBlurImage  = 204
7455     Sketch             = 205
7456     SketchImage        = 206
7457     UniqueColors       = 207
7458     UniqueColorsImage  = 208
7459     AdaptiveResize     = 209
7460     AdaptiveResizeImage= 210
7461     ClipMask           = 211
7462     ClipMaskImage      = 212
7463     LinearStretch      = 213
7464     LinearStretchImage = 214
7465     ColorMatrix        = 215
7466     ColorMatrixImage   = 216
7467     Mask               = 217
7468     MaskImage          = 218
7469     Polaroid           = 219
7470     PolaroidImage      = 220
7471     FloodfillPaint     = 221
7472     FloodfillPaintImage= 222
7473     Distort            = 223
7474     DistortImage       = 224
7475     Clut               = 225
7476     ClutImage          = 226
7477     LiquidRescale      = 227
7478     LiquidRescaleImage = 228
7479     Encipher           = 229
7480     EncipherImage      = 230
7481     Decipher           = 231
7482     DecipherImage      = 232
7483     Deskew             = 233
7484     DeskewImage        = 234
7485     Remap              = 235
7486     RemapImage         = 236
7487     SparseColor        = 237
7488     SparseColorImage   = 238
7489     Function           = 239
7490     FunctionImage      = 240
7491     SelectiveBlur      = 241
7492     SelectiveBlurImage = 242
7493     HaldClut           = 243
7494     HaldClutImage      = 244
7495     BlueShift          = 245
7496     BlueShiftImage     = 246
7497     ForwardFourierTransform  = 247
7498     ForwardFourierTransformImage = 248
7499     InverseFourierTransform = 249
7500     InverseFourierTransformImage = 250
7501     ColorDecisionList  = 251
7502     ColorDecisionListImage = 252
7503     AutoGamma          = 253
7504     AutoGammaImage     = 254
7505     AutoLevel          = 255
7506     AutoLevelImage     = 256
7507     LevelColors        = 257
7508     LevelImageColors   = 258
7509     Clamp              = 259
7510     ClampImage         = 260
7511     BrightnessContrast = 261
7512     BrightnessContrastImage = 262
7513     Morphology         = 263
7514     MorphologyImage    = 264
7515     Color              = 265
7516     ColorImage         = 266
7517     Mode               = 267
7518     ModeImage          = 268
7519     Statistic          = 269
7520     StatisticImage     = 270
7521     Perceptible        = 271
7522     PerceptibleImage   = 272
7523     Poly               = 273
7524     PolyImage          = 274
7525     Grayscale          = 275
7526     GrayscaleImage     = 276
7527     MogrifyRegion      = 666
7528   PPCODE:
7529   {
7530     AffineMatrix
7531       affine,
7532       current;
7533
7534     char
7535       attribute_flag[MaxArguments],
7536       message[MaxTextExtent];
7537
7538     ChannelType
7539       channel,
7540       channel_mask;
7541
7542     CompositeOperator
7543       compose;
7544
7545     const char
7546       *attribute,
7547       *value;
7548
7549     double
7550       angle;
7551
7552     ExceptionInfo
7553       *exception;
7554
7555     GeometryInfo
7556       geometry_info;
7557
7558     Image
7559       *image,
7560       *next,
7561       *region_image;
7562
7563     MagickBooleanType
7564       status;
7565
7566     MagickStatusType
7567       flags;
7568
7569     PixelInfo
7570       fill_color;
7571
7572     RectangleInfo
7573       geometry,
7574       region_info;
7575
7576     register ssize_t
7577       i;
7578
7579     ssize_t
7580       base,
7581       j,
7582       number_images;
7583
7584     struct Methods
7585       *rp;
7586
7587     struct PackageInfo
7588       *info;
7589
7590     SV
7591       *perl_exception,
7592       **pv,
7593       *reference,
7594       **reference_vector;
7595
7596     struct ArgumentList
7597       argument_list[MaxArguments];
7598
7599     PERL_UNUSED_VAR(ref);
7600     PERL_UNUSED_VAR(ix);
7601     exception=AcquireExceptionInfo();
7602     perl_exception=newSVpv("",0);
7603     reference_vector=NULL;
7604     region_image=NULL;
7605     number_images=0;
7606     base=2;
7607     if (sv_isobject(ST(0)) == 0)
7608       {
7609         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7610           PackageName);
7611         goto PerlException;
7612       }
7613     reference=SvRV(ST(0));
7614     region_info.width=0;
7615     region_info.height=0;
7616     region_info.x=0;
7617     region_info.y=0;
7618     region_image=(Image *) NULL;
7619     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7620     if (ix && (ix != 666))
7621       {
7622         /*
7623           Called as Method(...)
7624         */
7625         ix=(ix+1)/2;
7626         rp=(&Methods[ix-1]);
7627         attribute=rp->name;
7628       }
7629     else
7630       {
7631         /*
7632           Called as Mogrify("Method",...)
7633         */
7634         attribute=(char *) SvPV(ST(1),na);
7635         if (ix)
7636           {
7637             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7638             attribute=(char *) SvPV(ST(2),na);
7639             base++;
7640           }
7641         for (rp=Methods; ; rp++)
7642         {
7643           if (rp >= EndOf(Methods))
7644             {
7645               ThrowPerlException(exception,OptionError,
7646                 "UnrecognizedPerlMagickMethod",attribute);
7647               goto PerlException;
7648             }
7649           if (strEQcase(attribute,rp->name))
7650             break;
7651         }
7652         ix=rp-Methods+1;
7653         base++;
7654       }
7655     if (image == (Image *) NULL)
7656       {
7657         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7658         goto PerlException;
7659       }
7660     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7661     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7662     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7663     {
7664       Arguments
7665         *pp,
7666         *qq;
7667
7668       ssize_t
7669         ssize_test;
7670
7671       struct ArgumentList
7672         *al;
7673
7674       SV
7675         *sv;
7676
7677       sv=NULL;
7678       ssize_test=0;
7679       pp=(Arguments *) NULL;
7680       qq=rp->arguments;
7681       if (i == items)
7682         {
7683           pp=rp->arguments,
7684           sv=ST(i-1);
7685         }
7686       else
7687         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7688         {
7689           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7690             break;
7691           if (strEQcase(attribute,qq->method) > ssize_test)
7692             {
7693               pp=qq;
7694               ssize_test=strEQcase(attribute,qq->method);
7695             }
7696         }
7697       if (pp == (Arguments *) NULL)
7698         {
7699           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7700             attribute);
7701           goto continue_outer_loop;
7702         }
7703       al=(&argument_list[pp-rp->arguments]);
7704       switch (pp->type)
7705       {
7706         case ArrayReference:
7707         {
7708           if (SvTYPE(sv) != SVt_RV)
7709             {
7710               (void) FormatLocaleString(message,MaxTextExtent,
7711                 "invalid %.60s value",pp->method);
7712               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7713               goto continue_outer_loop;
7714             }
7715           al->array_reference=SvRV(sv);
7716           break;
7717         }
7718         case RealReference:
7719         {
7720           al->real_reference=SvNV(sv);
7721           break;
7722         }
7723         case FileReference:
7724         {
7725           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7726           break;
7727         }
7728         case ImageReference:
7729         {
7730           if (!sv_isobject(sv) ||
7731               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7732                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7733             {
7734               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7735                 PackageName);
7736               goto PerlException;
7737             }
7738           break;
7739         }
7740         case IntegerReference:
7741         {
7742           al->integer_reference=SvIV(sv);
7743           break;
7744         }
7745         case StringReference:
7746         {
7747           al->string_reference=(char *) SvPV(sv,al->length);
7748           if (sv_isobject(sv))
7749             al->image_reference=SetupList(aTHX_ SvRV(sv),
7750               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7751           break;
7752         }
7753         default:
7754         {
7755           /*
7756             Is a string; look up name.
7757           */
7758           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7759             {
7760               al->string_reference=(char *) SvPV(sv,al->length);
7761               al->integer_reference=(-1);
7762               break;
7763             }
7764           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7765             MagickFalse,SvPV(sv,na));
7766           if (pp->type == MagickChannelOptions)
7767             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7768           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7769             {
7770               (void) FormatLocaleString(message,MaxTextExtent,
7771                 "invalid %.60s value",pp->method);
7772               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7773               goto continue_outer_loop;
7774             }
7775           break;
7776         }
7777       }
7778       attribute_flag[pp-rp->arguments]++;
7779       continue_outer_loop: ;
7780     }
7781     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7782     pv=reference_vector;
7783     SetGeometryInfo(&geometry_info);
7784     channel=DefaultChannels;
7785     for (next=image; next; next=next->next)
7786     {
7787       image=next;
7788       SetGeometry(image,&geometry);
7789       if ((region_info.width*region_info.height) != 0)
7790         {
7791           region_image=image;
7792           image=CropImage(image,&region_info,exception);
7793         }
7794       switch (ix)
7795       {
7796         default:
7797         {
7798           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7799           ThrowPerlException(exception,OptionError,
7800             "UnrecognizedPerlMagickMethod",message);
7801           goto PerlException;
7802         }
7803         case 1:  /* Comment */
7804         {
7805           if (attribute_flag[0] == 0)
7806             argument_list[0].string_reference=(char *) NULL;
7807           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7808             info ? info->image_info : (ImageInfo *) NULL,image,
7809             argument_list[0].string_reference,exception),exception);
7810           break;
7811         }
7812         case 2:  /* Label */
7813         {
7814           if (attribute_flag[0] == 0)
7815             argument_list[0].string_reference=(char *) NULL;
7816           (void) SetImageProperty(image,"label",InterpretImageProperties(
7817             info ? info->image_info : (ImageInfo *) NULL,image,
7818             argument_list[0].string_reference,exception),exception);
7819           break;
7820         }
7821         case 3:  /* AddNoise */
7822         {
7823           double
7824             attenuate;
7825
7826           if (attribute_flag[0] == 0)
7827             argument_list[0].integer_reference=UniformNoise;
7828           attenuate=1.0;
7829           if (attribute_flag[1] != 0)
7830             attenuate=argument_list[1].real_reference;
7831           if (attribute_flag[2] != 0)
7832             channel=(ChannelType) argument_list[2].integer_reference;
7833           channel_mask=SetImageChannelMask(image,channel);
7834           image=AddNoiseImage(image,(NoiseType)
7835             argument_list[0].integer_reference,attenuate,exception);
7836           if (image != (Image *) NULL)
7837             (void) SetImageChannelMask(image,channel_mask);
7838           break;
7839         }
7840         case 4:  /* Colorize */
7841         {
7842           PixelInfo
7843             target;
7844
7845           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7846             0,0,&target,exception);
7847           if (attribute_flag[0] != 0)
7848             (void) QueryColorCompliance(argument_list[0].string_reference,
7849               AllCompliance,&target,exception);
7850           if (attribute_flag[1] == 0)
7851             argument_list[1].string_reference="100%";
7852           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7853             exception);
7854           break;
7855         }
7856         case 5:  /* Border */
7857         {
7858           CompositeOperator
7859             compose;
7860
7861           geometry.width=0;
7862           geometry.height=0;
7863           if (attribute_flag[0] != 0)
7864             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7865               &geometry,exception);
7866           if (attribute_flag[1] != 0)
7867             geometry.width=argument_list[1].integer_reference;
7868           if (attribute_flag[2] != 0)
7869             geometry.height=argument_list[2].integer_reference;
7870           if (attribute_flag[3] != 0)
7871             QueryColorCompliance(argument_list[3].string_reference,
7872               AllCompliance,&image->border_color,exception);
7873           if (attribute_flag[4] != 0)
7874             QueryColorCompliance(argument_list[4].string_reference,
7875               AllCompliance,&image->border_color,exception);
7876           if (attribute_flag[5] != 0)
7877             QueryColorCompliance(argument_list[5].string_reference,
7878               AllCompliance,&image->border_color,exception);
7879           compose=image->compose;
7880           if (attribute_flag[6] != 0)
7881             compose=(CompositeOperator) argument_list[6].integer_reference;
7882           image=BorderImage(image,&geometry,compose,exception);
7883           break;
7884         }
7885         case 6:  /* Blur */
7886         {
7887           if (attribute_flag[0] != 0)
7888             {
7889               flags=ParseGeometry(argument_list[0].string_reference,
7890                 &geometry_info);
7891               if ((flags & SigmaValue) == 0)
7892                 geometry_info.sigma=1.0;
7893             }
7894           if (attribute_flag[1] != 0)
7895             geometry_info.rho=argument_list[1].real_reference;
7896           if (attribute_flag[2] != 0)
7897             geometry_info.sigma=argument_list[2].real_reference;
7898           if (attribute_flag[3] != 0)
7899             channel=(ChannelType) argument_list[3].integer_reference;
7900           channel_mask=SetImageChannelMask(image,channel);
7901           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7902             exception);
7903           if (image != (Image *) NULL)
7904             (void) SetImageChannelMask(image,channel_mask);
7905           break;
7906         }
7907         case 7:  /* Chop */
7908         {
7909           if (attribute_flag[0] != 0)
7910             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7911               &geometry,exception);
7912           if (attribute_flag[1] != 0)
7913             geometry.width=argument_list[1].integer_reference;
7914           if (attribute_flag[2] != 0)
7915             geometry.height=argument_list[2].integer_reference;
7916           if (attribute_flag[3] != 0)
7917             geometry.x=argument_list[3].integer_reference;
7918           if (attribute_flag[4] != 0)
7919             geometry.y=argument_list[4].integer_reference;
7920           image=ChopImage(image,&geometry,exception);
7921           break;
7922         }
7923         case 8:  /* Crop */
7924         {
7925           if (attribute_flag[6] != 0)
7926             image->gravity=(GravityType) argument_list[6].integer_reference;
7927           if (attribute_flag[0] != 0)
7928             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7929               &geometry,exception);
7930           if (attribute_flag[1] != 0)
7931             geometry.width=argument_list[1].integer_reference;
7932           if (attribute_flag[2] != 0)
7933             geometry.height=argument_list[2].integer_reference;
7934           if (attribute_flag[3] != 0)
7935             geometry.x=argument_list[3].integer_reference;
7936           if (attribute_flag[4] != 0)
7937             geometry.y=argument_list[4].integer_reference;
7938           if (attribute_flag[5] != 0)
7939             image->fuzz=StringToDoubleInterval(
7940               argument_list[5].string_reference,(double) QuantumRange+1.0);
7941           image=CropImage(image,&geometry,exception);
7942           break;
7943         }
7944         case 9:  /* Despeckle */
7945         {
7946           image=DespeckleImage(image,exception);
7947           break;
7948         }
7949         case 10:  /* Edge */
7950         {
7951           if (attribute_flag[0] != 0)
7952             geometry_info.rho=argument_list[0].real_reference;
7953           image=EdgeImage(image,geometry_info.rho,exception);
7954           break;
7955         }
7956         case 11:  /* Emboss */
7957         {
7958           if (attribute_flag[0] != 0)
7959             {
7960               flags=ParseGeometry(argument_list[0].string_reference,
7961                 &geometry_info);
7962               if ((flags & SigmaValue) == 0)
7963                 geometry_info.sigma=1.0;
7964             }
7965           if (attribute_flag[1] != 0)
7966             geometry_info.rho=argument_list[1].real_reference;
7967           if (attribute_flag[2] != 0)
7968             geometry_info.sigma=argument_list[2].real_reference;
7969           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7970             exception);
7971           break;
7972         }
7973         case 12:  /* Enhance */
7974         {
7975           image=EnhanceImage(image,exception);
7976           break;
7977         }
7978         case 13:  /* Flip */
7979         {
7980           image=FlipImage(image,exception);
7981           break;
7982         }
7983         case 14:  /* Flop */
7984         {
7985           image=FlopImage(image,exception);
7986           break;
7987         }
7988         case 15:  /* Frame */
7989         {
7990           CompositeOperator
7991             compose;
7992
7993           FrameInfo
7994             frame_info;
7995
7996           if (attribute_flag[0] != 0)
7997             {
7998               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7999                 &geometry,exception);
8000               frame_info.width=geometry.width;
8001               frame_info.height=geometry.height;
8002               frame_info.outer_bevel=geometry.x;
8003               frame_info.inner_bevel=geometry.y;
8004             }
8005           if (attribute_flag[1] != 0)
8006             frame_info.width=argument_list[1].integer_reference;
8007           if (attribute_flag[2] != 0)
8008             frame_info.height=argument_list[2].integer_reference;
8009           if (attribute_flag[3] != 0)
8010             frame_info.inner_bevel=argument_list[3].integer_reference;
8011           if (attribute_flag[4] != 0)
8012             frame_info.outer_bevel=argument_list[4].integer_reference;
8013           if (attribute_flag[5] != 0)
8014             QueryColorCompliance(argument_list[5].string_reference,
8015               AllCompliance,&fill_color,exception);
8016           if (attribute_flag[6] != 0)
8017             QueryColorCompliance(argument_list[6].string_reference,
8018               AllCompliance,&fill_color,exception);
8019           frame_info.x=(ssize_t) frame_info.width;
8020           frame_info.y=(ssize_t) frame_info.height;
8021           frame_info.width=image->columns+2*frame_info.x;
8022           frame_info.height=image->rows+2*frame_info.y;
8023           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8024             image->matte_color=fill_color;
8025           compose=image->compose;
8026           if (attribute_flag[7] != 0)
8027             compose=(CompositeOperator) argument_list[7].integer_reference;
8028           image=FrameImage(image,&frame_info,compose,exception);
8029           break;
8030         }
8031         case 16:  /* Implode */
8032         {
8033           PixelInterpolateMethod
8034             method;
8035
8036           if (attribute_flag[0] == 0)
8037             argument_list[0].real_reference=0.5;
8038           method=UndefinedInterpolatePixel;
8039           if (attribute_flag[1] != 0)
8040             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8041           image=ImplodeImage(image,argument_list[0].real_reference,
8042             method,exception);
8043           break;
8044         }
8045         case 17:  /* Magnify */
8046         {
8047           image=MagnifyImage(image,exception);
8048           break;
8049         }
8050         case 18:  /* MedianFilter */
8051         {
8052           if (attribute_flag[0] != 0)
8053             {
8054               flags=ParseGeometry(argument_list[0].string_reference,
8055                 &geometry_info);
8056               if ((flags & SigmaValue) == 0)
8057                 geometry_info.sigma=geometry_info.rho;
8058             }
8059           if (attribute_flag[1] != 0)
8060             geometry_info.rho=argument_list[1].real_reference;
8061           if (attribute_flag[2] != 0)
8062             geometry_info.sigma=argument_list[2].real_reference;
8063           if (attribute_flag[3] != 0)
8064             channel=(ChannelType) argument_list[3].integer_reference;
8065           channel_mask=SetImageChannelMask(image,channel);
8066           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8067             (size_t) geometry_info.sigma,exception);
8068           if (image != (Image *) NULL)
8069             (void) SetImageChannelMask(image,channel_mask);
8070           break;
8071         }
8072         case 19:  /* Minify */
8073         {
8074           image=MinifyImage(image,exception);
8075           break;
8076         }
8077         case 20:  /* OilPaint */
8078         {
8079           if (attribute_flag[0] == 0)
8080             argument_list[0].real_reference=0.0;
8081           if (attribute_flag[1] == 0)
8082             argument_list[1].real_reference=1.0;
8083           image=OilPaintImage(image,argument_list[0].real_reference,
8084             argument_list[1].real_reference,exception);
8085           break;
8086         }
8087         case 21:  /* ReduceNoise */
8088         {
8089           if (attribute_flag[0] != 0)
8090             {
8091               flags=ParseGeometry(argument_list[0].string_reference,
8092                 &geometry_info);
8093               if ((flags & SigmaValue) == 0)
8094                 geometry_info.sigma=1.0;
8095             }
8096           if (attribute_flag[1] != 0)
8097             geometry_info.rho=argument_list[1].real_reference;
8098           if (attribute_flag[2] != 0)
8099             geometry_info.sigma=argument_list[2].real_reference;
8100           if (attribute_flag[3] != 0)
8101             channel=(ChannelType) argument_list[3].integer_reference;
8102           channel_mask=SetImageChannelMask(image,channel);
8103           image=StatisticImage(image,NonpeakStatistic,(size_t)
8104             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8105           if (image != (Image *) NULL)
8106             (void) SetImageChannelMask(image,channel_mask);
8107           break;
8108         }
8109         case 22:  /* Roll */
8110         {
8111           if (attribute_flag[0] != 0)
8112             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8113               &geometry,exception);
8114           if (attribute_flag[1] != 0)
8115             geometry.x=argument_list[1].integer_reference;
8116           if (attribute_flag[2] != 0)
8117             geometry.y=argument_list[2].integer_reference;
8118           image=RollImage(image,geometry.x,geometry.y,exception);
8119           break;
8120         }
8121         case 23:  /* Rotate */
8122         {
8123           if (attribute_flag[0] == 0)
8124             argument_list[0].real_reference=90.0;
8125           if (attribute_flag[1] != 0)
8126             {
8127               QueryColorCompliance(argument_list[1].string_reference,
8128                 AllCompliance,&image->background_color,exception);
8129               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
8130                   (image->alpha_trait != BlendPixelTrait))
8131                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8132             }
8133           image=RotateImage(image,argument_list[0].real_reference,exception);
8134           break;
8135         }
8136         case 24:  /* Sample */
8137         {
8138           if (attribute_flag[0] != 0)
8139             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8140               &geometry,exception);
8141           if (attribute_flag[1] != 0)
8142             geometry.width=argument_list[1].integer_reference;
8143           if (attribute_flag[2] != 0)
8144             geometry.height=argument_list[2].integer_reference;
8145           image=SampleImage(image,geometry.width,geometry.height,exception);
8146           break;
8147         }
8148         case 25:  /* Scale */
8149         {
8150           if (attribute_flag[0] != 0)
8151             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8152               &geometry,exception);
8153           if (attribute_flag[1] != 0)
8154             geometry.width=argument_list[1].integer_reference;
8155           if (attribute_flag[2] != 0)
8156             geometry.height=argument_list[2].integer_reference;
8157           image=ScaleImage(image,geometry.width,geometry.height,exception);
8158           break;
8159         }
8160         case 26:  /* Shade */
8161         {
8162           if (attribute_flag[0] != 0)
8163             {
8164               flags=ParseGeometry(argument_list[0].string_reference,
8165                 &geometry_info);
8166               if ((flags & SigmaValue) == 0)
8167                 geometry_info.sigma=0.0;
8168             }
8169           if (attribute_flag[1] != 0)
8170             geometry_info.rho=argument_list[1].real_reference;
8171           if (attribute_flag[2] != 0)
8172             geometry_info.sigma=argument_list[2].real_reference;
8173           image=ShadeImage(image,
8174             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8175             geometry_info.rho,geometry_info.sigma,exception);
8176           break;
8177         }
8178         case 27:  /* Sharpen */
8179         {
8180           if (attribute_flag[0] != 0)
8181             {
8182               flags=ParseGeometry(argument_list[0].string_reference,
8183                 &geometry_info);
8184               if ((flags & SigmaValue) == 0)
8185                 geometry_info.sigma=1.0;
8186             }
8187           if (attribute_flag[1] != 0)
8188             geometry_info.rho=argument_list[1].real_reference;
8189           if (attribute_flag[2] != 0)
8190             geometry_info.sigma=argument_list[2].real_reference;
8191           if (attribute_flag[3] != 0)
8192             channel=(ChannelType) argument_list[3].integer_reference;
8193           channel_mask=SetImageChannelMask(image,channel);
8194           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8195             exception);
8196           if (image != (Image *) NULL)
8197             (void) SetImageChannelMask(image,channel_mask);
8198           break;
8199         }
8200         case 28:  /* Shear */
8201         {
8202           if (attribute_flag[0] != 0)
8203             {
8204               flags=ParseGeometry(argument_list[0].string_reference,
8205                 &geometry_info);
8206               if ((flags & SigmaValue) == 0)
8207                 geometry_info.sigma=geometry_info.rho;
8208             }
8209           if (attribute_flag[1] != 0)
8210             geometry_info.rho=argument_list[1].real_reference;
8211           if (attribute_flag[2] != 0)
8212             geometry_info.sigma=argument_list[2].real_reference;
8213           if (attribute_flag[3] != 0)
8214             QueryColorCompliance(argument_list[3].string_reference,
8215               AllCompliance,&image->background_color,exception);
8216           if (attribute_flag[4] != 0)
8217             QueryColorCompliance(argument_list[4].string_reference,
8218               AllCompliance,&image->background_color,exception);
8219           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8220             exception);
8221           break;
8222         }
8223         case 29:  /* Spread */
8224         {
8225           PixelInterpolateMethod
8226             method;
8227
8228           if (attribute_flag[0] == 0)
8229             argument_list[0].real_reference=1.0;
8230           method=UndefinedInterpolatePixel;
8231           if (attribute_flag[1] != 0)
8232             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8233           image=SpreadImage(image,argument_list[0].real_reference,method,
8234             exception);
8235           break;
8236         }
8237         case 30:  /* Swirl */
8238         {
8239           PixelInterpolateMethod
8240             method;
8241
8242           if (attribute_flag[0] == 0)
8243             argument_list[0].real_reference=50.0;
8244           method=UndefinedInterpolatePixel;
8245           if (attribute_flag[1] != 0)
8246             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8247           image=SwirlImage(image,argument_list[0].real_reference,
8248             method,exception);
8249           break;
8250         }
8251         case 31:  /* Resize */
8252         case 32:  /* Zoom */
8253         {
8254           if (attribute_flag[0] != 0)
8255             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8256               &geometry,exception);
8257           if (attribute_flag[1] != 0)
8258             geometry.width=argument_list[1].integer_reference;
8259           if (attribute_flag[2] != 0)
8260             geometry.height=argument_list[2].integer_reference;
8261           if (attribute_flag[3] == 0)
8262             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8263           if (attribute_flag[4] != 0)
8264             SetImageArtifact(image,"filter:support",
8265               argument_list[4].string_reference);
8266           image=ResizeImage(image,geometry.width,geometry.height,
8267             (FilterTypes) argument_list[3].integer_reference,
8268             exception);
8269           break;
8270         }
8271         case 33:  /* Annotate */
8272         {
8273           DrawInfo
8274             *draw_info;
8275
8276           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8277             (DrawInfo *) NULL);
8278           if (attribute_flag[0] != 0)
8279             {
8280               char
8281                 *text;
8282
8283               text=InterpretImageProperties(info ? info->image_info :
8284                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8285                 exception);
8286               (void) CloneString(&draw_info->text,text);
8287               text=DestroyString(text);
8288             }
8289           if (attribute_flag[1] != 0)
8290             (void) CloneString(&draw_info->font,
8291               argument_list[1].string_reference);
8292           if (attribute_flag[2] != 0)
8293             draw_info->pointsize=argument_list[2].real_reference;
8294           if (attribute_flag[3] != 0)
8295             (void) CloneString(&draw_info->density,
8296               argument_list[3].string_reference);
8297           if (attribute_flag[4] != 0)
8298             (void) QueryColorCompliance(argument_list[4].string_reference,
8299               AllCompliance,&draw_info->undercolor,exception);
8300           if (attribute_flag[5] != 0)
8301             {
8302               (void) QueryColorCompliance(argument_list[5].string_reference,
8303                 AllCompliance,&draw_info->stroke,exception);
8304               if (argument_list[5].image_reference != (Image *) NULL)
8305                 draw_info->stroke_pattern=CloneImage(
8306                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8307             }
8308           if (attribute_flag[6] != 0)
8309             {
8310               (void) QueryColorCompliance(argument_list[6].string_reference,
8311                 AllCompliance,&draw_info->fill,exception);
8312               if (argument_list[6].image_reference != (Image *) NULL)
8313                 draw_info->fill_pattern=CloneImage(
8314                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8315             }
8316           if (attribute_flag[7] != 0)
8317             {
8318               (void) CloneString(&draw_info->geometry,
8319                 argument_list[7].string_reference);
8320               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8321                 &geometry,exception);
8322               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8323                 geometry_info.sigma=geometry_info.xi;
8324             }
8325           if (attribute_flag[8] != 0)
8326             (void) QueryColorCompliance(argument_list[8].string_reference,
8327               AllCompliance,&draw_info->fill,exception);
8328           if (attribute_flag[11] != 0)
8329             draw_info->gravity=(GravityType)
8330               argument_list[11].integer_reference;
8331           if (attribute_flag[25] != 0)
8332             {
8333               AV
8334                 *av;
8335
8336               av=(AV *) argument_list[25].array_reference;
8337               if ((av_len(av) != 3) && (av_len(av) != 5))
8338                 {
8339                   ThrowPerlException(exception,OptionError,
8340                     "affine matrix must have 4 or 6 elements",PackageName);
8341                   goto PerlException;
8342                 }
8343               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8344               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8345               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8346               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8347               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8348                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8349                 {
8350                   ThrowPerlException(exception,OptionError,
8351                     "affine matrix is singular",PackageName);
8352                    goto PerlException;
8353                 }
8354               if (av_len(av) == 5)
8355                 {
8356                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8357                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8358                 }
8359             }
8360           for (j=12; j < 17; j++)
8361           {
8362             if (attribute_flag[j] == 0)
8363               continue;
8364             value=argument_list[j].string_reference;
8365             angle=argument_list[j].real_reference;
8366             current=draw_info->affine;
8367             GetAffineMatrix(&affine);
8368             switch (j)
8369             {
8370               case 12:
8371               {
8372                 /*
8373                   Translate.
8374                 */
8375                 flags=ParseGeometry(value,&geometry_info);
8376                 affine.tx=geometry_info.xi;
8377                 affine.ty=geometry_info.psi;
8378                 if ((flags & PsiValue) == 0)
8379                   affine.ty=affine.tx;
8380                 break;
8381               }
8382               case 13:
8383               {
8384                 /*
8385                   Scale.
8386                 */
8387                 flags=ParseGeometry(value,&geometry_info);
8388                 affine.sx=geometry_info.rho;
8389                 affine.sy=geometry_info.sigma;
8390                 if ((flags & SigmaValue) == 0)
8391                   affine.sy=affine.sx;
8392                 break;
8393               }
8394               case 14:
8395               {
8396                 /*
8397                   Rotate.
8398                 */
8399                 if (angle == 0.0)
8400                   break;
8401                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8402                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8403                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8404                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8405                 break;
8406               }
8407               case 15:
8408               {
8409                 /*
8410                   SkewX.
8411                 */
8412                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8413                 break;
8414               }
8415               case 16:
8416               {
8417                 /*
8418                   SkewY.
8419                 */
8420                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8421                 break;
8422               }
8423             }
8424             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8425             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8426             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8427             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8428             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8429               current.tx;
8430             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8431               current.ty;
8432           }
8433           if (attribute_flag[9] == 0)
8434             argument_list[9].real_reference=0.0;
8435           if (attribute_flag[10] == 0)
8436             argument_list[10].real_reference=0.0;
8437           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8438             {
8439               char
8440                 geometry[MaxTextExtent];
8441
8442               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8443                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8444                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8445               (void) CloneString(&draw_info->geometry,geometry);
8446             }
8447           if (attribute_flag[17] != 0)
8448             draw_info->stroke_width=argument_list[17].real_reference;
8449           if (attribute_flag[18] != 0)
8450             {
8451               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8452                 MagickTrue : MagickFalse;
8453               draw_info->stroke_antialias=draw_info->text_antialias;
8454             }
8455           if (attribute_flag[19] != 0)
8456             (void) CloneString(&draw_info->family,
8457               argument_list[19].string_reference);
8458           if (attribute_flag[20] != 0)
8459             draw_info->style=(StyleType) argument_list[20].integer_reference;
8460           if (attribute_flag[21] != 0)
8461             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8462           if (attribute_flag[22] != 0)
8463             draw_info->weight=argument_list[22].integer_reference;
8464           if (attribute_flag[23] != 0)
8465             draw_info->align=(AlignType) argument_list[23].integer_reference;
8466           if (attribute_flag[24] != 0)
8467             (void) CloneString(&draw_info->encoding,
8468               argument_list[24].string_reference);
8469           if (attribute_flag[25] != 0)
8470             draw_info->fill_pattern=CloneImage(
8471               argument_list[25].image_reference,0,0,MagickTrue,exception);
8472           if (attribute_flag[26] != 0)
8473             draw_info->fill_pattern=CloneImage(
8474               argument_list[26].image_reference,0,0,MagickTrue,exception);
8475           if (attribute_flag[27] != 0)
8476             draw_info->stroke_pattern=CloneImage(
8477               argument_list[27].image_reference,0,0,MagickTrue,exception);
8478           if (attribute_flag[29] != 0)
8479             draw_info->kerning=argument_list[29].real_reference;
8480           if (attribute_flag[30] != 0)
8481             draw_info->interline_spacing=argument_list[30].real_reference;
8482           if (attribute_flag[31] != 0)
8483             draw_info->interword_spacing=argument_list[31].real_reference;
8484           if (attribute_flag[32] != 0)
8485             draw_info->direction=(DirectionType)
8486               argument_list[32].integer_reference;
8487           (void) AnnotateImage(image,draw_info,exception);
8488           draw_info=DestroyDrawInfo(draw_info);
8489           break;
8490         }
8491         case 34:  /* ColorFloodfill */
8492         {
8493           DrawInfo
8494             *draw_info;
8495
8496           MagickBooleanType
8497             invert;
8498
8499           PixelInfo
8500             target;
8501
8502           draw_info=CloneDrawInfo(info ? info->image_info :
8503             (ImageInfo *) NULL,(DrawInfo *) NULL);
8504           if (attribute_flag[0] != 0)
8505             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8506               &geometry,exception);
8507           if (attribute_flag[1] != 0)
8508             geometry.x=argument_list[1].integer_reference;
8509           if (attribute_flag[2] != 0)
8510             geometry.y=argument_list[2].integer_reference;
8511           if (attribute_flag[3] != 0)
8512             (void) QueryColorCompliance(argument_list[3].string_reference,
8513               AllCompliance,&draw_info->fill,exception);
8514           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8515             geometry.x,geometry.y,&target,exception);
8516           invert=MagickFalse;
8517           if (attribute_flag[4] != 0)
8518             {
8519               QueryColorCompliance(argument_list[4].string_reference,
8520                 AllCompliance,&target,exception);
8521               invert=MagickTrue;
8522             }
8523           if (attribute_flag[5] != 0)
8524             image->fuzz=StringToDoubleInterval(
8525               argument_list[5].string_reference,(double) QuantumRange+1.0);
8526           if (attribute_flag[6] != 0)
8527             invert=(MagickBooleanType) argument_list[6].integer_reference;
8528           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8529             geometry.y,invert,exception);
8530           draw_info=DestroyDrawInfo(draw_info);
8531           break;
8532         }
8533         case 35:  /* Composite */
8534         {
8535           char
8536             composite_geometry[MaxTextExtent];
8537
8538           Image
8539             *composite_image,
8540             *rotate_image;
8541
8542           MagickBooleanType
8543             clip_to_self;
8544
8545           compose=OverCompositeOp;
8546           if (attribute_flag[0] != 0)
8547             composite_image=argument_list[0].image_reference;
8548           else
8549             {
8550               ThrowPerlException(exception,OptionError,
8551                 "CompositeImageRequired",PackageName);
8552               goto PerlException;
8553             }
8554           /*
8555             Parameter Handling used for BOTH normal and tiled composition.
8556           */
8557           if (attribute_flag[1] != 0) /* compose */
8558             compose=(CompositeOperator) argument_list[1].integer_reference;
8559           if (attribute_flag[6] != 0) /* opacity  */
8560             {
8561               if (compose != DissolveCompositeOp)
8562                 (void) SetImageAlpha(composite_image,(Quantum)
8563                   StringToDoubleInterval(argument_list[6].string_reference,
8564                   (double) QuantumRange+1.0),exception);
8565               else
8566                 {
8567                   CacheView
8568                     *composite_view;
8569
8570                   double
8571                     opacity;
8572
8573                   MagickBooleanType
8574                     sync;
8575
8576                   register ssize_t
8577                     x;
8578
8579                   register Quantum
8580                     *q;
8581
8582                   ssize_t
8583                     y;
8584
8585                   /*
8586                     Handle dissolve composite operator (patch by
8587                     Kevin A. McGrail).
8588                   */
8589                   (void) CloneString(&image->geometry,
8590                     argument_list[6].string_reference);
8591                   opacity=(Quantum) StringToDoubleInterval(
8592                     argument_list[6].string_reference,(double) QuantumRange+
8593                     1.0);
8594                   if (composite_image->alpha_trait == BlendPixelTrait)
8595                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8596                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8597                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8598                   {
8599                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8600                       composite_image->columns,1,exception);
8601                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8602                     {
8603                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8604                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8605                           q);
8606                       q+=GetPixelChannels(composite_image);
8607                     }
8608                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8609                     if (sync == MagickFalse)
8610                       break;
8611                   }
8612                   composite_view=DestroyCacheView(composite_view);
8613                 }
8614             }
8615           if (attribute_flag[9] != 0)    /* "color=>" */
8616             QueryColorCompliance(argument_list[9].string_reference,
8617               AllCompliance,&composite_image->background_color,exception);
8618           if (attribute_flag[12] != 0) /* "interpolate=>" */
8619             image->interpolate=(PixelInterpolateMethod)
8620               argument_list[12].integer_reference;
8621           if (attribute_flag[13] != 0)   /* "args=>" */
8622             (void) SetImageArtifact(composite_image,"compose:args",
8623               argument_list[13].string_reference);
8624           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8625             (void) SetImageArtifact(composite_image,"compose:args",
8626               argument_list[14].string_reference);
8627           clip_to_self=MagickTrue;
8628           if (attribute_flag[15] != 0)
8629             clip_to_self=(MagickBooleanType)
8630               argument_list[15].integer_reference;
8631           /*
8632             Tiling Composition (with orthogonal rotate).
8633           */
8634           rotate_image=(Image *) NULL;
8635           if (attribute_flag[8] != 0)   /* "rotate=>" */
8636             {
8637                /*
8638                  Rotate image.
8639                */
8640                rotate_image=RotateImage(composite_image,
8641                  argument_list[8].real_reference,exception);
8642                if (rotate_image == (Image *) NULL)
8643                  break;
8644             }
8645           if ((attribute_flag[7] != 0) &&
8646               (argument_list[7].integer_reference != 0)) /* tile */
8647             {
8648               ssize_t
8649                 x,
8650                 y;
8651
8652               /*
8653                 Tile the composite image.
8654               */
8655              if (attribute_flag[8] != 0)   /* "tile=>" */
8656                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8657                  "false");
8658              else
8659                (void) SetImageArtifact(composite_image,
8660                  "compose:outside-overlay","false");
8661              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8662                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8663                 {
8664                   if (attribute_flag[8] != 0) /* rotate */
8665                     (void) CompositeImage(image,rotate_image,compose,
8666                       MagickTrue,x,y,exception);
8667                   else
8668                     (void) CompositeImage(image,composite_image,compose,
8669                       MagickTrue,x,y,exception);
8670                 }
8671               if (attribute_flag[8] != 0) /* rotate */
8672                 rotate_image=DestroyImage(rotate_image);
8673               break;
8674             }
8675           /*
8676             Parameter Handling used used ONLY for normal composition.
8677           */
8678           if (attribute_flag[5] != 0) /* gravity */
8679             image->gravity=(GravityType) argument_list[5].integer_reference;
8680           if (attribute_flag[2] != 0) /* geometry offset */
8681             {
8682               SetGeometry(image,&geometry);
8683               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8684                 &geometry);
8685               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8686                 &geometry);
8687             }
8688           if (attribute_flag[3] != 0) /* x offset */
8689             geometry.x=argument_list[3].integer_reference;
8690           if (attribute_flag[4] != 0) /* y offset */
8691             geometry.y=argument_list[4].integer_reference;
8692           if (attribute_flag[10] != 0) /* mask */
8693             {
8694               if ((image->compose == DisplaceCompositeOp) ||
8695                   (image->compose == DistortCompositeOp))
8696                 {
8697                   /*
8698                     Merge Y displacement into X displacement image.
8699                   */
8700                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8701                     exception);
8702                   (void) CompositeImage(composite_image,
8703                     argument_list[10].image_reference,CopyGreenCompositeOp,
8704                     MagickTrue,0,0,exception);
8705                 }
8706               else
8707                 {
8708                   Image
8709                     *mask_image;
8710
8711                   /*
8712                     Set a blending mask for the composition.
8713                   */
8714                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8715                     MagickTrue,exception);
8716                   (void) SetImageMask(composite_image,mask_image,exception);
8717                   mask_image=DestroyImage(mask_image);
8718                 }
8719             }
8720           if (attribute_flag[11] != 0) /* channel */
8721             channel=(ChannelType) argument_list[11].integer_reference;
8722           /*
8723             Composite two images (normal composition).
8724           */
8725           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8726             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8727             (double) composite_image->rows,(double) geometry.x,(double)
8728             geometry.y);
8729           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8730             exception);
8731           channel_mask=SetImageChannelMask(image,channel);
8732           if (attribute_flag[8] == 0) /* no rotate */
8733             CompositeImage(image,composite_image,compose,clip_to_self,
8734               geometry.x,geometry.y,exception);
8735           else
8736             {
8737               /*
8738                 Position adjust rotated image then composite.
8739               */
8740               geometry.x-=(ssize_t) (rotate_image->columns-
8741                 composite_image->columns)/2;
8742               geometry.y-=(ssize_t) (rotate_image->rows-
8743                 composite_image->rows)/2;
8744               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8745                 geometry.y,exception);
8746               rotate_image=DestroyImage(rotate_image);
8747             }
8748           if (attribute_flag[10] != 0) /* mask */
8749             {
8750               if ((image->compose == DisplaceCompositeOp) ||
8751                   (image->compose == DistortCompositeOp))
8752                 composite_image=DestroyImage(composite_image);
8753               else
8754                 (void) SetImageMask(image,(Image *) NULL,exception);
8755             }
8756           (void) SetImageChannelMask(image,channel_mask);
8757           break;
8758         }
8759         case 36:  /* Contrast */
8760         {
8761           if (attribute_flag[0] == 0)
8762             argument_list[0].integer_reference=0;
8763           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8764             MagickTrue : MagickFalse,exception);
8765           break;
8766         }
8767         case 37:  /* CycleColormap */
8768         {
8769           if (attribute_flag[0] == 0)
8770             argument_list[0].integer_reference=6;
8771           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8772             exception);
8773           break;
8774         }
8775         case 38:  /* Draw */
8776         {
8777           DrawInfo
8778             *draw_info;
8779
8780           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8781             (DrawInfo *) NULL);
8782           (void) CloneString(&draw_info->primitive,"point");
8783           if (attribute_flag[0] != 0)
8784             {
8785               if (argument_list[0].integer_reference < 0)
8786                 (void) CloneString(&draw_info->primitive,
8787                   argument_list[0].string_reference);
8788               else
8789                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8790                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8791             }
8792           if (attribute_flag[1] != 0)
8793             {
8794               if (LocaleCompare(draw_info->primitive,"path") == 0)
8795                 {
8796                   (void) ConcatenateString(&draw_info->primitive," '");
8797                   ConcatenateString(&draw_info->primitive,
8798                     argument_list[1].string_reference);
8799                   (void) ConcatenateString(&draw_info->primitive,"'");
8800                 }
8801               else
8802                 {
8803                   (void) ConcatenateString(&draw_info->primitive," ");
8804                   ConcatenateString(&draw_info->primitive,
8805                     argument_list[1].string_reference);
8806                 }
8807             }
8808           if (attribute_flag[2] != 0)
8809             {
8810               (void) ConcatenateString(&draw_info->primitive," ");
8811               (void) ConcatenateString(&draw_info->primitive,
8812                 CommandOptionToMnemonic(MagickMethodOptions,
8813                 argument_list[2].integer_reference));
8814             }
8815           if (attribute_flag[3] != 0)
8816             {
8817               (void) QueryColorCompliance(argument_list[3].string_reference,
8818                 AllCompliance,&draw_info->stroke,exception);
8819               if (argument_list[3].image_reference != (Image *) NULL)
8820                 draw_info->stroke_pattern=CloneImage(
8821                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8822             }
8823           if (attribute_flag[4] != 0)
8824             {
8825               (void) QueryColorCompliance(argument_list[4].string_reference,
8826                 AllCompliance,&draw_info->fill,exception);
8827               if (argument_list[4].image_reference != (Image *) NULL)
8828                 draw_info->fill_pattern=CloneImage(
8829                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8830             }
8831           if (attribute_flag[5] != 0)
8832             draw_info->stroke_width=argument_list[5].real_reference;
8833           if (attribute_flag[6] != 0)
8834             (void) CloneString(&draw_info->font,
8835               argument_list[6].string_reference);
8836           if (attribute_flag[7] != 0)
8837             (void) QueryColorCompliance(argument_list[7].string_reference,
8838               AllCompliance,&draw_info->border_color,exception);
8839           if (attribute_flag[8] != 0)
8840             draw_info->affine.tx=argument_list[8].real_reference;
8841           if (attribute_flag[9] != 0)
8842             draw_info->affine.ty=argument_list[9].real_reference;
8843           if (attribute_flag[20] != 0)
8844             {
8845               AV
8846                 *av;
8847
8848               av=(AV *) argument_list[20].array_reference;
8849               if ((av_len(av) != 3) && (av_len(av) != 5))
8850                 {
8851                   ThrowPerlException(exception,OptionError,
8852                     "affine matrix must have 4 or 6 elements",PackageName);
8853                   goto PerlException;
8854                 }
8855               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8856               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8857               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8858               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8859               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8860                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8861                 {
8862                   ThrowPerlException(exception,OptionError,
8863                     "affine matrix is singular",PackageName);
8864                    goto PerlException;
8865                 }
8866               if (av_len(av) == 5)
8867                 {
8868                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8869                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8870                 }
8871             }
8872           for (j=10; j < 15; j++)
8873           {
8874             if (attribute_flag[j] == 0)
8875               continue;
8876             value=argument_list[j].string_reference;
8877             angle=argument_list[j].real_reference;
8878             current=draw_info->affine;
8879             GetAffineMatrix(&affine);
8880             switch (j)
8881             {
8882               case 10:
8883               {
8884                 /*
8885                   Translate.
8886                 */
8887                 flags=ParseGeometry(value,&geometry_info);
8888                 affine.tx=geometry_info.xi;
8889                 affine.ty=geometry_info.psi;
8890                 if ((flags & PsiValue) == 0)
8891                   affine.ty=affine.tx;
8892                 break;
8893               }
8894               case 11:
8895               {
8896                 /*
8897                   Scale.
8898                 */
8899                 flags=ParseGeometry(value,&geometry_info);
8900                 affine.sx=geometry_info.rho;
8901                 affine.sy=geometry_info.sigma;
8902                 if ((flags & SigmaValue) == 0)
8903                   affine.sy=affine.sx;
8904                 break;
8905               }
8906               case 12:
8907               {
8908                 /*
8909                   Rotate.
8910                 */
8911                 if (angle == 0.0)
8912                   break;
8913                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8914                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8915                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8916                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8917                 break;
8918               }
8919               case 13:
8920               {
8921                 /*
8922                   SkewX.
8923                 */
8924                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8925                 break;
8926               }
8927               case 14:
8928               {
8929                 /*
8930                   SkewY.
8931                 */
8932                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8933                 break;
8934               }
8935             }
8936             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8937             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8938             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8939             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8940             draw_info->affine.tx=
8941               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8942             draw_info->affine.ty=
8943               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8944           }
8945           if (attribute_flag[15] != 0)
8946             draw_info->fill_pattern=CloneImage(
8947               argument_list[15].image_reference,0,0,MagickTrue,exception);
8948           if (attribute_flag[16] != 0)
8949             draw_info->pointsize=argument_list[16].real_reference;
8950           if (attribute_flag[17] != 0)
8951             {
8952               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8953                 ? MagickTrue : MagickFalse;
8954               draw_info->text_antialias=draw_info->stroke_antialias;
8955             }
8956           if (attribute_flag[18] != 0)
8957             (void) CloneString(&draw_info->density,
8958               argument_list[18].string_reference);
8959           if (attribute_flag[19] != 0)
8960             draw_info->stroke_width=argument_list[19].real_reference;
8961           if (attribute_flag[21] != 0)
8962             draw_info->dash_offset=argument_list[21].real_reference;
8963           if (attribute_flag[22] != 0)
8964             {
8965               AV
8966                 *av;
8967
8968               av=(AV *) argument_list[22].array_reference;
8969               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8970                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8971               if (draw_info->dash_pattern != (double *) NULL)
8972                 {
8973                   for (i=0; i <= av_len(av); i++)
8974                     draw_info->dash_pattern[i]=(double)
8975                       SvNV(*(av_fetch(av,i,0)));
8976                   draw_info->dash_pattern[i]=0.0;
8977                 }
8978             }
8979           if (attribute_flag[23] != 0)
8980             image->interpolate=(PixelInterpolateMethod)
8981               argument_list[23].integer_reference;
8982           if ((attribute_flag[24] != 0) &&
8983               (draw_info->fill_pattern != (Image *) NULL))
8984             flags=ParsePageGeometry(draw_info->fill_pattern,
8985               argument_list[24].string_reference,
8986               &draw_info->fill_pattern->tile_offset,exception);
8987           if (attribute_flag[25] != 0)
8988             {
8989               (void) ConcatenateString(&draw_info->primitive," '");
8990               (void) ConcatenateString(&draw_info->primitive,
8991                 argument_list[25].string_reference);
8992               (void) ConcatenateString(&draw_info->primitive,"'");
8993             }
8994           if (attribute_flag[26] != 0)
8995             draw_info->fill_pattern=CloneImage(
8996               argument_list[26].image_reference,0,0,MagickTrue,exception);
8997           if (attribute_flag[27] != 0)
8998             draw_info->stroke_pattern=CloneImage(
8999               argument_list[27].image_reference,0,0,MagickTrue,exception);
9000           if (attribute_flag[28] != 0)
9001             (void) CloneString(&draw_info->primitive,
9002               argument_list[28].string_reference);
9003           if (attribute_flag[29] != 0)
9004             draw_info->kerning=argument_list[29].real_reference;
9005           if (attribute_flag[30] != 0)
9006             draw_info->interline_spacing=argument_list[30].real_reference;
9007           if (attribute_flag[31] != 0)
9008             draw_info->interword_spacing=argument_list[31].real_reference;
9009           if (attribute_flag[32] != 0)
9010             draw_info->direction=(DirectionType)
9011               argument_list[32].integer_reference;
9012           DrawImage(image,draw_info,exception);
9013           draw_info=DestroyDrawInfo(draw_info);
9014           break;
9015         }
9016         case 39:  /* Equalize */
9017         {
9018           if (attribute_flag[0] != 0)
9019             channel=(ChannelType) argument_list[0].integer_reference;
9020           channel_mask=SetImageChannelMask(image,channel);
9021           EqualizeImage(image,exception);
9022           (void) SetImageChannelMask(image,channel_mask);
9023           break;
9024         }
9025         case 40:  /* Gamma */
9026         {
9027           if (attribute_flag[1] != 0)
9028             channel=(ChannelType) argument_list[1].integer_reference;
9029           if (attribute_flag[2] == 0)
9030             argument_list[2].real_reference=1.0;
9031           if (attribute_flag[3] == 0)
9032             argument_list[3].real_reference=1.0;
9033           if (attribute_flag[4] == 0)
9034             argument_list[4].real_reference=1.0;
9035           if (attribute_flag[0] == 0)
9036             {
9037               (void) FormatLocaleString(message,MaxTextExtent,
9038                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9039                 (double) argument_list[3].real_reference,
9040                 (double) argument_list[4].real_reference);
9041               argument_list[0].string_reference=message;
9042             }
9043           (void) GammaImage(image,StringToDouble(
9044             argument_list[0].string_reference,(char **) NULL),exception);
9045           break;
9046         }
9047         case 41:  /* Map */
9048         {
9049           QuantizeInfo
9050             *quantize_info;
9051
9052           if (attribute_flag[0] == 0)
9053             {
9054               ThrowPerlException(exception,OptionError,"MapImageRequired",
9055                 PackageName);
9056               goto PerlException;
9057             }
9058           quantize_info=AcquireQuantizeInfo(info->image_info);
9059           if (attribute_flag[1] != 0)
9060             quantize_info->dither_method=(DitherMethod)
9061               argument_list[1].integer_reference;
9062           (void) RemapImages(quantize_info,image,
9063             argument_list[0].image_reference,exception);
9064           quantize_info=DestroyQuantizeInfo(quantize_info);
9065           break;
9066         }
9067         case 42:  /* MatteFloodfill */
9068         {
9069           DrawInfo
9070             *draw_info;
9071
9072           MagickBooleanType
9073             invert;
9074
9075           PixelInfo
9076             target;
9077
9078           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9079             (DrawInfo *) NULL);
9080           if (attribute_flag[0] != 0)
9081             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9082               &geometry,exception);
9083           if (attribute_flag[1] != 0)
9084             geometry.x=argument_list[1].integer_reference;
9085           if (attribute_flag[2] != 0)
9086             geometry.y=argument_list[2].integer_reference;
9087           if (image->alpha_trait != BlendPixelTrait)
9088             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9089           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9090             geometry.x,geometry.y,&target,exception);
9091           if (attribute_flag[4] != 0)
9092             QueryColorCompliance(argument_list[4].string_reference,
9093               AllCompliance,&target,exception);
9094           if (attribute_flag[3] != 0)
9095             target.alpha=StringToDoubleInterval(
9096               argument_list[3].string_reference,(double) (double) QuantumRange+
9097               1.0);
9098           if (attribute_flag[5] != 0)
9099             image->fuzz=StringToDoubleInterval(
9100               argument_list[5].string_reference,(double) QuantumRange+1.0);
9101           invert=MagickFalse;
9102           if (attribute_flag[6] != 0)
9103             invert=(MagickBooleanType) argument_list[6].integer_reference;
9104           channel_mask=SetImageChannelMask(image,AlphaChannel);
9105           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9106             geometry.y,invert,exception);
9107           (void) SetImageChannelMask(image,channel_mask);
9108           draw_info=DestroyDrawInfo(draw_info);
9109           break;
9110         }
9111         case 43:  /* Modulate */
9112         {
9113           char
9114             modulate[MaxTextExtent];
9115
9116           geometry_info.rho=100.0;
9117           geometry_info.sigma=100.0;
9118           geometry_info.xi=100.0;
9119           if (attribute_flag[0] != 0)
9120             (void)ParseGeometry(argument_list[0].string_reference,
9121               &geometry_info);
9122           if (attribute_flag[1] != 0)
9123             geometry_info.xi=argument_list[1].real_reference;
9124           if (attribute_flag[2] != 0)
9125             geometry_info.sigma=argument_list[2].real_reference;
9126           if (attribute_flag[3] != 0)
9127             {
9128               geometry_info.sigma=argument_list[3].real_reference;
9129               SetImageArtifact(image,"modulate:colorspace","HWB");
9130             }
9131           if (attribute_flag[4] != 0)
9132             {
9133               geometry_info.rho=argument_list[4].real_reference;
9134               SetImageArtifact(image,"modulate:colorspace","HSB");
9135             }
9136           if (attribute_flag[5] != 0)
9137             {
9138               geometry_info.sigma=argument_list[5].real_reference;
9139               SetImageArtifact(image,"modulate:colorspace","HSL");
9140             }
9141           if (attribute_flag[6] != 0)
9142             {
9143               geometry_info.rho=argument_list[6].real_reference;
9144               SetImageArtifact(image,"modulate:colorspace","HWB");
9145             }
9146           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
9147             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9148           (void) ModulateImage(image,modulate,exception);
9149           break;
9150         }
9151         case 44:  /* Negate */
9152         {
9153           if (attribute_flag[0] == 0)
9154             argument_list[0].integer_reference=0;
9155           if (attribute_flag[1] != 0)
9156             channel=(ChannelType) argument_list[1].integer_reference;
9157           channel_mask=SetImageChannelMask(image,channel);
9158           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9159             MagickTrue : MagickFalse,exception);
9160           (void) SetImageChannelMask(image,channel_mask);
9161           break;
9162         }
9163         case 45:  /* Normalize */
9164         {
9165           if (attribute_flag[0] != 0)
9166             channel=(ChannelType) argument_list[0].integer_reference;
9167           channel_mask=SetImageChannelMask(image,channel);
9168           NormalizeImage(image,exception);
9169           (void) SetImageChannelMask(image,channel_mask);
9170           break;
9171         }
9172         case 46:  /* NumberColors */
9173           break;
9174         case 47:  /* Opaque */
9175         {
9176           MagickBooleanType
9177             invert;
9178
9179           PixelInfo
9180             fill_color,
9181             target;
9182
9183           (void) QueryColorCompliance("none",AllCompliance,&target,
9184              exception);
9185           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9186             exception);
9187           if (attribute_flag[0] != 0)
9188             (void) QueryColorCompliance(argument_list[0].string_reference,
9189               AllCompliance,&target,exception);
9190           if (attribute_flag[1] != 0)
9191             (void) QueryColorCompliance(argument_list[1].string_reference,
9192               AllCompliance,&fill_color,exception);
9193           if (attribute_flag[2] != 0)
9194             image->fuzz=StringToDoubleInterval(
9195               argument_list[2].string_reference,(double) QuantumRange+1.0);
9196           if (attribute_flag[3] != 0)
9197             channel=(ChannelType) argument_list[3].integer_reference;
9198           invert=MagickFalse;
9199           if (attribute_flag[4] != 0)
9200             invert=(MagickBooleanType) argument_list[4].integer_reference;
9201           channel_mask=SetImageChannelMask(image,channel);
9202           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9203           (void) SetImageChannelMask(image,channel_mask);
9204           break;
9205         }
9206         case 48:  /* Quantize */
9207         {
9208           QuantizeInfo
9209             *quantize_info;
9210
9211           quantize_info=AcquireQuantizeInfo(info->image_info);
9212           if (attribute_flag[0] != 0)
9213             quantize_info->number_colors=(size_t)
9214               argument_list[0].integer_reference;
9215           if (attribute_flag[1] != 0)
9216             quantize_info->tree_depth=(size_t)
9217               argument_list[1].integer_reference;
9218           if (attribute_flag[2] != 0)
9219             quantize_info->colorspace=(ColorspaceType)
9220               argument_list[2].integer_reference;
9221           if (attribute_flag[3] != 0)
9222             quantize_info->dither_method=(DitherMethod)
9223               argument_list[3].integer_reference;
9224           if (attribute_flag[4] != 0)
9225             quantize_info->measure_error=argument_list[4].integer_reference !=
9226               0 ? MagickTrue : MagickFalse;
9227           if (attribute_flag[5] != 0)
9228             (void) QueryColorCompliance(argument_list[5].string_reference,
9229               AllCompliance,&image->transparent_color,exception);
9230           if (attribute_flag[5] && argument_list[5].integer_reference)
9231             {
9232               (void) QuantizeImages(quantize_info,image,exception);
9233               goto PerlException;
9234             }
9235           if (attribute_flag[6] != 0)
9236             quantize_info->dither_method=(DitherMethod)
9237               argument_list[6].integer_reference;
9238           if ((image->storage_class == DirectClass) ||
9239               (image->colors > quantize_info->number_colors) ||
9240               (quantize_info->colorspace == GRAYColorspace))
9241             (void) QuantizeImage(quantize_info,image,exception);
9242           else
9243             CompressImageColormap(image,exception);
9244           quantize_info=DestroyQuantizeInfo(quantize_info);
9245           break;
9246         }
9247         case 49:  /* Raise */
9248         {
9249           if (attribute_flag[0] != 0)
9250             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9251               &geometry,exception);
9252           if (attribute_flag[1] != 0)
9253             geometry.width=argument_list[1].integer_reference;
9254           if (attribute_flag[2] != 0)
9255             geometry.height=argument_list[2].integer_reference;
9256           if (attribute_flag[3] == 0)
9257             argument_list[3].integer_reference=1;
9258           (void) RaiseImage(image,&geometry,
9259             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9260             exception);
9261           break;
9262         }
9263         case 50:  /* Segment */
9264         {
9265           ColorspaceType
9266             colorspace;
9267
9268           double
9269             cluster_threshold,
9270             smoothing_threshold;
9271
9272           MagickBooleanType
9273             verbose;
9274
9275           cluster_threshold=1.0;
9276           smoothing_threshold=1.5;
9277           colorspace=sRGBColorspace;
9278           verbose=MagickFalse;
9279           if (attribute_flag[0] != 0)
9280             {
9281               flags=ParseGeometry(argument_list[0].string_reference,
9282                 &geometry_info);
9283               cluster_threshold=geometry_info.rho;
9284               if (flags & SigmaValue)
9285                 smoothing_threshold=geometry_info.sigma;
9286             }
9287           if (attribute_flag[1] != 0)
9288             cluster_threshold=argument_list[1].real_reference;
9289           if (attribute_flag[2] != 0)
9290             smoothing_threshold=argument_list[2].real_reference;
9291           if (attribute_flag[3] != 0)
9292             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9293           if (attribute_flag[4] != 0)
9294             verbose=argument_list[4].integer_reference != 0 ?
9295               MagickTrue : MagickFalse;
9296           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9297             smoothing_threshold,exception);
9298           break;
9299         }
9300         case 51:  /* Signature */
9301         {
9302           (void) SignatureImage(image,exception);
9303           break;
9304         }
9305         case 52:  /* Solarize */
9306         {
9307           geometry_info.rho=QuantumRange/2.0;
9308           if (attribute_flag[0] != 0)
9309             flags=ParseGeometry(argument_list[0].string_reference,
9310               &geometry_info);
9311           if (attribute_flag[1] != 0)
9312             geometry_info.rho=StringToDoubleInterval(
9313               argument_list[1].string_reference,(double) QuantumRange+1.0);
9314           (void) SolarizeImage(image,geometry_info.rho,exception);
9315           break;
9316         }
9317         case 53:  /* Sync */
9318         {
9319           (void) SyncImage(image,exception);
9320           break;
9321         }
9322         case 54:  /* Texture */
9323         {
9324           if (attribute_flag[0] == 0)
9325             break;
9326           TextureImage(image,argument_list[0].image_reference,exception);
9327           break;
9328         }
9329         case 55:  /* Evalute */
9330         {
9331           MagickEvaluateOperator
9332             op;
9333
9334           op=SetEvaluateOperator;
9335           if (attribute_flag[0] == MagickFalse)
9336             argument_list[0].real_reference=0.0;
9337           if (attribute_flag[1] != MagickFalse)
9338             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9339           if (attribute_flag[2] != MagickFalse)
9340             channel=(ChannelType) argument_list[2].integer_reference;
9341           channel_mask=SetImageChannelMask(image,channel);
9342           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9343             exception);
9344           (void) SetImageChannelMask(image,channel_mask);
9345           break;
9346         }
9347         case 56:  /* Transparent */
9348         {
9349           double
9350             opacity;
9351
9352           MagickBooleanType
9353             invert;
9354
9355           PixelInfo
9356             target;
9357
9358           (void) QueryColorCompliance("none",AllCompliance,&target,
9359             exception);
9360           if (attribute_flag[0] != 0)
9361             (void) QueryColorCompliance(argument_list[0].string_reference,
9362               AllCompliance,&target,exception);
9363           opacity=TransparentAlpha;
9364           if (attribute_flag[1] != 0)
9365             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9366               (double) QuantumRange+1.0);
9367           if (attribute_flag[2] != 0)
9368             image->fuzz=StringToDoubleInterval(
9369               argument_list[2].string_reference,(double) QuantumRange+1.0);
9370           if (attribute_flag[3] == 0)
9371             argument_list[3].integer_reference=0;
9372           invert=MagickFalse;
9373           if (attribute_flag[3] != 0)
9374             invert=(MagickBooleanType) argument_list[3].integer_reference;
9375           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9376             invert,exception);
9377           break;
9378         }
9379         case 57:  /* Threshold */
9380         {
9381           double
9382             threshold;
9383
9384           if (attribute_flag[0] == 0)
9385             argument_list[0].string_reference="50%";
9386           if (attribute_flag[1] != 0)
9387             channel=(ChannelType) argument_list[1].integer_reference;
9388           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9389             (double) QuantumRange+1.0);
9390           channel_mask=SetImageChannelMask(image,channel);
9391           (void) BilevelImage(image,threshold,exception);
9392           (void) SetImageChannelMask(image,channel_mask);
9393           break;
9394         }
9395         case 58:  /* Charcoal */
9396         {
9397           if (attribute_flag[0] != 0)
9398             {
9399               flags=ParseGeometry(argument_list[0].string_reference,
9400                 &geometry_info);
9401               if ((flags & SigmaValue) == 0)
9402                 geometry_info.sigma=1.0;
9403             }
9404           if (attribute_flag[1] != 0)
9405             geometry_info.rho=argument_list[1].real_reference;
9406           if (attribute_flag[2] != 0)
9407             geometry_info.sigma=argument_list[2].real_reference;
9408           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9409             exception);
9410           break;
9411         }
9412         case 59:  /* Trim */
9413         {
9414           if (attribute_flag[0] != 0)
9415             image->fuzz=StringToDoubleInterval(
9416               argument_list[0].string_reference,(double) QuantumRange+1.0);
9417           image=TrimImage(image,exception);
9418           break;
9419         }
9420         case 60:  /* Wave */
9421         {
9422           PixelInterpolateMethod
9423             method;
9424
9425           if (attribute_flag[0] != 0)
9426             {
9427               flags=ParseGeometry(argument_list[0].string_reference,
9428                 &geometry_info);
9429               if ((flags & SigmaValue) == 0)
9430                 geometry_info.sigma=1.0;
9431             }
9432           if (attribute_flag[1] != 0)
9433             geometry_info.rho=argument_list[1].real_reference;
9434           if (attribute_flag[2] != 0)
9435             geometry_info.sigma=argument_list[2].real_reference;
9436           method=UndefinedInterpolatePixel;
9437           if (attribute_flag[3] != 0)
9438             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9439           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9440             method,exception);
9441           break;
9442         }
9443         case 61:  /* Separate */
9444         {
9445           if (attribute_flag[0] != 0)
9446             channel=(ChannelType) argument_list[0].integer_reference;
9447           image=SeparateImage(image,channel,exception);
9448           break;
9449         }
9450         case 63:  /* Stereo */
9451         {
9452           if (attribute_flag[0] == 0)
9453             {
9454               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9455                 PackageName);
9456               goto PerlException;
9457             }
9458           if (attribute_flag[1] != 0)
9459             geometry.x=argument_list[1].integer_reference;
9460           if (attribute_flag[2] != 0)
9461             geometry.y=argument_list[2].integer_reference;
9462           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9463             geometry.x,geometry.y,exception);
9464           break;
9465         }
9466         case 64:  /* Stegano */
9467         {
9468           if (attribute_flag[0] == 0)
9469             {
9470               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9471                 PackageName);
9472               goto PerlException;
9473             }
9474           if (attribute_flag[1] == 0)
9475             argument_list[1].integer_reference=0;
9476           image->offset=argument_list[1].integer_reference;
9477           image=SteganoImage(image,argument_list[0].image_reference,exception);
9478           break;
9479         }
9480         case 65:  /* Deconstruct */
9481         {
9482           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9483           break;
9484         }
9485         case 66:  /* GaussianBlur */
9486         {
9487           if (attribute_flag[0] != 0)
9488             {
9489               flags=ParseGeometry(argument_list[0].string_reference,
9490                 &geometry_info);
9491               if ((flags & SigmaValue) == 0)
9492                 geometry_info.sigma=1.0;
9493             }
9494           if (attribute_flag[1] != 0)
9495             geometry_info.rho=argument_list[1].real_reference;
9496           if (attribute_flag[2] != 0)
9497             geometry_info.sigma=argument_list[2].real_reference;
9498           if (attribute_flag[3] != 0)
9499             channel=(ChannelType) argument_list[3].integer_reference;
9500           channel_mask=SetImageChannelMask(image,channel);
9501           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9502             exception);
9503           if (image != (Image *) NULL)
9504             (void) SetImageChannelMask(image,channel_mask);
9505           break;
9506         }
9507         case 67:  /* Convolve */
9508         {
9509           KernelInfo
9510             *kernel;
9511
9512           kernel=(KernelInfo *) NULL;
9513           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9514             break;
9515           if (attribute_flag[0] != 0)
9516             {
9517               AV
9518                 *av;
9519
9520               size_t
9521                 order;
9522
9523               kernel=AcquireKernelInfo((const char *) NULL);
9524               if (kernel == (KernelInfo *) NULL)
9525                 break;
9526               av=(AV *) argument_list[0].array_reference;
9527               order=(size_t) sqrt(av_len(av)+1);
9528               kernel->width=order;
9529               kernel->height=order;
9530               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9531                 order*sizeof(*kernel->values));
9532               if (kernel->values == (MagickRealType *) NULL)
9533                 {
9534                   kernel=DestroyKernelInfo(kernel);
9535                   ThrowPerlException(exception,ResourceLimitFatalError,
9536                     "MemoryAllocationFailed",PackageName);
9537                   goto PerlException;
9538                 }
9539               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9540                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9541               for ( ; j < (ssize_t) (order*order); j++)
9542                 kernel->values[j]=0.0;
9543             }
9544           if (attribute_flag[1] != 0)
9545             channel=(ChannelType) argument_list[1].integer_reference;
9546           if (attribute_flag[2] != 0)
9547             SetImageArtifact(image,"filter:blur",
9548               argument_list[2].string_reference);
9549           if (attribute_flag[3] != 0)
9550             {
9551               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9552               if (kernel == (KernelInfo *) NULL)
9553                 break;
9554             }
9555           channel_mask=SetImageChannelMask(image,channel);
9556           image=ConvolveImage(image,kernel,exception);
9557           if (image != (Image *) NULL)
9558             (void) SetImageChannelMask(image,channel_mask);
9559           kernel=DestroyKernelInfo(kernel);
9560           break;
9561         }
9562         case 68:  /* Profile */
9563         {
9564           const char
9565             *name;
9566
9567           Image
9568             *profile_image;
9569
9570           ImageInfo
9571             *profile_info;
9572
9573           StringInfo
9574             *profile;
9575
9576           name="*";
9577           if (attribute_flag[0] != 0)
9578             name=argument_list[0].string_reference;
9579           if (attribute_flag[2] != 0)
9580             image->rendering_intent=(RenderingIntent)
9581               argument_list[2].integer_reference;
9582           if (attribute_flag[3] != 0)
9583             image->black_point_compensation=
9584               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9585           if (attribute_flag[1] != 0)
9586             {
9587               if (argument_list[1].length == 0)
9588                 {
9589                   /*
9590                     Remove a profile from the image.
9591                   */
9592                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9593                     exception);
9594                   break;
9595                 }
9596               /*
9597                 Associate user supplied profile with the image.
9598               */
9599               profile=AcquireStringInfo(argument_list[1].length);
9600               SetStringInfoDatum(profile,(const unsigned char *)
9601                 argument_list[1].string_reference);
9602               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9603                 (size_t) GetStringInfoLength(profile),exception);
9604               profile=DestroyStringInfo(profile);
9605               break;
9606             }
9607           /*
9608             Associate a profile with the image.
9609           */
9610           profile_info=CloneImageInfo(info ? info->image_info :
9611             (ImageInfo *) NULL);
9612           profile_image=ReadImages(profile_info,name,exception);
9613           if (profile_image == (Image *) NULL)
9614             break;
9615           ResetImageProfileIterator(profile_image);
9616           name=GetNextImageProfile(profile_image);
9617           while (name != (const char *) NULL)
9618           {
9619             const StringInfo
9620               *profile;
9621
9622             profile=GetImageProfile(profile_image,name);
9623             if (profile != (const StringInfo *) NULL)
9624               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9625                 (size_t) GetStringInfoLength(profile),exception);
9626             name=GetNextImageProfile(profile_image);
9627           }
9628           profile_image=DestroyImage(profile_image);
9629           profile_info=DestroyImageInfo(profile_info);
9630           break;
9631         }
9632         case 69:  /* UnsharpMask */
9633         {
9634           if (attribute_flag[0] != 0)
9635             {
9636               flags=ParseGeometry(argument_list[0].string_reference,
9637                 &geometry_info);
9638               if ((flags & SigmaValue) == 0)
9639                 geometry_info.sigma=1.0;
9640               if ((flags & XiValue) == 0)
9641                 geometry_info.xi=1.0;
9642               if ((flags & PsiValue) == 0)
9643                 geometry_info.psi=0.5;
9644             }
9645           if (attribute_flag[1] != 0)
9646             geometry_info.rho=argument_list[1].real_reference;
9647           if (attribute_flag[2] != 0)
9648             geometry_info.sigma=argument_list[2].real_reference;
9649           if (attribute_flag[3] != 0)
9650             geometry_info.xi=argument_list[3].real_reference;
9651           if (attribute_flag[4] != 0)
9652             geometry_info.psi=argument_list[4].real_reference;
9653           if (attribute_flag[5] != 0)
9654             channel=(ChannelType) argument_list[5].integer_reference;
9655           channel_mask=SetImageChannelMask(image,channel);
9656           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9657             geometry_info.xi,geometry_info.psi,exception);
9658           if (image != (Image *) NULL)
9659             (void) SetImageChannelMask(image,channel_mask);
9660           break;
9661         }
9662         case 70:  /* MotionBlur */
9663         {
9664           if (attribute_flag[0] != 0)
9665             {
9666               flags=ParseGeometry(argument_list[0].string_reference,
9667                 &geometry_info);
9668               if ((flags & SigmaValue) == 0)
9669                 geometry_info.sigma=1.0;
9670               if ((flags & XiValue) == 0)
9671                 geometry_info.xi=1.0;
9672             }
9673           if (attribute_flag[1] != 0)
9674             geometry_info.rho=argument_list[1].real_reference;
9675           if (attribute_flag[2] != 0)
9676             geometry_info.sigma=argument_list[2].real_reference;
9677           if (attribute_flag[3] != 0)
9678             geometry_info.xi=argument_list[3].real_reference;
9679           if (attribute_flag[4] != 0)
9680             channel=(ChannelType) argument_list[4].integer_reference;
9681           channel_mask=SetImageChannelMask(image,channel);
9682           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9683             geometry_info.xi,exception);
9684           if (image != (Image *) NULL)
9685             (void) SetImageChannelMask(image,channel_mask);
9686           break;
9687         }
9688         case 71:  /* OrderedDither */
9689         {
9690           if (attribute_flag[0] == 0)
9691             argument_list[0].string_reference="o8x8";
9692           if (attribute_flag[1] != 0)
9693             channel=(ChannelType) argument_list[1].integer_reference;
9694           channel_mask=SetImageChannelMask(image,channel);
9695           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9696             exception);
9697           (void) SetImageChannelMask(image,channel_mask);
9698           break;
9699         }
9700         case 72:  /* Shave */
9701         {
9702           if (attribute_flag[0] != 0)
9703             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9704               &geometry,exception);
9705           if (attribute_flag[1] != 0)
9706             geometry.width=argument_list[1].integer_reference;
9707           if (attribute_flag[2] != 0)
9708             geometry.height=argument_list[2].integer_reference;
9709           image=ShaveImage(image,&geometry,exception);
9710           break;
9711         }
9712         case 73:  /* Level */
9713         {
9714           double
9715             black_point,
9716             gamma,
9717             white_point;
9718
9719           black_point=0.0;
9720           white_point=(double) image->columns*image->rows;
9721           gamma=1.0;
9722           if (attribute_flag[0] != 0)
9723             {
9724               flags=ParseGeometry(argument_list[0].string_reference,
9725                 &geometry_info);
9726               black_point=geometry_info.rho;
9727               if ((flags & SigmaValue) != 0)
9728                 white_point=geometry_info.sigma;
9729               if ((flags & XiValue) != 0)
9730                 gamma=geometry_info.xi;
9731               if ((flags & PercentValue) != 0)
9732                 {
9733                   black_point*=(double) (QuantumRange/100.0);
9734                   white_point*=(double) (QuantumRange/100.0);
9735                 }
9736               if ((flags & SigmaValue) == 0)
9737                 white_point=(double) QuantumRange-black_point;
9738             }
9739           if (attribute_flag[1] != 0)
9740             black_point=argument_list[1].real_reference;
9741           if (attribute_flag[2] != 0)
9742             white_point=argument_list[2].real_reference;
9743           if (attribute_flag[3] != 0)
9744             gamma=argument_list[3].real_reference;
9745           if (attribute_flag[4] != 0)
9746             channel=(ChannelType) argument_list[4].integer_reference;
9747           if (attribute_flag[5] != 0)
9748             {
9749               argument_list[0].real_reference=argument_list[5].real_reference;
9750               attribute_flag[0]=attribute_flag[5];
9751             }
9752           channel_mask=SetImageChannelMask(image,channel);
9753           (void) LevelImage(image,black_point,white_point,gamma,exception);
9754           (void) SetImageChannelMask(image,channel_mask);
9755           break;
9756         }
9757         case 74:  /* Clip */
9758         {
9759           if (attribute_flag[0] == 0)
9760             argument_list[0].string_reference="#1";
9761           if (attribute_flag[1] == 0)
9762             argument_list[1].integer_reference=MagickTrue;
9763           (void) ClipImagePath(image,argument_list[0].string_reference,
9764             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9765             exception);
9766           break;
9767         }
9768         case 75:  /* AffineTransform */
9769         {
9770           DrawInfo
9771             *draw_info;
9772
9773           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9774             (DrawInfo *) NULL);
9775           if (attribute_flag[0] != 0)
9776             {
9777               AV
9778                 *av;
9779
9780               av=(AV *) argument_list[0].array_reference;
9781               if ((av_len(av) != 3) && (av_len(av) != 5))
9782                 {
9783                   ThrowPerlException(exception,OptionError,
9784                     "affine matrix must have 4 or 6 elements",PackageName);
9785                   goto PerlException;
9786                 }
9787               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9788               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9789               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9790               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9791               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9792                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9793                 {
9794                   ThrowPerlException(exception,OptionError,
9795                     "affine matrix is singular",PackageName);
9796                    goto PerlException;
9797                 }
9798               if (av_len(av) == 5)
9799                 {
9800                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9801                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9802                 }
9803             }
9804           for (j=1; j < 6; j++)
9805           {
9806             if (attribute_flag[j] == 0)
9807               continue;
9808             value=argument_list[j].string_reference;
9809             angle=argument_list[j].real_reference;
9810             current=draw_info->affine;
9811             GetAffineMatrix(&affine);
9812             switch (j)
9813             {
9814               case 1:
9815               {
9816                 /*
9817                   Translate.
9818                 */
9819                 flags=ParseGeometry(value,&geometry_info);
9820                 affine.tx=geometry_info.xi;
9821                 affine.ty=geometry_info.psi;
9822                 if ((flags & PsiValue) == 0)
9823                   affine.ty=affine.tx;
9824                 break;
9825               }
9826               case 2:
9827               {
9828                 /*
9829                   Scale.
9830                 */
9831                 flags=ParseGeometry(value,&geometry_info);
9832                 affine.sx=geometry_info.rho;
9833                 affine.sy=geometry_info.sigma;
9834                 if ((flags & SigmaValue) == 0)
9835                   affine.sy=affine.sx;
9836                 break;
9837               }
9838               case 3:
9839               {
9840                 /*
9841                   Rotate.
9842                 */
9843                 if (angle == 0.0)
9844                   break;
9845                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9846                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9847                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9848                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9849                 break;
9850               }
9851               case 4:
9852               {
9853                 /*
9854                   SkewX.
9855                 */
9856                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9857                 break;
9858               }
9859               case 5:
9860               {
9861                 /*
9862                   SkewY.
9863                 */
9864                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9865                 break;
9866               }
9867             }
9868             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9869             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9870             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9871             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9872             draw_info->affine.tx=
9873               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9874             draw_info->affine.ty=
9875               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9876           }
9877           if (attribute_flag[6] != 0)
9878             image->interpolate=(PixelInterpolateMethod)
9879               argument_list[6].integer_reference;
9880           if (attribute_flag[7] != 0)
9881             QueryColorCompliance(argument_list[7].string_reference,
9882               AllCompliance,&image->background_color,exception);
9883           image=AffineTransformImage(image,&draw_info->affine,exception);
9884           draw_info=DestroyDrawInfo(draw_info);
9885           break;
9886         }
9887         case 76:  /* Difference */
9888         {
9889           if (attribute_flag[0] == 0)
9890             {
9891               ThrowPerlException(exception,OptionError,
9892                 "ReferenceImageRequired",PackageName);
9893               goto PerlException;
9894             }
9895           if (attribute_flag[1] != 0)
9896             image->fuzz=StringToDoubleInterval(
9897               argument_list[1].string_reference,(double) QuantumRange+1.0);
9898           (void) IsImagesEqual(image,argument_list[0].image_reference,
9899             exception);
9900           break;
9901         }
9902         case 77:  /* AdaptiveThreshold */
9903         {
9904           if (attribute_flag[0] != 0)
9905             {
9906               flags=ParseGeometry(argument_list[0].string_reference,
9907                 &geometry_info);
9908               if ((flags & PercentValue) != 0)
9909                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9910             }
9911           if (attribute_flag[1] != 0)
9912             geometry_info.rho=argument_list[1].integer_reference;
9913           if (attribute_flag[2] != 0)
9914             geometry_info.sigma=argument_list[2].integer_reference;
9915           if (attribute_flag[3] != 0)
9916             geometry_info.xi=argument_list[3].integer_reference;;
9917           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9918             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9919           break;
9920         }
9921         case 78:  /* Resample */
9922         {
9923           size_t
9924             height,
9925             width;
9926
9927           if (attribute_flag[0] != 0)
9928             {
9929               flags=ParseGeometry(argument_list[0].string_reference,
9930                 &geometry_info);
9931               if ((flags & SigmaValue) == 0)
9932                 geometry_info.sigma=geometry_info.rho;
9933             }
9934           if (attribute_flag[1] != 0)
9935             geometry_info.rho=argument_list[1].real_reference;
9936           if (attribute_flag[2] != 0)
9937             geometry_info.sigma=argument_list[2].real_reference;
9938           if (attribute_flag[3] == 0)
9939             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9940           if (attribute_flag[4] == 0)
9941             SetImageArtifact(image,"filter:support",
9942               argument_list[4].string_reference);
9943           width=(size_t) (geometry_info.rho*image->columns/
9944             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9945           height=(size_t) (geometry_info.sigma*image->rows/
9946             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9947           image=ResizeImage(image,width,height,(FilterTypes)
9948             argument_list[3].integer_reference,exception);
9949           if (image != (Image *) NULL)
9950             {
9951               image->resolution.x=geometry_info.rho;
9952               image->resolution.y=geometry_info.sigma;
9953             }
9954           break;
9955         }
9956         case 79:  /* Describe */
9957         {
9958           if (attribute_flag[0] == 0)
9959             argument_list[0].file_reference=(FILE *) NULL;
9960           if (attribute_flag[1] != 0)
9961             (void) SetImageArtifact(image,"identify:features",
9962               argument_list[1].string_reference);
9963           (void) IdentifyImage(image,argument_list[0].file_reference,
9964             MagickTrue,exception);
9965           break;
9966         }
9967         case 80:  /* BlackThreshold */
9968         {
9969           if (attribute_flag[0] == 0)
9970             argument_list[0].string_reference="50%";
9971           if (attribute_flag[2] != 0)
9972             channel=(ChannelType) argument_list[2].integer_reference;
9973           channel_mask=SetImageChannelMask(image,channel);
9974           BlackThresholdImage(image,argument_list[0].string_reference,
9975             exception);
9976           (void) SetImageChannelMask(image,channel_mask);
9977           break;
9978         }
9979         case 81:  /* WhiteThreshold */
9980         {
9981           if (attribute_flag[0] == 0)
9982             argument_list[0].string_reference="50%";
9983           if (attribute_flag[2] != 0)
9984             channel=(ChannelType) argument_list[2].integer_reference;
9985           channel_mask=SetImageChannelMask(image,channel);
9986           WhiteThresholdImage(image,argument_list[0].string_reference,
9987             exception);
9988           (void) SetImageChannelMask(image,channel_mask);
9989           break;
9990         }
9991         case 82:  /* RadialBlur */
9992         {
9993           if (attribute_flag[0] != 0)
9994             {
9995               flags=ParseGeometry(argument_list[0].string_reference,
9996                 &geometry_info);
9997             }
9998           if (attribute_flag[1] != 0)
9999             geometry_info.rho=argument_list[1].real_reference;
10000           if (attribute_flag[2] != 0)
10001             channel=(ChannelType) argument_list[2].integer_reference;
10002           channel_mask=SetImageChannelMask(image,channel);
10003           image=RadialBlurImage(image,geometry_info.rho,exception);
10004           if (image != (Image *) NULL)
10005             (void) SetImageChannelMask(image,channel_mask);
10006           break;
10007         }
10008         case 83:  /* Thumbnail */
10009         {
10010           if (attribute_flag[0] != 0)
10011             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10012               &geometry,exception);
10013           if (attribute_flag[1] != 0)
10014             geometry.width=argument_list[1].integer_reference;
10015           if (attribute_flag[2] != 0)
10016             geometry.height=argument_list[2].integer_reference;
10017           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10018           break;
10019         }
10020         case 84:  /* Strip */
10021         {
10022           (void) StripImage(image,exception);
10023           break;
10024         }
10025         case 85:  /* Tint */
10026         {
10027           PixelInfo
10028             tint;
10029
10030           GetPixelInfo(image,&tint);
10031           if (attribute_flag[0] != 0)
10032             (void) QueryColorCompliance(argument_list[0].string_reference,
10033               AllCompliance,&tint,exception);
10034           if (attribute_flag[1] == 0)
10035             argument_list[1].string_reference="100";
10036           image=TintImage(image,argument_list[1].string_reference,&tint,
10037             exception);
10038           break;
10039         }
10040         case 86:  /* Channel */
10041         {
10042           if (attribute_flag[0] != 0)
10043             channel=(ChannelType) argument_list[0].integer_reference;
10044           image=SeparateImage(image,channel,exception);
10045           break;
10046         }
10047         case 87:  /* Splice */
10048         {
10049           if (attribute_flag[0] != 0)
10050             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10051               &geometry,exception);
10052           if (attribute_flag[1] != 0)
10053             geometry.width=argument_list[1].integer_reference;
10054           if (attribute_flag[2] != 0)
10055             geometry.height=argument_list[2].integer_reference;
10056           if (attribute_flag[3] != 0)
10057             geometry.x=argument_list[3].integer_reference;
10058           if (attribute_flag[4] != 0)
10059             geometry.y=argument_list[4].integer_reference;
10060           if (attribute_flag[5] != 0)
10061             image->fuzz=StringToDoubleInterval(
10062               argument_list[5].string_reference,(double) QuantumRange+1.0);
10063           if (attribute_flag[6] != 0)
10064             (void) QueryColorCompliance(argument_list[6].string_reference,
10065               AllCompliance,&image->background_color,exception);
10066           if (attribute_flag[7] != 0)
10067             image->gravity=(GravityType) argument_list[7].integer_reference;
10068           image=SpliceImage(image,&geometry,exception);
10069           break;
10070         }
10071         case 88:  /* Posterize */
10072         {
10073           if (attribute_flag[0] == 0)
10074             argument_list[0].integer_reference=3;
10075           if (attribute_flag[1] == 0)
10076             argument_list[1].integer_reference=0;
10077           (void) PosterizeImage(image,argument_list[0].integer_reference,
10078             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10079             NoDitherMethod,exception);
10080           break;
10081         }
10082         case 89:  /* Shadow */
10083         {
10084           if (attribute_flag[0] != 0)
10085             {
10086               flags=ParseGeometry(argument_list[0].string_reference,
10087                 &geometry_info);
10088               if ((flags & SigmaValue) == 0)
10089                 geometry_info.sigma=1.0;
10090               if ((flags & XiValue) == 0)
10091                 geometry_info.xi=4.0;
10092               if ((flags & PsiValue) == 0)
10093                 geometry_info.psi=4.0;
10094             }
10095           if (attribute_flag[1] != 0)
10096             geometry_info.rho=argument_list[1].real_reference;
10097           if (attribute_flag[2] != 0)
10098             geometry_info.sigma=argument_list[2].real_reference;
10099           if (attribute_flag[3] != 0)
10100             geometry_info.xi=argument_list[3].integer_reference;
10101           if (attribute_flag[4] != 0)
10102             geometry_info.psi=argument_list[4].integer_reference;
10103           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10104             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10105             ceil(geometry_info.psi-0.5),exception);
10106           break;
10107         }
10108         case 90:  /* Identify */
10109         {
10110           if (attribute_flag[0] == 0)
10111             argument_list[0].file_reference=(FILE *) NULL;
10112           if (attribute_flag[1] != 0)
10113             (void) SetImageArtifact(image,"identify:features",
10114               argument_list[1].string_reference);
10115           if ((attribute_flag[2] != 0) &&
10116               (argument_list[2].integer_reference != 0))
10117             (void) SetImageArtifact(image,"identify:unique","true");
10118           (void) IdentifyImage(image,argument_list[0].file_reference,
10119             MagickTrue,exception);
10120           break;
10121         }
10122         case 91:  /* SepiaTone */
10123         {
10124           if (attribute_flag[0] == 0)
10125             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10126           image=SepiaToneImage(image,argument_list[0].real_reference,
10127             exception);
10128           break;
10129         }
10130         case 92:  /* SigmoidalContrast */
10131         {
10132           MagickBooleanType
10133             sharpen;
10134
10135           if (attribute_flag[0] != 0)
10136             {
10137               flags=ParseGeometry(argument_list[0].string_reference,
10138                 &geometry_info);
10139               if ((flags & SigmaValue) == 0)
10140                 geometry_info.sigma=QuantumRange/2.0;
10141               if ((flags & PercentValue) != 0)
10142                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10143             }
10144           if (attribute_flag[1] != 0)
10145             geometry_info.rho=argument_list[1].real_reference;
10146           if (attribute_flag[2] != 0)
10147             geometry_info.sigma=argument_list[2].real_reference;
10148           if (attribute_flag[3] != 0)
10149             channel=(ChannelType) argument_list[3].integer_reference;
10150           sharpen=MagickTrue;
10151           if (attribute_flag[4] != 0)
10152             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10153               MagickFalse;
10154           channel_mask=SetImageChannelMask(image,channel);
10155           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10156             geometry_info.sigma,exception);
10157           (void) SetImageChannelMask(image,channel_mask);
10158           break;
10159         }
10160         case 93:  /* Extent */
10161         {
10162           if (attribute_flag[7] != 0)
10163             image->gravity=(GravityType) argument_list[7].integer_reference;
10164           if (attribute_flag[0] != 0)
10165             {
10166               int
10167                 flags;
10168
10169               flags=ParseGravityGeometry(image,
10170                 argument_list[0].string_reference,&geometry,exception);
10171               (void) flags;
10172               if (geometry.width == 0)
10173                 geometry.width=image->columns;
10174               if (geometry.height == 0)
10175                 geometry.height=image->rows;
10176             }
10177           if (attribute_flag[1] != 0)
10178             geometry.width=argument_list[1].integer_reference;
10179           if (attribute_flag[2] != 0)
10180             geometry.height=argument_list[2].integer_reference;
10181           if (attribute_flag[3] != 0)
10182             geometry.x=argument_list[3].integer_reference;
10183           if (attribute_flag[4] != 0)
10184             geometry.y=argument_list[4].integer_reference;
10185           if (attribute_flag[5] != 0)
10186             image->fuzz=StringToDoubleInterval(
10187               argument_list[5].string_reference,(double) QuantumRange+1.0);
10188           if (attribute_flag[6] != 0)
10189             (void) QueryColorCompliance(argument_list[6].string_reference,
10190               AllCompliance,&image->background_color,exception);
10191           image=ExtentImage(image,&geometry,exception);
10192           break;
10193         }
10194         case 94:  /* Vignette */
10195         {
10196           if (attribute_flag[0] != 0)
10197             {
10198               flags=ParseGeometry(argument_list[0].string_reference,
10199                 &geometry_info);
10200               if ((flags & SigmaValue) == 0)
10201                 geometry_info.sigma=1.0;
10202               if ((flags & XiValue) == 0)
10203                 geometry_info.xi=0.1*image->columns;
10204               if ((flags & PsiValue) == 0)
10205                 geometry_info.psi=0.1*image->rows;
10206             }
10207           if (attribute_flag[1] != 0)
10208             geometry_info.rho=argument_list[1].real_reference;
10209           if (attribute_flag[2] != 0)
10210             geometry_info.sigma=argument_list[2].real_reference;
10211           if (attribute_flag[3] != 0)
10212             geometry_info.xi=argument_list[3].integer_reference;
10213           if (attribute_flag[4] != 0)
10214             geometry_info.psi=argument_list[4].integer_reference;
10215           if (attribute_flag[5] != 0)
10216             (void) QueryColorCompliance(argument_list[5].string_reference,
10217               AllCompliance,&image->background_color,exception);
10218           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10219             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10220             ceil(geometry_info.psi-0.5),exception);
10221           break;
10222         }
10223         case 95:  /* ContrastStretch */
10224         {
10225           double
10226             black_point,
10227             white_point;
10228
10229           black_point=0.0;
10230           white_point=(double) image->columns*image->rows;
10231           if (attribute_flag[0] != 0)
10232             {
10233               flags=ParseGeometry(argument_list[0].string_reference,
10234                 &geometry_info);
10235               black_point=geometry_info.rho;
10236               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10237                 black_point;
10238               if ((flags & PercentValue) != 0)
10239                 {
10240                   black_point*=(double) image->columns*image->rows/100.0;
10241                   white_point*=(double) image->columns*image->rows/100.0;
10242                 }
10243               white_point=(double) image->columns*image->rows-
10244                 white_point;
10245             }
10246           if (attribute_flag[1] != 0)
10247             black_point=argument_list[1].real_reference;
10248           if (attribute_flag[2] != 0)
10249             white_point=argument_list[2].real_reference;
10250           if (attribute_flag[4] != 0)
10251             channel=(ChannelType) argument_list[4].integer_reference;
10252           channel_mask=SetImageChannelMask(image,channel);
10253           (void) ContrastStretchImage(image,black_point,white_point,exception);
10254           (void) SetImageChannelMask(image,channel_mask);
10255           break;
10256         }
10257         case 96:  /* Sans0 */
10258         {
10259           break;
10260         }
10261         case 97:  /* Sans1 */
10262         {
10263           break;
10264         }
10265         case 98:  /* AdaptiveSharpen */
10266         {
10267           if (attribute_flag[0] != 0)
10268             {
10269               flags=ParseGeometry(argument_list[0].string_reference,
10270                 &geometry_info);
10271               if ((flags & SigmaValue) == 0)
10272                 geometry_info.sigma=1.0;
10273               if ((flags & XiValue) == 0)
10274                 geometry_info.xi=0.0;
10275             }
10276           if (attribute_flag[1] != 0)
10277             geometry_info.rho=argument_list[1].real_reference;
10278           if (attribute_flag[2] != 0)
10279             geometry_info.sigma=argument_list[2].real_reference;
10280           if (attribute_flag[3] != 0)
10281             geometry_info.xi=argument_list[3].real_reference;
10282           if (attribute_flag[4] != 0)
10283             channel=(ChannelType) argument_list[4].integer_reference;
10284           channel_mask=SetImageChannelMask(image,channel);
10285           image=AdaptiveSharpenImage(image,geometry_info.rho,
10286             geometry_info.sigma,exception);
10287           if (image != (Image *) NULL)
10288             (void) SetImageChannelMask(image,channel_mask);
10289           break;
10290         }
10291         case 99:  /* Transpose */
10292         {
10293           image=TransposeImage(image,exception);
10294           break;
10295         }
10296         case 100:  /* Tranverse */
10297         {
10298           image=TransverseImage(image,exception);
10299           break;
10300         }
10301         case 101:  /* AutoOrient */
10302         {
10303           image=AutoOrientImage(image,image->orientation,exception);
10304           break;
10305         }
10306         case 102:  /* AdaptiveBlur */
10307         {
10308           if (attribute_flag[0] != 0)
10309             {
10310               flags=ParseGeometry(argument_list[0].string_reference,
10311                 &geometry_info);
10312               if ((flags & SigmaValue) == 0)
10313                 geometry_info.sigma=1.0;
10314               if ((flags & XiValue) == 0)
10315                 geometry_info.xi=0.0;
10316             }
10317           if (attribute_flag[1] != 0)
10318             geometry_info.rho=argument_list[1].real_reference;
10319           if (attribute_flag[2] != 0)
10320             geometry_info.sigma=argument_list[2].real_reference;
10321           if (attribute_flag[3] != 0)
10322             channel=(ChannelType) argument_list[3].integer_reference;
10323           channel_mask=SetImageChannelMask(image,channel);
10324           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10325             exception);
10326           if (image != (Image *) NULL)
10327             (void) SetImageChannelMask(image,channel_mask);
10328           break;
10329         }
10330         case 103:  /* Sketch */
10331         {
10332           if (attribute_flag[0] != 0)
10333             {
10334               flags=ParseGeometry(argument_list[0].string_reference,
10335                 &geometry_info);
10336               if ((flags & SigmaValue) == 0)
10337                 geometry_info.sigma=1.0;
10338               if ((flags & XiValue) == 0)
10339                 geometry_info.xi=1.0;
10340             }
10341           if (attribute_flag[1] != 0)
10342             geometry_info.rho=argument_list[1].real_reference;
10343           if (attribute_flag[2] != 0)
10344             geometry_info.sigma=argument_list[2].real_reference;
10345           if (attribute_flag[3] != 0)
10346             geometry_info.xi=argument_list[3].real_reference;
10347           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10348             geometry_info.xi,exception);
10349           break;
10350         }
10351         case 104:  /* UniqueColors */
10352         {
10353           image=UniqueImageColors(image,exception);
10354           break;
10355         }
10356         case 105:  /* AdaptiveResize */
10357         {
10358           if (attribute_flag[0] != 0)
10359             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10360               &geometry,exception);
10361           if (attribute_flag[1] != 0)
10362             geometry.width=argument_list[1].integer_reference;
10363           if (attribute_flag[2] != 0)
10364             geometry.height=argument_list[2].integer_reference;
10365           if (attribute_flag[3] != 0)
10366             image->filter=(FilterTypes) argument_list[4].integer_reference;
10367           if (attribute_flag[4] != 0)
10368             SetImageArtifact(image,"filter:support",
10369               argument_list[4].string_reference);
10370           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10371             exception);
10372           break;
10373         }
10374         case 106:  /* ClipMask */
10375         {
10376           Image
10377             *mask_image;
10378
10379           if (attribute_flag[0] == 0)
10380             {
10381               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10382                 PackageName);
10383               goto PerlException;
10384             }
10385           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10386             exception);
10387           (void) SetImageMask(image,mask_image,exception);
10388           mask_image=DestroyImage(mask_image);
10389           break;
10390         }
10391         case 107:  /* LinearStretch */
10392         {
10393            double
10394              black_point,
10395              white_point;
10396
10397            black_point=0.0;
10398            white_point=(double) image->columns*image->rows;
10399            if (attribute_flag[0] != 0)
10400              {
10401                flags=ParseGeometry(argument_list[0].string_reference,
10402                  &geometry_info);
10403                if ((flags & SigmaValue) != 0)
10404                   white_point=geometry_info.sigma;
10405                if ((flags & PercentValue) != 0)
10406                  {
10407                    black_point*=(double) image->columns*image->rows/100.0;
10408                    white_point*=(double) image->columns*image->rows/100.0;
10409                  }
10410                if ((flags & SigmaValue) == 0)
10411                  white_point=(double) image->columns*image->rows-black_point;
10412              }
10413           if (attribute_flag[1] != 0)
10414             black_point=argument_list[1].real_reference;
10415           if (attribute_flag[2] != 0)
10416             white_point=argument_list[2].real_reference;
10417           (void) LinearStretchImage(image,black_point,white_point,exception);
10418           break;
10419         }
10420         case 108:  /* ColorMatrix */
10421         {
10422           AV
10423             *av;
10424
10425           double
10426             *color_matrix;
10427
10428           KernelInfo
10429             *kernel_info;
10430
10431           size_t
10432             order;
10433
10434           if (attribute_flag[0] == 0)
10435             break;
10436           av=(AV *) argument_list[0].array_reference;
10437           order=(size_t) sqrt(av_len(av)+1);
10438           color_matrix=(double *) AcquireQuantumMemory(order,order*
10439             sizeof(*color_matrix));
10440           if (color_matrix == (double *) NULL)
10441             {
10442               ThrowPerlException(exception,ResourceLimitFatalError,
10443                 "MemoryAllocationFailed",PackageName);
10444               goto PerlException;
10445            }
10446           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10447             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10448           for ( ; j < (ssize_t) (order*order); j++)
10449             color_matrix[j]=0.0;
10450           kernel_info=AcquireKernelInfo((const char *) NULL);
10451           if (kernel_info == (KernelInfo *) NULL)
10452             break;
10453           kernel_info->width=order;
10454           kernel_info->height=order;
10455           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10456             order*sizeof(*kernel_info->values));
10457           if (kernel_info->values != (MagickRealType *) NULL)
10458             {
10459               for (i=0; i < (ssize_t) (order*order); i++)
10460                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10461               image=ColorMatrixImage(image,kernel_info,exception);
10462             }
10463           kernel_info=DestroyKernelInfo(kernel_info);
10464           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10465           break;
10466         }
10467         case 109:  /* Mask */
10468         {
10469           Image
10470             *mask_image;
10471
10472           if (attribute_flag[0] == 0)
10473             {
10474               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10475                 PackageName);
10476               goto PerlException;
10477             }
10478           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10479             MagickTrue,exception);
10480           (void) SetImageMask(image,mask_image,exception);
10481           mask_image=DestroyImage(mask_image);
10482           break;
10483         }
10484         case 110:  /* Polaroid */
10485         {
10486           char
10487             *caption;
10488
10489           DrawInfo
10490             *draw_info;
10491
10492           double
10493             angle;
10494
10495           PixelInterpolateMethod
10496             method;
10497
10498           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10499             (DrawInfo *) NULL);
10500           caption=(char *) NULL;
10501           if (attribute_flag[0] != 0)
10502             caption=InterpretImageProperties(info ? info->image_info :
10503               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10504               exception);
10505           angle=0.0;
10506           if (attribute_flag[1] != 0)
10507             angle=argument_list[1].real_reference;
10508           if (attribute_flag[2] != 0)
10509             (void) CloneString(&draw_info->font,
10510               argument_list[2].string_reference);
10511           if (attribute_flag[3] != 0)
10512             (void) QueryColorCompliance(argument_list[3].string_reference,
10513               AllCompliance,&draw_info->stroke,exception);
10514           if (attribute_flag[4] != 0)
10515             (void) QueryColorCompliance(argument_list[4].string_reference,
10516               AllCompliance,&draw_info->fill,exception);
10517           if (attribute_flag[5] != 0)
10518             draw_info->stroke_width=argument_list[5].real_reference;
10519           if (attribute_flag[6] != 0)
10520             draw_info->pointsize=argument_list[6].real_reference;
10521           if (attribute_flag[7] != 0)
10522             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10523           if (attribute_flag[8] != 0)
10524             (void) QueryColorCompliance(argument_list[8].string_reference,
10525               AllCompliance,&image->background_color,exception);
10526           method=UndefinedInterpolatePixel;
10527           if (attribute_flag[9] != 0)
10528             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10529           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10530           draw_info=DestroyDrawInfo(draw_info);
10531           if (caption != (char *) NULL)
10532             caption=DestroyString(caption);
10533           break;
10534         }
10535         case 111:  /* FloodfillPaint */
10536         {
10537           DrawInfo
10538             *draw_info;
10539
10540           MagickBooleanType
10541             invert;
10542
10543           PixelInfo
10544             target;
10545
10546           draw_info=CloneDrawInfo(info ? info->image_info :
10547             (ImageInfo *) NULL,(DrawInfo *) NULL);
10548           if (attribute_flag[0] != 0)
10549             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10550               &geometry,exception);
10551           if (attribute_flag[1] != 0)
10552             geometry.x=argument_list[1].integer_reference;
10553           if (attribute_flag[2] != 0)
10554             geometry.y=argument_list[2].integer_reference;
10555           if (attribute_flag[3] != 0)
10556             (void) QueryColorCompliance(argument_list[3].string_reference,
10557               AllCompliance,&draw_info->fill,exception);
10558           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10559             geometry.x,geometry.y,&target,exception);
10560           if (attribute_flag[4] != 0)
10561             QueryColorCompliance(argument_list[4].string_reference,
10562               AllCompliance,&target,exception);
10563           if (attribute_flag[5] != 0)
10564             image->fuzz=StringToDoubleInterval(
10565               argument_list[5].string_reference,(double) QuantumRange+1.0);
10566           if (attribute_flag[6] != 0)
10567             channel=(ChannelType) argument_list[6].integer_reference;
10568           invert=MagickFalse;
10569           if (attribute_flag[7] != 0)
10570             invert=(MagickBooleanType) argument_list[7].integer_reference;
10571           channel_mask=SetImageChannelMask(image,channel);
10572           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10573             geometry.y,invert,exception);
10574           (void) SetImageChannelMask(image,channel_mask);
10575           draw_info=DestroyDrawInfo(draw_info);
10576           break;
10577         }
10578         case 112:  /* Distort */
10579         {
10580           AV
10581             *av;
10582
10583           double
10584             *coordinates;
10585
10586           DistortImageMethod
10587             method;
10588
10589           size_t
10590             number_coordinates;
10591
10592           VirtualPixelMethod
10593             virtual_pixel;
10594
10595           if (attribute_flag[0] == 0)
10596             break;
10597           method=UndefinedDistortion;
10598           if (attribute_flag[1] != 0)
10599             method=(DistortImageMethod) argument_list[1].integer_reference;
10600           av=(AV *) argument_list[0].array_reference;
10601           number_coordinates=(size_t) av_len(av)+1;
10602           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10603             sizeof(*coordinates));
10604           if (coordinates == (double *) NULL)
10605             {
10606               ThrowPerlException(exception,ResourceLimitFatalError,
10607                 "MemoryAllocationFailed",PackageName);
10608               goto PerlException;
10609             }
10610           for (j=0; j < (ssize_t) number_coordinates; j++)
10611             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10612           virtual_pixel=UndefinedVirtualPixelMethod;
10613           if (attribute_flag[2] != 0)
10614             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10615               argument_list[2].integer_reference,exception);
10616           image=DistortImage(image,method,number_coordinates,coordinates,
10617             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10618             exception);
10619           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10620             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10621               exception);
10622           coordinates=(double *) RelinquishMagickMemory(coordinates);
10623           break;
10624         }
10625         case 113:  /* Clut */
10626         {
10627           PixelInterpolateMethod
10628             method;
10629
10630           if (attribute_flag[0] == 0)
10631             {
10632               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10633                 PackageName);
10634               goto PerlException;
10635             }
10636           method=UndefinedInterpolatePixel;
10637           if (attribute_flag[1] != 0)
10638             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10639           if (attribute_flag[2] != 0)
10640             channel=(ChannelType) argument_list[2].integer_reference;
10641           channel_mask=SetImageChannelMask(image,channel);
10642           (void) ClutImage(image,argument_list[0].image_reference,method,
10643             exception);
10644           (void) SetImageChannelMask(image,channel_mask);
10645           break;
10646         }
10647         case 114:  /* LiquidRescale */
10648         {
10649           if (attribute_flag[0] != 0)
10650             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10651               &geometry,exception);
10652           if (attribute_flag[1] != 0)
10653             geometry.width=argument_list[1].integer_reference;
10654           if (attribute_flag[2] != 0)
10655             geometry.height=argument_list[2].integer_reference;
10656           if (attribute_flag[3] == 0)
10657             argument_list[3].real_reference=1.0;
10658           if (attribute_flag[4] == 0)
10659             argument_list[4].real_reference=0.0;
10660           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10661             argument_list[3].real_reference,argument_list[4].real_reference,
10662             exception);
10663           break;
10664         }
10665         case 115:  /* EncipherImage */
10666         {
10667           (void) EncipherImage(image,argument_list[0].string_reference,
10668             exception);
10669           break;
10670         }
10671         case 116:  /* DecipherImage */
10672         {
10673           (void) DecipherImage(image,argument_list[0].string_reference,
10674             exception);
10675           break;
10676         }
10677         case 117:  /* Deskew */
10678         {
10679           geometry_info.rho=QuantumRange/2.0;
10680           if (attribute_flag[0] != 0)
10681             flags=ParseGeometry(argument_list[0].string_reference,
10682               &geometry_info);
10683           if (attribute_flag[1] != 0)
10684             geometry_info.rho=StringToDoubleInterval(
10685               argument_list[1].string_reference,(double) QuantumRange+1.0);
10686           image=DeskewImage(image,geometry_info.rho,exception);
10687           break;
10688         }
10689         case 118:  /* Remap */
10690         {
10691           QuantizeInfo
10692             *quantize_info;
10693
10694           if (attribute_flag[0] == 0)
10695             {
10696               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10697                 PackageName);
10698               goto PerlException;
10699             }
10700           quantize_info=AcquireQuantizeInfo(info->image_info);
10701           if (attribute_flag[1] != 0)
10702             quantize_info->dither_method=(DitherMethod)
10703               argument_list[1].integer_reference;
10704           (void) RemapImages(quantize_info,image,
10705             argument_list[0].image_reference,exception);
10706           quantize_info=DestroyQuantizeInfo(quantize_info);
10707           break;
10708         }
10709         case 119:  /* SparseColor */
10710         {
10711           AV
10712             *av;
10713
10714           double
10715             *coordinates;
10716
10717           SparseColorMethod
10718             method;
10719
10720           size_t
10721             number_coordinates;
10722
10723           VirtualPixelMethod
10724             virtual_pixel;
10725
10726           if (attribute_flag[0] == 0)
10727             break;
10728           method=UndefinedColorInterpolate;
10729           if (attribute_flag[1] != 0)
10730             method=(SparseColorMethod) argument_list[1].integer_reference;
10731           av=(AV *) argument_list[0].array_reference;
10732           number_coordinates=(size_t) av_len(av)+1;
10733           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10734             sizeof(*coordinates));
10735           if (coordinates == (double *) NULL)
10736             {
10737               ThrowPerlException(exception,ResourceLimitFatalError,
10738                 "MemoryAllocationFailed",PackageName);
10739               goto PerlException;
10740             }
10741           for (j=0; j < (ssize_t) number_coordinates; j++)
10742             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10743           virtual_pixel=UndefinedVirtualPixelMethod;
10744           if (attribute_flag[2] != 0)
10745             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10746               argument_list[2].integer_reference,exception);
10747           if (attribute_flag[3] != 0)
10748             channel=(ChannelType) argument_list[3].integer_reference;
10749           channel_mask=SetImageChannelMask(image,channel);
10750           image=SparseColorImage(image,method,number_coordinates,coordinates,
10751             exception);
10752           if (image != (Image *) NULL)
10753             (void) SetImageChannelMask(image,channel_mask);
10754           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10755             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10756               exception);
10757           coordinates=(double *) RelinquishMagickMemory(coordinates);
10758           break;
10759         }
10760         case 120:  /* Function */
10761         {
10762           AV
10763             *av;
10764
10765           double
10766             *parameters;
10767
10768           MagickFunction
10769             function;
10770
10771           size_t
10772             number_parameters;
10773
10774           VirtualPixelMethod
10775             virtual_pixel;
10776
10777           if (attribute_flag[0] == 0)
10778             break;
10779           function=UndefinedFunction;
10780           if (attribute_flag[1] != 0)
10781             function=(MagickFunction) argument_list[1].integer_reference;
10782           av=(AV *) argument_list[0].array_reference;
10783           number_parameters=(size_t) av_len(av)+1;
10784           parameters=(double *) AcquireQuantumMemory(number_parameters,
10785             sizeof(*parameters));
10786           if (parameters == (double *) NULL)
10787             {
10788               ThrowPerlException(exception,ResourceLimitFatalError,
10789                 "MemoryAllocationFailed",PackageName);
10790               goto PerlException;
10791             }
10792           for (j=0; j < (ssize_t) number_parameters; j++)
10793             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10794           virtual_pixel=UndefinedVirtualPixelMethod;
10795           if (attribute_flag[2] != 0)
10796             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10797               argument_list[2].integer_reference,exception);
10798           (void) FunctionImage(image,function,number_parameters,parameters,
10799             exception);
10800           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10801             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10802               exception);
10803           parameters=(double *) RelinquishMagickMemory(parameters);
10804           break;
10805         }
10806         case 121:  /* SelectiveBlur */
10807         {
10808           if (attribute_flag[0] != 0)
10809             {
10810               flags=ParseGeometry(argument_list[0].string_reference,
10811                 &geometry_info);
10812               if ((flags & SigmaValue) == 0)
10813                 geometry_info.sigma=1.0;
10814               if ((flags & PercentValue) != 0)
10815                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10816             }
10817           if (attribute_flag[1] != 0)
10818             geometry_info.rho=argument_list[1].real_reference;
10819           if (attribute_flag[2] != 0)
10820             geometry_info.sigma=argument_list[2].real_reference;
10821           if (attribute_flag[3] != 0)
10822             geometry_info.xi=argument_list[3].integer_reference;;
10823           if (attribute_flag[5] != 0)
10824             channel=(ChannelType) argument_list[5].integer_reference;
10825           channel_mask=SetImageChannelMask(image,channel);
10826           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10827             geometry_info.xi,exception);
10828           if (image != (Image *) NULL)
10829             (void) SetImageChannelMask(image,channel_mask);
10830           break;
10831         }
10832         case 122:  /* HaldClut */
10833         {
10834           if (attribute_flag[0] == 0)
10835             {
10836               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10837                 PackageName);
10838               goto PerlException;
10839             }
10840           if (attribute_flag[1] != 0)
10841             channel=(ChannelType) argument_list[1].integer_reference;
10842           channel_mask=SetImageChannelMask(image,channel);
10843           (void) HaldClutImage(image,argument_list[0].image_reference,
10844             exception);
10845           (void) SetImageChannelMask(image,channel_mask);
10846           break;
10847         }
10848         case 123:  /* BlueShift */
10849         {
10850           if (attribute_flag[0] != 0)
10851             (void) ParseGeometry(argument_list[0].string_reference,
10852               &geometry_info);
10853           image=BlueShiftImage(image,geometry_info.rho,exception);
10854           break;
10855         }
10856         case 124:  /* ForwardFourierTransformImage */
10857         {
10858           image=ForwardFourierTransformImage(image,
10859             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10860             exception);
10861           break;
10862         }
10863         case 125:  /* InverseFourierTransformImage */
10864         {
10865           image=InverseFourierTransformImage(image,image->next,
10866             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10867             exception);
10868           break;
10869         }
10870         case 126:  /* ColorDecisionList */
10871         {
10872           if (attribute_flag[0] == 0)
10873             argument_list[0].string_reference=(char *) NULL;
10874           (void) ColorDecisionListImage(image,
10875             argument_list[0].string_reference,exception);
10876           break;
10877         }
10878         case 127:  /* AutoGamma */
10879         {
10880           if (attribute_flag[0] != 0)
10881             channel=(ChannelType) argument_list[0].integer_reference;
10882           channel_mask=SetImageChannelMask(image,channel);
10883           (void) AutoGammaImage(image,exception);
10884           (void) SetImageChannelMask(image,channel_mask);
10885           break;
10886         }
10887         case 128:  /* AutoLevel */
10888         {
10889           if (attribute_flag[0] != 0)
10890             channel=(ChannelType) argument_list[0].integer_reference;
10891           channel_mask=SetImageChannelMask(image,channel);
10892           (void) AutoLevelImage(image,exception);
10893           (void) SetImageChannelMask(image,channel_mask);
10894           break;
10895         }
10896         case 129:  /* LevelColors */
10897         {
10898           PixelInfo
10899             black_point,
10900             white_point;
10901
10902           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10903             exception);
10904           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10905             exception);
10906           if (attribute_flag[1] != 0)
10907              (void) QueryColorCompliance(
10908                argument_list[1].string_reference,AllCompliance,&black_point,
10909                exception);
10910           if (attribute_flag[2] != 0)
10911              (void) QueryColorCompliance(
10912                argument_list[2].string_reference,AllCompliance,&white_point,
10913                exception);
10914           if (attribute_flag[3] != 0)
10915             channel=(ChannelType) argument_list[3].integer_reference;
10916           channel_mask=SetImageChannelMask(image,channel);
10917           (void) LevelImageColors(image,&black_point,&white_point,
10918             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10919             exception);
10920           (void) SetImageChannelMask(image,channel_mask);
10921           break;
10922         }
10923         case 130:  /* Clamp */
10924         {
10925           if (attribute_flag[0] != 0)
10926             channel=(ChannelType) argument_list[0].integer_reference;
10927           channel_mask=SetImageChannelMask(image,channel);
10928           (void) ClampImage(image,exception);
10929           (void) SetImageChannelMask(image,channel_mask);
10930           break;
10931         }
10932         case 131:  /* BrightnessContrast */
10933         {
10934           double
10935             brightness,
10936             contrast;
10937
10938           brightness=0.0;
10939           contrast=0.0;
10940           if (attribute_flag[0] != 0)
10941             {
10942               flags=ParseGeometry(argument_list[0].string_reference,
10943                 &geometry_info);
10944               brightness=geometry_info.rho;
10945               if ((flags & SigmaValue) == 0)
10946                 contrast=geometry_info.sigma;
10947             }
10948           if (attribute_flag[1] != 0)
10949             brightness=argument_list[1].real_reference;
10950           if (attribute_flag[2] != 0)
10951             contrast=argument_list[2].real_reference;
10952           if (attribute_flag[4] != 0)
10953             channel=(ChannelType) argument_list[4].integer_reference;
10954           channel_mask=SetImageChannelMask(image,channel);
10955           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10956           (void) SetImageChannelMask(image,channel_mask);
10957           break;
10958         }
10959         case 132:  /* Morphology */
10960         {
10961           KernelInfo
10962             *kernel;
10963
10964           MorphologyMethod
10965             method;
10966
10967           ssize_t
10968             iterations;
10969
10970           if (attribute_flag[0] == 0)
10971             break;
10972           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10973           if (kernel == (KernelInfo *) NULL)
10974             break;
10975           if (attribute_flag[1] != 0)
10976             channel=(ChannelType) argument_list[1].integer_reference;
10977           method=UndefinedMorphology;
10978           if (attribute_flag[2] != 0)
10979             method=argument_list[2].integer_reference;
10980           iterations=1;
10981           if (attribute_flag[3] != 0)
10982             iterations=argument_list[3].integer_reference;
10983           channel_mask=SetImageChannelMask(image,channel);
10984           image=MorphologyImage(image,method,iterations,kernel,exception);
10985           if (image != (Image *) NULL)
10986             (void) SetImageChannelMask(image,channel_mask);
10987           kernel=DestroyKernelInfo(kernel);
10988           break;
10989         }
10990         case 133:  /* Mode */
10991         {
10992           if (attribute_flag[0] != 0)
10993             {
10994               flags=ParseGeometry(argument_list[0].string_reference,
10995                 &geometry_info);
10996               if ((flags & SigmaValue) == 0)
10997                 geometry_info.sigma=1.0;
10998             }
10999           if (attribute_flag[1] != 0)
11000             geometry_info.rho=argument_list[1].real_reference;
11001           if (attribute_flag[2] != 0)
11002             geometry_info.sigma=argument_list[2].real_reference;
11003           if (attribute_flag[3] != 0)
11004             channel=(ChannelType) argument_list[3].integer_reference;
11005           channel_mask=SetImageChannelMask(image,channel);
11006           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11007             (size_t) geometry_info.sigma,exception);
11008           if (image != (Image *) NULL)
11009             (void) SetImageChannelMask(image,channel_mask);
11010           break;
11011         }
11012         case 134:  /* Statistic */
11013         {
11014           StatisticType
11015             statistic;
11016
11017           statistic=UndefinedStatistic;
11018           if (attribute_flag[0] != 0)
11019             {
11020               flags=ParseGeometry(argument_list[0].string_reference,
11021                 &geometry_info);
11022               if ((flags & SigmaValue) == 0)
11023                 geometry_info.sigma=1.0;
11024             }
11025           if (attribute_flag[1] != 0)
11026             geometry_info.rho=argument_list[1].real_reference;
11027           if (attribute_flag[2] != 0)
11028             geometry_info.sigma=argument_list[2].real_reference;
11029           if (attribute_flag[3] != 0)
11030             channel=(ChannelType) argument_list[3].integer_reference;
11031           if (attribute_flag[4] != 0)
11032             statistic=(StatisticType) argument_list[4].integer_reference;
11033           channel_mask=SetImageChannelMask(image,channel);
11034           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11035             (size_t) geometry_info.sigma,exception);
11036           if (image != (Image *) NULL)
11037             (void) SetImageChannelMask(image,channel_mask);
11038           break;
11039         }
11040         case 135:  /* Perceptible */
11041         {
11042           double
11043             epsilon;
11044
11045           epsilon=MagickEpsilon;
11046           if (attribute_flag[0] != 0)
11047             epsilon=argument_list[0].real_reference;
11048           if (attribute_flag[1] != 0)
11049             channel=(ChannelType) argument_list[1].integer_reference;
11050           channel_mask=SetImageChannelMask(image,channel);
11051           (void) PerceptibleImage(image,epsilon,exception);
11052           (void) SetImageChannelMask(image,channel_mask);
11053           break;
11054         }
11055         case 136:  /* Poly */
11056         {
11057           AV
11058             *av;
11059
11060           double
11061             *terms;
11062
11063           size_t
11064             number_terms;
11065
11066           if (attribute_flag[0] == 0)
11067             break;
11068           if (attribute_flag[1] != 0)
11069             channel=(ChannelType) argument_list[1].integer_reference;
11070           av=(AV *) argument_list[0].array_reference;
11071           number_terms=(size_t) av_len(av);
11072           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11073           if (terms == (double *) NULL)
11074             {
11075               ThrowPerlException(exception,ResourceLimitFatalError,
11076                 "MemoryAllocationFailed",PackageName);
11077               goto PerlException;
11078             }
11079           for (j=0; j < av_len(av); j++)
11080             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11081           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11082           terms=(double *) RelinquishMagickMemory(terms);
11083           break;
11084         }
11085         case 137:  /* Grayscale */
11086         {
11087           PixelIntensityMethod
11088             method;
11089
11090           method=UndefinedPixelIntensityMethod;
11091           if (attribute_flag[0] != 0)
11092             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11093           (void) GrayscaleImage(image,method,exception);
11094           break;
11095         }
11096       }
11097       if (next != (Image *) NULL)
11098         (void) CatchImageException(next);
11099       if (region_image != (Image *) NULL)
11100         {
11101           /*
11102             Composite region.
11103           */
11104           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11105             region_info.x,region_info.y,exception);
11106           (void) status;
11107           (void) CatchImageException(region_image);
11108           image=DestroyImage(image);
11109           image=region_image;
11110         }
11111       if (image != (Image *) NULL)
11112         {
11113           number_images++;
11114           if (next && (next != image))
11115             {
11116               image->next=next->next;
11117               if (image->next != (Image *) NULL)
11118                 image->next->previous=image;
11119               DeleteImageFromRegistry(*pv,next);
11120             }
11121           sv_setiv(*pv,PTR2IV(image));
11122           next=image;
11123         }
11124       if (*pv)
11125         pv++;
11126     }
11127
11128   PerlException:
11129     if (reference_vector)
11130       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11131     InheritPerlException(exception,perl_exception);
11132     exception=DestroyExceptionInfo(exception);
11133     sv_setiv(perl_exception,(IV) number_images);
11134     SvPOK_on(perl_exception);
11135     ST(0)=sv_2mortal(perl_exception);
11136     XSRETURN(1);
11137   }
11138 \f
11139 #
11140 ###############################################################################
11141 #                                                                             #
11142 #                                                                             #
11143 #                                                                             #
11144 #   M o n t a g e                                                             #
11145 #                                                                             #
11146 #                                                                             #
11147 #                                                                             #
11148 ###############################################################################
11149 #
11150 #
11151 void
11152 Montage(ref,...)
11153   Image::Magick ref=NO_INIT
11154   ALIAS:
11155     MontageImage  = 1
11156     montage       = 2
11157     montageimage  = 3
11158   PPCODE:
11159   {
11160     AV
11161       *av;
11162
11163     char
11164       *attribute;
11165
11166     ExceptionInfo
11167       *exception;
11168
11169     HV
11170       *hv;
11171
11172     Image
11173       *image,
11174       *next;
11175
11176     PixelInfo
11177       transparent_color;
11178
11179     MontageInfo
11180       *montage_info;
11181
11182     register ssize_t
11183       i;
11184
11185     ssize_t
11186       sp;
11187
11188     struct PackageInfo
11189       *info;
11190
11191     SV
11192       *av_reference,
11193       *perl_exception,
11194       *reference,
11195       *rv,
11196       *sv;
11197
11198     PERL_UNUSED_VAR(ref);
11199     PERL_UNUSED_VAR(ix);
11200     exception=AcquireExceptionInfo();
11201     perl_exception=newSVpv("",0);
11202     sv=NULL;
11203     attribute=NULL;
11204     if (sv_isobject(ST(0)) == 0)
11205       {
11206         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11207           PackageName);
11208         goto PerlException;
11209       }
11210     reference=SvRV(ST(0));
11211     hv=SvSTASH(reference);
11212     av=newAV();
11213     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11214     SvREFCNT_dec(av);
11215     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11216     if (image == (Image *) NULL)
11217       {
11218         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11219           PackageName);
11220         goto PerlException;
11221       }
11222     /*
11223       Get options.
11224     */
11225     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11226     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11227     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11228       exception);
11229     for (i=2; i < items; i+=2)
11230     {
11231       attribute=(char *) SvPV(ST(i-1),na);
11232       switch (*attribute)
11233       {
11234         case 'B':
11235         case 'b':
11236         {
11237           if (LocaleCompare(attribute,"background") == 0)
11238             {
11239               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11240                 &montage_info->background_color,exception);
11241               for (next=image; next; next=next->next)
11242                 next->background_color=montage_info->background_color;
11243               break;
11244             }
11245           if (LocaleCompare(attribute,"border") == 0)
11246             {
11247               montage_info->border_width=SvIV(ST(i));
11248               break;
11249             }
11250           if (LocaleCompare(attribute,"bordercolor") == 0)
11251             {
11252               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11253                 &montage_info->border_color,exception);
11254               for (next=image; next; next=next->next)
11255                 next->border_color=montage_info->border_color;
11256               break;
11257             }
11258           if (LocaleCompare(attribute,"borderwidth") == 0)
11259             {
11260               montage_info->border_width=SvIV(ST(i));
11261               break;
11262             }
11263           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11264             attribute);
11265           break;
11266         }
11267         case 'C':
11268         case 'c':
11269         {
11270           if (LocaleCompare(attribute,"compose") == 0)
11271             {
11272               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11273                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11274               if (sp < 0)
11275                 {
11276                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11277                     SvPV(ST(i),na));
11278                   break;
11279                 }
11280               for (next=image; next; next=next->next)
11281                 next->compose=(CompositeOperator) sp;
11282               break;
11283             }
11284           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11285             attribute);
11286           break;
11287         }
11288         case 'F':
11289         case 'f':
11290         {
11291           if (LocaleCompare(attribute,"fill") == 0)
11292             {
11293               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11294                 &montage_info->fill,exception);
11295               break;
11296             }
11297           if (LocaleCompare(attribute,"font") == 0)
11298             {
11299               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11300               break;
11301             }
11302           if (LocaleCompare(attribute,"frame") == 0)
11303             {
11304               char
11305                 *p;
11306
11307               p=SvPV(ST(i),na);
11308               if (IsGeometry(p) == MagickFalse)
11309                 {
11310                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11311                     p);
11312                   break;
11313                 }
11314               (void) CloneString(&montage_info->frame,p);
11315               if (*p == '\0')
11316                 montage_info->frame=(char *) NULL;
11317               break;
11318             }
11319           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11320             attribute);
11321           break;
11322         }
11323         case 'G':
11324         case 'g':
11325         {
11326           if (LocaleCompare(attribute,"geometry") == 0)
11327             {
11328               char
11329                 *p;
11330
11331               p=SvPV(ST(i),na);
11332               if (IsGeometry(p) == MagickFalse)
11333                 {
11334                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11335                     p);
11336                   break;
11337                 }
11338              (void) CloneString(&montage_info->geometry,p);
11339              if (*p == '\0')
11340                montage_info->geometry=(char *) NULL;
11341              break;
11342            }
11343          if (LocaleCompare(attribute,"gravity") == 0)
11344            {
11345              ssize_t
11346                in;
11347
11348              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11349                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11350              if (in < 0)
11351                {
11352                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11353                    SvPV(ST(i),na));
11354                  return;
11355                }
11356              montage_info->gravity=(GravityType) in;
11357              for (next=image; next; next=next->next)
11358                next->gravity=(GravityType) in;
11359              break;
11360            }
11361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11362             attribute);
11363           break;
11364         }
11365         case 'L':
11366         case 'l':
11367         {
11368           if (LocaleCompare(attribute,"label") == 0)
11369             {
11370               for (next=image; next; next=next->next)
11371                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11372                   info ? info->image_info : (ImageInfo *) NULL,next,
11373                   SvPV(ST(i),na),exception),exception);
11374               break;
11375             }
11376           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11377             attribute);
11378           break;
11379         }
11380         case 'M':
11381         case 'm':
11382         {
11383           if (LocaleCompare(attribute,"mattecolor") == 0)
11384             {
11385               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11386                 &montage_info->matte_color,exception);
11387               for (next=image; next; next=next->next)
11388                 next->matte_color=montage_info->matte_color;
11389               break;
11390             }
11391           if (LocaleCompare(attribute,"mode") == 0)
11392             {
11393               ssize_t
11394                 in;
11395
11396               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11397                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11398               switch (in)
11399               {
11400                 default:
11401                 {
11402                   ThrowPerlException(exception,OptionError,
11403                     "UnrecognizedModeType",SvPV(ST(i),na));
11404                   break;
11405                 }
11406                 case FrameMode:
11407                 {
11408                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11409                   montage_info->shadow=MagickTrue;
11410                   break;
11411                 }
11412                 case UnframeMode:
11413                 {
11414                   montage_info->frame=(char *) NULL;
11415                   montage_info->shadow=MagickFalse;
11416                   montage_info->border_width=0;
11417                   break;
11418                 }
11419                 case ConcatenateMode:
11420                 {
11421                   montage_info->frame=(char *) NULL;
11422                   montage_info->shadow=MagickFalse;
11423                   (void) CloneString(&montage_info->geometry,"+0+0");
11424                   montage_info->border_width=0;
11425                 }
11426               }
11427               break;
11428             }
11429           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11430             attribute);
11431           break;
11432         }
11433         case 'P':
11434         case 'p':
11435         {
11436           if (LocaleCompare(attribute,"pointsize") == 0)
11437             {
11438               montage_info->pointsize=SvIV(ST(i));
11439               break;
11440             }
11441           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11442             attribute);
11443           break;
11444         }
11445         case 'S':
11446         case 's':
11447         {
11448           if (LocaleCompare(attribute,"shadow") == 0)
11449             {
11450               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11451                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11452               if (sp < 0)
11453                 {
11454                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11455                     SvPV(ST(i),na));
11456                   break;
11457                 }
11458              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11459              break;
11460             }
11461           if (LocaleCompare(attribute,"stroke") == 0)
11462             {
11463               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11464                 &montage_info->stroke,exception);
11465               break;
11466             }
11467           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11468             attribute);
11469           break;
11470         }
11471         case 'T':
11472         case 't':
11473         {
11474           if (LocaleCompare(attribute,"texture") == 0)
11475             {
11476               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11477               break;
11478             }
11479           if (LocaleCompare(attribute,"tile") == 0)
11480             {
11481               char *p=SvPV(ST(i),na);
11482               if (IsGeometry(p) == MagickFalse)
11483                 {
11484                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11485                     p);
11486                   break;
11487                 }
11488               (void) CloneString(&montage_info->tile,p);
11489               if (*p == '\0')
11490                 montage_info->tile=(char *) NULL;
11491               break;
11492             }
11493           if (LocaleCompare(attribute,"title") == 0)
11494             {
11495               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11496               break;
11497             }
11498           if (LocaleCompare(attribute,"transparent") == 0)
11499             {
11500               PixelInfo
11501                 transparent_color;
11502
11503               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11504                 &transparent_color,exception);
11505               for (next=image; next; next=next->next)
11506                 (void) TransparentPaintImage(next,&transparent_color,
11507                   TransparentAlpha,MagickFalse,exception);
11508               break;
11509             }
11510           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11511             attribute);
11512           break;
11513         }
11514         default:
11515         {
11516           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11517             attribute);
11518           break;
11519         }
11520       }
11521     }
11522     image=MontageImageList(info->image_info,montage_info,image,exception);
11523     montage_info=DestroyMontageInfo(montage_info);
11524     if (image == (Image *) NULL)
11525       goto PerlException;
11526     if (transparent_color.alpha != TransparentAlpha)
11527       for (next=image; next; next=next->next)
11528         (void) TransparentPaintImage(next,&transparent_color,
11529           TransparentAlpha,MagickFalse,exception);
11530     for (  ; image; image=image->next)
11531     {
11532       AddImageToRegistry(sv,image);
11533       rv=newRV(sv);
11534       av_push(av,sv_bless(rv,hv));
11535       SvREFCNT_dec(sv);
11536     }
11537     exception=DestroyExceptionInfo(exception);
11538     ST(0)=av_reference;
11539     SvREFCNT_dec(perl_exception);
11540     XSRETURN(1);
11541
11542   PerlException:
11543     InheritPerlException(exception,perl_exception);
11544     exception=DestroyExceptionInfo(exception);
11545     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11546     SvPOK_on(perl_exception);
11547     ST(0)=sv_2mortal(perl_exception);
11548     XSRETURN(1);
11549   }
11550 \f
11551 #
11552 ###############################################################################
11553 #                                                                             #
11554 #                                                                             #
11555 #                                                                             #
11556 #   M o r p h                                                                 #
11557 #                                                                             #
11558 #                                                                             #
11559 #                                                                             #
11560 ###############################################################################
11561 #
11562 #
11563 void
11564 Morph(ref,...)
11565   Image::Magick ref=NO_INIT
11566   ALIAS:
11567     MorphImage  = 1
11568     morph       = 2
11569     morphimage  = 3
11570   PPCODE:
11571   {
11572     AV
11573       *av;
11574
11575     char
11576       *attribute;
11577
11578     ExceptionInfo
11579       *exception;
11580
11581     HV
11582       *hv;
11583
11584     Image
11585       *image;
11586
11587     register ssize_t
11588       i;
11589
11590     ssize_t
11591       number_frames;
11592
11593     struct PackageInfo
11594       *info;
11595
11596     SV
11597       *av_reference,
11598       *perl_exception,
11599       *reference,
11600       *rv,
11601       *sv;
11602
11603     PERL_UNUSED_VAR(ref);
11604     PERL_UNUSED_VAR(ix);
11605     exception=AcquireExceptionInfo();
11606     perl_exception=newSVpv("",0);
11607     sv=NULL;
11608     av=NULL;
11609     attribute=NULL;
11610     if (sv_isobject(ST(0)) == 0)
11611       {
11612         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11613           PackageName);
11614         goto PerlException;
11615       }
11616     reference=SvRV(ST(0));
11617     hv=SvSTASH(reference);
11618     av=newAV();
11619     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11620     SvREFCNT_dec(av);
11621     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11622     if (image == (Image *) NULL)
11623       {
11624         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11625           PackageName);
11626         goto PerlException;
11627       }
11628     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11629     /*
11630       Get attribute.
11631     */
11632     number_frames=30;
11633     for (i=2; i < items; i+=2)
11634     {
11635       attribute=(char *) SvPV(ST(i-1),na);
11636       switch (*attribute)
11637       {
11638         case 'F':
11639         case 'f':
11640         {
11641           if (LocaleCompare(attribute,"frames") == 0)
11642             {
11643               number_frames=SvIV(ST(i));
11644               break;
11645             }
11646           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11647             attribute);
11648           break;
11649         }
11650         default:
11651         {
11652           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11653             attribute);
11654           break;
11655         }
11656       }
11657     }
11658     image=MorphImages(image,number_frames,exception);
11659     if (image == (Image *) NULL)
11660       goto PerlException;
11661     for ( ; image; image=image->next)
11662     {
11663       AddImageToRegistry(sv,image);
11664       rv=newRV(sv);
11665       av_push(av,sv_bless(rv,hv));
11666       SvREFCNT_dec(sv);
11667     }
11668     exception=DestroyExceptionInfo(exception);
11669     ST(0)=av_reference;
11670     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11671     XSRETURN(1);
11672
11673   PerlException:
11674     InheritPerlException(exception,perl_exception);
11675     exception=DestroyExceptionInfo(exception);
11676     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11677     SvPOK_on(perl_exception);
11678     ST(0)=sv_2mortal(perl_exception);
11679     XSRETURN(1);
11680   }
11681 \f
11682 #
11683 ###############################################################################
11684 #                                                                             #
11685 #                                                                             #
11686 #                                                                             #
11687 #   M o s a i c                                                               #
11688 #                                                                             #
11689 #                                                                             #
11690 #                                                                             #
11691 ###############################################################################
11692 #
11693 #
11694 void
11695 Mosaic(ref)
11696   Image::Magick ref=NO_INIT
11697   ALIAS:
11698     MosaicImage   = 1
11699     mosaic        = 2
11700     mosaicimage   = 3
11701   PPCODE:
11702   {
11703     AV
11704       *av;
11705
11706     ExceptionInfo
11707       *exception;
11708
11709     HV
11710       *hv;
11711
11712     Image
11713       *image;
11714
11715     struct PackageInfo
11716       *info;
11717
11718     SV
11719       *perl_exception,
11720       *reference,
11721       *rv,
11722       *sv;
11723
11724     PERL_UNUSED_VAR(ref);
11725     PERL_UNUSED_VAR(ix);
11726     exception=AcquireExceptionInfo();
11727     perl_exception=newSVpv("",0);
11728     sv=NULL;
11729     if (sv_isobject(ST(0)) == 0)
11730       {
11731         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11732           PackageName);
11733         goto PerlException;
11734       }
11735     reference=SvRV(ST(0));
11736     hv=SvSTASH(reference);
11737     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11738     if (image == (Image *) NULL)
11739       {
11740         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11741           PackageName);
11742         goto PerlException;
11743       }
11744     image=MergeImageLayers(image,MosaicLayer,exception);
11745     /*
11746       Create blessed Perl array for the returned image.
11747     */
11748     av=newAV();
11749     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11750     SvREFCNT_dec(av);
11751     AddImageToRegistry(sv,image);
11752     rv=newRV(sv);
11753     av_push(av,sv_bless(rv,hv));
11754     SvREFCNT_dec(sv);
11755     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11756     (void) CopyMagickString(info->image_info->filename,image->filename,
11757       MaxTextExtent);
11758     SetImageInfo(info->image_info,0,exception);
11759     exception=DestroyExceptionInfo(exception);
11760     SvREFCNT_dec(perl_exception);
11761     XSRETURN(1);
11762
11763   PerlException:
11764     InheritPerlException(exception,perl_exception);
11765     exception=DestroyExceptionInfo(exception);
11766     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11767     SvPOK_on(perl_exception);  /* return messages in string context */
11768     ST(0)=sv_2mortal(perl_exception);
11769     XSRETURN(1);
11770   }
11771 \f
11772 #
11773 ###############################################################################
11774 #                                                                             #
11775 #                                                                             #
11776 #                                                                             #
11777 #   P i n g                                                                   #
11778 #                                                                             #
11779 #                                                                             #
11780 #                                                                             #
11781 ###############################################################################
11782 #
11783 #
11784 void
11785 Ping(ref,...)
11786   Image::Magick ref=NO_INIT
11787   ALIAS:
11788     PingImage  = 1
11789     ping       = 2
11790     pingimage  = 3
11791   PPCODE:
11792   {
11793     AV
11794       *av;
11795
11796     char
11797       **keep,
11798       **list;
11799
11800     ExceptionInfo
11801       *exception;
11802
11803     Image
11804       *image,
11805       *next;
11806
11807     int
11808       n;
11809
11810     MagickBooleanType
11811       status;
11812
11813     register char
11814       **p;
11815
11816     register ssize_t
11817       i;
11818
11819     ssize_t
11820       ac;
11821
11822     STRLEN
11823       *length;
11824
11825     struct PackageInfo
11826       *info,
11827       *package_info;
11828
11829     SV
11830       *perl_exception,
11831       *reference;
11832
11833     size_t
11834       count;
11835
11836     PERL_UNUSED_VAR(ref);
11837     PERL_UNUSED_VAR(ix);
11838     exception=AcquireExceptionInfo();
11839     perl_exception=newSVpv("",0);
11840     package_info=(struct PackageInfo *) NULL;
11841     ac=(items < 2) ? 1 : items-1;
11842     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11843     keep=list;
11844     length=(STRLEN *) NULL;
11845     if (list == (char **) NULL)
11846       {
11847         ThrowPerlException(exception,ResourceLimitError,
11848           "MemoryAllocationFailed",PackageName);
11849         goto PerlException;
11850       }
11851     keep=list;
11852     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11853     if (length == (STRLEN *) NULL)
11854       {
11855         ThrowPerlException(exception,ResourceLimitError,
11856           "MemoryAllocationFailed",PackageName);
11857         goto PerlException;
11858       }
11859     if (sv_isobject(ST(0)) == 0)
11860       {
11861         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11862           PackageName);
11863         goto PerlException;
11864       }
11865     reference=SvRV(ST(0));
11866     if (SvTYPE(reference) != SVt_PVAV)
11867       {
11868         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11869           PackageName);
11870         goto PerlException;
11871       }
11872     av=(AV *) reference;
11873     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11874       exception);
11875     package_info=ClonePackageInfo(info,exception);
11876     n=1;
11877     if (items <= 1)
11878       *list=(char *) (*package_info->image_info->filename ?
11879         package_info->image_info->filename : "XC:black");
11880     else
11881       for (n=0, i=0; i < ac; i++)
11882       {
11883         list[n]=(char *) SvPV(ST(i+1),length[n]);
11884         if ((items >= 3) && strEQcase(list[n],"blob"))
11885           {
11886             void
11887               *blob;
11888
11889             i++;
11890             blob=(void *) (SvPV(ST(i+1),length[n]));
11891             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11892           }
11893         if ((items >= 3) && strEQcase(list[n],"filename"))
11894           continue;
11895         if ((items >= 3) && strEQcase(list[n],"file"))
11896           {
11897             FILE
11898               *file;
11899
11900             PerlIO
11901               *io_info;
11902
11903             i++;
11904             io_info=IoIFP(sv_2io(ST(i+1)));
11905             if (io_info == (PerlIO *) NULL)
11906               {
11907                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11908                   PackageName);
11909                 continue;
11910               }
11911             file=PerlIO_findFILE(io_info);
11912             if (file == (FILE *) NULL)
11913               {
11914                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11915                   PackageName);
11916                 continue;
11917               }
11918             SetImageInfoFile(package_info->image_info,file);
11919           }
11920         if ((items >= 3) && strEQcase(list[n],"magick"))
11921           continue;
11922         n++;
11923       }
11924     list[n]=(char *) NULL;
11925     keep=list;
11926     status=ExpandFilenames(&n,&list);
11927     if (status == MagickFalse)
11928       {
11929         ThrowPerlException(exception,ResourceLimitError,
11930           "MemoryAllocationFailed",PackageName);
11931         goto PerlException;
11932       }
11933     count=0;
11934     for (i=0; i < n; i++)
11935     {
11936       (void) CopyMagickString(package_info->image_info->filename,list[i],
11937         MaxTextExtent);
11938       image=PingImage(package_info->image_info,exception);
11939       if (image == (Image *) NULL)
11940         break;
11941       if ((package_info->image_info->file != (FILE *) NULL) ||
11942           (package_info->image_info->blob != (void *) NULL))
11943         DisassociateImageStream(image);
11944       count+=GetImageListLength(image);
11945       EXTEND(sp,4*count);
11946       for (next=image; next; next=next->next)
11947       {
11948         PUSHs(sv_2mortal(newSViv(next->columns)));
11949         PUSHs(sv_2mortal(newSViv(next->rows)));
11950         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11951         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11952       }
11953       image=DestroyImageList(image);
11954     }
11955     /*
11956       Free resources.
11957     */
11958     for (i=0; i < n; i++)
11959       if (list[i] != (char *) NULL)
11960         for (p=keep; list[i] != *p++; )
11961           if (*p == NULL)
11962             {
11963               list[i]=(char *) RelinquishMagickMemory(list[i]);
11964               break;
11965             }
11966
11967   PerlException:
11968     if (package_info != (struct PackageInfo *) NULL)
11969       DestroyPackageInfo(package_info);
11970     if (list && (list != keep))
11971       list=(char **) RelinquishMagickMemory(list);
11972     if (keep)
11973       keep=(char **) RelinquishMagickMemory(keep);
11974     if (length)
11975       length=(STRLEN *) RelinquishMagickMemory(length);
11976     InheritPerlException(exception,perl_exception);
11977     exception=DestroyExceptionInfo(exception);
11978     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11979   }
11980 \f
11981 #
11982 ###############################################################################
11983 #                                                                             #
11984 #                                                                             #
11985 #                                                                             #
11986 #   P r e v i e w                                                             #
11987 #                                                                             #
11988 #                                                                             #
11989 #                                                                             #
11990 ###############################################################################
11991 #
11992 #
11993 void
11994 Preview(ref,...)
11995   Image::Magick ref=NO_INIT
11996   ALIAS:
11997     PreviewImage = 1
11998     preview      = 2
11999     previewimage = 3
12000   PPCODE:
12001   {
12002     AV
12003       *av;
12004
12005     ExceptionInfo
12006       *exception;
12007
12008     HV
12009       *hv;
12010
12011     Image
12012       *image,
12013       *preview_image;
12014
12015     PreviewType
12016       preview_type;
12017
12018     struct PackageInfo
12019       *info;
12020
12021     SV
12022       *av_reference,
12023       *perl_exception,
12024       *reference,
12025       *rv,
12026       *sv;
12027
12028     PERL_UNUSED_VAR(ref);
12029     PERL_UNUSED_VAR(ix);
12030     exception=AcquireExceptionInfo();
12031     perl_exception=newSVpv("",0);
12032     sv=NULL;
12033     av=NULL;
12034     if (sv_isobject(ST(0)) == 0)
12035       {
12036         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12037           PackageName);
12038         goto PerlException;
12039       }
12040     reference=SvRV(ST(0));
12041     hv=SvSTASH(reference);
12042     av=newAV();
12043     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12044     SvREFCNT_dec(av);
12045     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12046     if (image == (Image *) NULL)
12047       {
12048         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12049           PackageName);
12050         goto PerlException;
12051       }
12052     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12053     preview_type=GammaPreview;
12054     if (items > 1)
12055       preview_type=(PreviewType)
12056         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12057     for ( ; image; image=image->next)
12058     {
12059       preview_image=PreviewImage(image,preview_type,exception);
12060       if (preview_image == (Image *) NULL)
12061         goto PerlException;
12062       AddImageToRegistry(sv,preview_image);
12063       rv=newRV(sv);
12064       av_push(av,sv_bless(rv,hv));
12065       SvREFCNT_dec(sv);
12066     }
12067     exception=DestroyExceptionInfo(exception);
12068     ST(0)=av_reference;
12069     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12070     XSRETURN(1);
12071
12072   PerlException:
12073     InheritPerlException(exception,perl_exception);
12074     exception=DestroyExceptionInfo(exception);
12075     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12076     SvPOK_on(perl_exception);
12077     ST(0)=sv_2mortal(perl_exception);
12078     XSRETURN(1);
12079   }
12080 \f
12081 #
12082 ###############################################################################
12083 #                                                                             #
12084 #                                                                             #
12085 #                                                                             #
12086 #   Q u e r y C o l o r                                                       #
12087 #                                                                             #
12088 #                                                                             #
12089 #                                                                             #
12090 ###############################################################################
12091 #
12092 #
12093 void
12094 QueryColor(ref,...)
12095   Image::Magick ref=NO_INIT
12096   ALIAS:
12097     querycolor = 1
12098   PPCODE:
12099   {
12100     char
12101       *name;
12102
12103     ExceptionInfo
12104       *exception;
12105
12106     PixelInfo
12107       color;
12108
12109     register ssize_t
12110       i;
12111
12112     SV
12113       *perl_exception;
12114
12115     PERL_UNUSED_VAR(ref);
12116     PERL_UNUSED_VAR(ix);
12117     exception=AcquireExceptionInfo();
12118     perl_exception=newSVpv("",0);
12119     if (items == 1)
12120       {
12121         const ColorInfo
12122           **colorlist;
12123
12124         size_t
12125           colors;
12126
12127         colorlist=GetColorInfoList("*",&colors,exception);
12128         EXTEND(sp,colors);
12129         for (i=0; i < (ssize_t) colors; i++)
12130         {
12131           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12132         }
12133         colorlist=(const ColorInfo **)
12134           RelinquishMagickMemory((ColorInfo **) colorlist);
12135         goto PerlException;
12136       }
12137     EXTEND(sp,5*items);
12138     for (i=1; i < items; i++)
12139     {
12140       name=(char *) SvPV(ST(i),na);
12141       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12142         {
12143           PUSHs(&sv_undef);
12144           continue;
12145         }
12146       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12147       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12148       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12149       if (color.colorspace == CMYKColorspace)
12150         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12151       if (color.alpha_trait == BlendPixelTrait)
12152         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12153     }
12154
12155   PerlException:
12156     InheritPerlException(exception,perl_exception);
12157     exception=DestroyExceptionInfo(exception);
12158     SvREFCNT_dec(perl_exception);
12159   }
12160 \f
12161 #
12162 ###############################################################################
12163 #                                                                             #
12164 #                                                                             #
12165 #                                                                             #
12166 #   Q u e r y C o l o r N a m e                                               #
12167 #                                                                             #
12168 #                                                                             #
12169 #                                                                             #
12170 ###############################################################################
12171 #
12172 #
12173 void
12174 QueryColorname(ref,...)
12175   Image::Magick ref=NO_INIT
12176   ALIAS:
12177     querycolorname = 1
12178   PPCODE:
12179   {
12180     AV
12181       *av;
12182
12183     char
12184       message[MaxTextExtent];
12185
12186     ExceptionInfo
12187       *exception;
12188
12189     Image
12190       *image;
12191
12192     PixelInfo
12193       target_color;
12194
12195     register ssize_t
12196       i;
12197
12198     struct PackageInfo
12199       *info;
12200
12201     SV
12202       *perl_exception,
12203       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12204
12205     PERL_UNUSED_VAR(ref);
12206     PERL_UNUSED_VAR(ix);
12207     exception=AcquireExceptionInfo();
12208     perl_exception=newSVpv("",0);
12209     reference=SvRV(ST(0));
12210     av=(AV *) reference;
12211     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12212       exception);
12213     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12214     if (image == (Image *) NULL)
12215       {
12216         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12217           PackageName);
12218         goto PerlException;
12219       }
12220     EXTEND(sp,items);
12221     for (i=1; i < items; i++)
12222     {
12223       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12224         exception);
12225       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12226         exception);
12227       PUSHs(sv_2mortal(newSVpv(message,0)));
12228     }
12229
12230   PerlException:
12231     InheritPerlException(exception,perl_exception);
12232     exception=DestroyExceptionInfo(exception);
12233     SvREFCNT_dec(perl_exception);
12234   }
12235 \f
12236 #
12237 ###############################################################################
12238 #                                                                             #
12239 #                                                                             #
12240 #                                                                             #
12241 #   Q u e r y F o n t                                                         #
12242 #                                                                             #
12243 #                                                                             #
12244 #                                                                             #
12245 ###############################################################################
12246 #
12247 #
12248 void
12249 QueryFont(ref,...)
12250   Image::Magick ref=NO_INIT
12251   ALIAS:
12252     queryfont = 1
12253   PPCODE:
12254   {
12255     char
12256       *name,
12257       message[MaxTextExtent];
12258
12259     ExceptionInfo
12260       *exception;
12261
12262     register ssize_t
12263       i;
12264
12265     SV
12266       *perl_exception;
12267
12268     volatile const TypeInfo
12269       *type_info;
12270
12271     PERL_UNUSED_VAR(ref);
12272     PERL_UNUSED_VAR(ix);
12273     exception=AcquireExceptionInfo();
12274     perl_exception=newSVpv("",0);
12275     if (items == 1)
12276       {
12277         const TypeInfo
12278           **typelist;
12279
12280         size_t
12281           types;
12282
12283         typelist=GetTypeInfoList("*",&types,exception);
12284         EXTEND(sp,types);
12285         for (i=0; i < (ssize_t) types; i++)
12286         {
12287           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12288         }
12289         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12290           typelist);
12291         goto PerlException;
12292       }
12293     EXTEND(sp,10*items);
12294     for (i=1; i < items; i++)
12295     {
12296       name=(char *) SvPV(ST(i),na);
12297       type_info=GetTypeInfo(name,exception);
12298       if (type_info == (TypeInfo *) NULL)
12299         {
12300           PUSHs(&sv_undef);
12301           continue;
12302         }
12303       if (type_info->name == (char *) NULL)
12304         PUSHs(&sv_undef);
12305       else
12306         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12307       if (type_info->description == (char *) NULL)
12308         PUSHs(&sv_undef);
12309       else
12310         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12311       if (type_info->family == (char *) NULL)
12312         PUSHs(&sv_undef);
12313       else
12314         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12315       if (type_info->style == UndefinedStyle)
12316         PUSHs(&sv_undef);
12317       else
12318         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12319           type_info->style),0)));
12320       if (type_info->stretch == UndefinedStretch)
12321         PUSHs(&sv_undef);
12322       else
12323         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12324           type_info->stretch),0)));
12325       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12326         type_info->weight);
12327       PUSHs(sv_2mortal(newSVpv(message,0)));
12328       if (type_info->encoding == (char *) NULL)
12329         PUSHs(&sv_undef);
12330       else
12331         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12332       if (type_info->foundry == (char *) NULL)
12333         PUSHs(&sv_undef);
12334       else
12335         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12336       if (type_info->format == (char *) NULL)
12337         PUSHs(&sv_undef);
12338       else
12339         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12340       if (type_info->metrics == (char *) NULL)
12341         PUSHs(&sv_undef);
12342       else
12343         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12344       if (type_info->glyphs == (char *) NULL)
12345         PUSHs(&sv_undef);
12346       else
12347         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12348     }
12349
12350   PerlException:
12351     InheritPerlException(exception,perl_exception);
12352     exception=DestroyExceptionInfo(exception);
12353     SvREFCNT_dec(perl_exception);
12354   }
12355 \f
12356 #
12357 ###############################################################################
12358 #                                                                             #
12359 #                                                                             #
12360 #                                                                             #
12361 #   Q u e r y F o n t M e t r i c s                                           #
12362 #                                                                             #
12363 #                                                                             #
12364 #                                                                             #
12365 ###############################################################################
12366 #
12367 #
12368 void
12369 QueryFontMetrics(ref,...)
12370   Image::Magick ref=NO_INIT
12371   ALIAS:
12372     queryfontmetrics = 1
12373   PPCODE:
12374   {
12375     AffineMatrix
12376       affine,
12377       current;
12378
12379     AV
12380       *av;
12381
12382     char
12383       *attribute;
12384
12385     double
12386       x,
12387       y;
12388
12389     DrawInfo
12390       *draw_info;
12391
12392     ExceptionInfo
12393       *exception;
12394
12395     GeometryInfo
12396       geometry_info;
12397
12398     Image
12399       *image;
12400
12401     MagickBooleanType
12402       status;
12403
12404     MagickStatusType
12405       flags;
12406
12407     register ssize_t
12408       i;
12409
12410     ssize_t
12411       type;
12412
12413     struct PackageInfo
12414       *info,
12415       *package_info;
12416
12417     SV
12418       *perl_exception,
12419       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12420
12421     TypeMetric
12422       metrics;
12423
12424     PERL_UNUSED_VAR(ref);
12425     PERL_UNUSED_VAR(ix);
12426     exception=AcquireExceptionInfo();
12427     package_info=(struct PackageInfo *) NULL;
12428     perl_exception=newSVpv("",0);
12429     reference=SvRV(ST(0));
12430     av=(AV *) reference;
12431     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12432       exception);
12433     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12434     if (image == (Image *) NULL)
12435       {
12436         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12437           PackageName);
12438         goto PerlException;
12439       }
12440     package_info=ClonePackageInfo(info,exception);
12441     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12442     CloneString(&draw_info->text,"");
12443     current=draw_info->affine;
12444     GetAffineMatrix(&affine);
12445     x=0.0;
12446     y=0.0;
12447     EXTEND(sp,7*items);
12448     for (i=2; i < items; i+=2)
12449     {
12450       attribute=(char *) SvPV(ST(i-1),na);
12451       switch (*attribute)
12452       {
12453         case 'A':
12454         case 'a':
12455         {
12456           if (LocaleCompare(attribute,"antialias") == 0)
12457             {
12458               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12459                 SvPV(ST(i),na));
12460               if (type < 0)
12461                 {
12462                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12463                     SvPV(ST(i),na));
12464                   break;
12465                 }
12466               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12467               break;
12468             }
12469           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12470             attribute);
12471           break;
12472         }
12473         case 'd':
12474         case 'D':
12475         {
12476           if (LocaleCompare(attribute,"density") == 0)
12477             {
12478               CloneString(&draw_info->density,SvPV(ST(i),na));
12479               break;
12480             }
12481           if (LocaleCompare(attribute,"direction") == 0)
12482             {
12483               draw_info->direction=(DirectionType) ParseCommandOption(
12484                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12485               break;
12486             }
12487           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12488             attribute);
12489           break;
12490         }
12491         case 'e':
12492         case 'E':
12493         {
12494           if (LocaleCompare(attribute,"encoding") == 0)
12495             {
12496               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12497               break;
12498             }
12499           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12500             attribute);
12501           break;
12502         }
12503         case 'f':
12504         case 'F':
12505         {
12506           if (LocaleCompare(attribute,"family") == 0)
12507             {
12508               CloneString(&draw_info->family,SvPV(ST(i),na));
12509               break;
12510             }
12511           if (LocaleCompare(attribute,"fill") == 0)
12512             {
12513               if (info)
12514                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12515                   &draw_info->fill,exception);
12516               break;
12517             }
12518           if (LocaleCompare(attribute,"font") == 0)
12519             {
12520               CloneString(&draw_info->font,SvPV(ST(i),na));
12521               break;
12522             }
12523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12524             attribute);
12525           break;
12526         }
12527         case 'g':
12528         case 'G':
12529         {
12530           if (LocaleCompare(attribute,"geometry") == 0)
12531             {
12532               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12533               break;
12534             }
12535           if (LocaleCompare(attribute,"gravity") == 0)
12536             {
12537               draw_info->gravity=(GravityType) ParseCommandOption(
12538                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12539               break;
12540             }
12541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12542             attribute);
12543           break;
12544         }
12545         case 'i':
12546         case 'I':
12547         {
12548           if (LocaleCompare(attribute,"interline-spacing") == 0)
12549             {
12550               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12551               draw_info->interline_spacing=geometry_info.rho;
12552               break;
12553             }
12554           if (LocaleCompare(attribute,"interword-spacing") == 0)
12555             {
12556               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12557               draw_info->interword_spacing=geometry_info.rho;
12558               break;
12559             }
12560           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12561             attribute);
12562           break;
12563         }
12564         case 'k':
12565         case 'K':
12566         {
12567           if (LocaleCompare(attribute,"kerning") == 0)
12568             {
12569               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12570               draw_info->kerning=geometry_info.rho;
12571               break;
12572             }
12573           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12574             attribute);
12575           break;
12576         }
12577         case 'p':
12578         case 'P':
12579         {
12580           if (LocaleCompare(attribute,"pointsize") == 0)
12581             {
12582               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12583               draw_info->pointsize=geometry_info.rho;
12584               break;
12585             }
12586           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12587             attribute);
12588           break;
12589         }
12590         case 'r':
12591         case 'R':
12592         {
12593           if (LocaleCompare(attribute,"rotate") == 0)
12594             {
12595               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12596               affine.rx=geometry_info.rho;
12597               affine.ry=geometry_info.sigma;
12598               if ((flags & SigmaValue) == 0)
12599                 affine.ry=affine.rx;
12600               break;
12601             }
12602           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12603             attribute);
12604           break;
12605         }
12606         case 's':
12607         case 'S':
12608         {
12609           if (LocaleCompare(attribute,"scale") == 0)
12610             {
12611               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12612               affine.sx=geometry_info.rho;
12613               affine.sy=geometry_info.sigma;
12614               if ((flags & SigmaValue) == 0)
12615                 affine.sy=affine.sx;
12616               break;
12617             }
12618           if (LocaleCompare(attribute,"skew") == 0)
12619             {
12620               double
12621                 x_angle,
12622                 y_angle;
12623
12624               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12625               x_angle=geometry_info.rho;
12626               y_angle=geometry_info.sigma;
12627               if ((flags & SigmaValue) == 0)
12628                 y_angle=x_angle;
12629               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12630               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12631               break;
12632             }
12633           if (LocaleCompare(attribute,"stroke") == 0)
12634             {
12635               if (info)
12636                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12637                   &draw_info->stroke,exception);
12638               break;
12639             }
12640           if (LocaleCompare(attribute,"style") == 0)
12641             {
12642               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12643                 SvPV(ST(i),na));
12644               if (type < 0)
12645                 {
12646                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12647                     SvPV(ST(i),na));
12648                   break;
12649                 }
12650               draw_info->style=(StyleType) type;
12651               break;
12652             }
12653           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12654             attribute);
12655           break;
12656         }
12657         case 't':
12658         case 'T':
12659         {
12660           if (LocaleCompare(attribute,"text") == 0)
12661             {
12662               CloneString(&draw_info->text,SvPV(ST(i),na));
12663               break;
12664             }
12665           if (LocaleCompare(attribute,"translate") == 0)
12666             {
12667               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12668               affine.tx=geometry_info.rho;
12669               affine.ty=geometry_info.sigma;
12670               if ((flags & SigmaValue) == 0)
12671                 affine.ty=affine.tx;
12672               break;
12673             }
12674           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12675             attribute);
12676           break;
12677         }
12678         case 'w':
12679         case 'W':
12680         {
12681           if (LocaleCompare(attribute,"weight") == 0)
12682             {
12683               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12684               draw_info->weight=(size_t) geometry_info.rho;
12685               break;
12686             }
12687           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12688             attribute);
12689           break;
12690         }
12691         case 'x':
12692         case 'X':
12693         {
12694           if (LocaleCompare(attribute,"x") == 0)
12695             {
12696               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12697               x=geometry_info.rho;
12698               break;
12699             }
12700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12701             attribute);
12702           break;
12703         }
12704         case 'y':
12705         case 'Y':
12706         {
12707           if (LocaleCompare(attribute,"y") == 0)
12708             {
12709               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12710               y=geometry_info.rho;
12711               break;
12712             }
12713           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12714             attribute);
12715           break;
12716         }
12717         default:
12718         {
12719           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12720             attribute);
12721           break;
12722         }
12723       }
12724     }
12725     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12726     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12727     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12728     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12729     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12730     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12731     if (draw_info->geometry == (char *) NULL)
12732       {
12733         draw_info->geometry=AcquireString((char *) NULL);
12734         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12735           "%.15g,%.15g",x,y);
12736       }
12737     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12738     (void) CatchImageException(image);
12739     if (status == MagickFalse)
12740       PUSHs(&sv_undef);
12741     else
12742       {
12743         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12744         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12745         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12746         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12747         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12748         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12749         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12750         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12751         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12752         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12753         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12754         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12755         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12756       }
12757     draw_info=DestroyDrawInfo(draw_info);
12758
12759   PerlException:
12760     if (package_info != (struct PackageInfo *) NULL)
12761       DestroyPackageInfo(package_info);
12762     InheritPerlException(exception,perl_exception);
12763     exception=DestroyExceptionInfo(exception);
12764     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12765   }
12766 \f
12767 #
12768 ###############################################################################
12769 #                                                                             #
12770 #                                                                             #
12771 #                                                                             #
12772 #   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                         #
12773 #                                                                             #
12774 #                                                                             #
12775 #                                                                             #
12776 ###############################################################################
12777 #
12778 #
12779 void
12780 QueryMultilineFontMetrics(ref,...)
12781   Image::Magick ref=NO_INIT
12782   ALIAS:
12783     querymultilinefontmetrics = 1
12784   PPCODE:
12785   {
12786     AffineMatrix
12787       affine,
12788       current;
12789
12790     AV
12791       *av;
12792
12793     char
12794       *attribute;
12795
12796     double
12797       x,
12798       y;
12799
12800     DrawInfo
12801       *draw_info;
12802
12803     ExceptionInfo
12804       *exception;
12805
12806     GeometryInfo
12807       geometry_info;
12808
12809     Image
12810       *image;
12811
12812     MagickBooleanType
12813       status;
12814
12815     MagickStatusType
12816       flags;
12817
12818     register ssize_t
12819       i;
12820
12821     ssize_t
12822       type;
12823
12824     struct PackageInfo
12825       *info,
12826       *package_info;
12827
12828     SV
12829       *perl_exception,
12830       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12831
12832     TypeMetric
12833       metrics;
12834
12835     PERL_UNUSED_VAR(ref);
12836     PERL_UNUSED_VAR(ix);
12837     exception=AcquireExceptionInfo();
12838     package_info=(struct PackageInfo *) NULL;
12839     perl_exception=newSVpv("",0);
12840     reference=SvRV(ST(0));
12841     av=(AV *) reference;
12842     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12843       exception);
12844     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12845     if (image == (Image *) NULL)
12846       {
12847         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12848           PackageName);
12849         goto PerlException;
12850       }
12851     package_info=ClonePackageInfo(info,exception);
12852     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12853     CloneString(&draw_info->text,"");
12854     current=draw_info->affine;
12855     GetAffineMatrix(&affine);
12856     x=0.0;
12857     y=0.0;
12858     EXTEND(sp,7*items);
12859     for (i=2; i < items; i+=2)
12860     {
12861       attribute=(char *) SvPV(ST(i-1),na);
12862       switch (*attribute)
12863       {
12864         case 'A':
12865         case 'a':
12866         {
12867           if (LocaleCompare(attribute,"antialias") == 0)
12868             {
12869               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12870                 SvPV(ST(i),na));
12871               if (type < 0)
12872                 {
12873                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12874                     SvPV(ST(i),na));
12875                   break;
12876                 }
12877               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12878               break;
12879             }
12880           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12881             attribute);
12882           break;
12883         }
12884         case 'd':
12885         case 'D':
12886         {
12887           if (LocaleCompare(attribute,"density") == 0)
12888             {
12889               CloneString(&draw_info->density,SvPV(ST(i),na));
12890               break;
12891             }
12892           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12893             attribute);
12894           break;
12895         }
12896         case 'e':
12897         case 'E':
12898         {
12899           if (LocaleCompare(attribute,"encoding") == 0)
12900             {
12901               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12902               break;
12903             }
12904           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12905             attribute);
12906           break;
12907         }
12908         case 'f':
12909         case 'F':
12910         {
12911           if (LocaleCompare(attribute,"family") == 0)
12912             {
12913               CloneString(&draw_info->family,SvPV(ST(i),na));
12914               break;
12915             }
12916           if (LocaleCompare(attribute,"fill") == 0)
12917             {
12918               if (info)
12919                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12920                   &draw_info->fill,exception);
12921               break;
12922             }
12923           if (LocaleCompare(attribute,"font") == 0)
12924             {
12925               CloneString(&draw_info->font,SvPV(ST(i),na));
12926               break;
12927             }
12928           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12929             attribute);
12930           break;
12931         }
12932         case 'g':
12933         case 'G':
12934         {
12935           if (LocaleCompare(attribute,"geometry") == 0)
12936             {
12937               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12938               break;
12939             }
12940           if (LocaleCompare(attribute,"gravity") == 0)
12941             {
12942               draw_info->gravity=(GravityType) ParseCommandOption(
12943                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12944               break;
12945             }
12946           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12947             attribute);
12948           break;
12949         }
12950         case 'p':
12951         case 'P':
12952         {
12953           if (LocaleCompare(attribute,"pointsize") == 0)
12954             {
12955               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12956               draw_info->pointsize=geometry_info.rho;
12957               break;
12958             }
12959           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12960             attribute);
12961           break;
12962         }
12963         case 'r':
12964         case 'R':
12965         {
12966           if (LocaleCompare(attribute,"rotate") == 0)
12967             {
12968               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12969               affine.rx=geometry_info.rho;
12970               affine.ry=geometry_info.sigma;
12971               if ((flags & SigmaValue) == 0)
12972                 affine.ry=affine.rx;
12973               break;
12974             }
12975           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12976             attribute);
12977           break;
12978         }
12979         case 's':
12980         case 'S':
12981         {
12982           if (LocaleCompare(attribute,"scale") == 0)
12983             {
12984               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12985               affine.sx=geometry_info.rho;
12986               affine.sy=geometry_info.sigma;
12987               if ((flags & SigmaValue) == 0)
12988                 affine.sy=affine.sx;
12989               break;
12990             }
12991           if (LocaleCompare(attribute,"skew") == 0)
12992             {
12993               double
12994                 x_angle,
12995                 y_angle;
12996
12997               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12998               x_angle=geometry_info.rho;
12999               y_angle=geometry_info.sigma;
13000               if ((flags & SigmaValue) == 0)
13001                 y_angle=x_angle;
13002               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13003               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13004               break;
13005             }
13006           if (LocaleCompare(attribute,"stroke") == 0)
13007             {
13008               if (info)
13009                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13010                   &draw_info->stroke,exception);
13011               break;
13012             }
13013           if (LocaleCompare(attribute,"style") == 0)
13014             {
13015               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13016                 SvPV(ST(i),na));
13017               if (type < 0)
13018                 {
13019                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13020                     SvPV(ST(i),na));
13021                   break;
13022                 }
13023               draw_info->style=(StyleType) type;
13024               break;
13025             }
13026           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13027             attribute);
13028           break;
13029         }
13030         case 't':
13031         case 'T':
13032         {
13033           if (LocaleCompare(attribute,"text") == 0)
13034             {
13035               CloneString(&draw_info->text,SvPV(ST(i),na));
13036               break;
13037             }
13038           if (LocaleCompare(attribute,"translate") == 0)
13039             {
13040               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13041               affine.tx=geometry_info.rho;
13042               affine.ty=geometry_info.sigma;
13043               if ((flags & SigmaValue) == 0)
13044                 affine.ty=affine.tx;
13045               break;
13046             }
13047           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13048             attribute);
13049           break;
13050         }
13051         case 'w':
13052         case 'W':
13053         {
13054           if (LocaleCompare(attribute,"weight") == 0)
13055             {
13056               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13057               draw_info->weight=(size_t) geometry_info.rho;
13058               break;
13059             }
13060           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13061             attribute);
13062           break;
13063         }
13064         case 'x':
13065         case 'X':
13066         {
13067           if (LocaleCompare(attribute,"x") == 0)
13068             {
13069               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13070               x=geometry_info.rho;
13071               break;
13072             }
13073           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13074             attribute);
13075           break;
13076         }
13077         case 'y':
13078         case 'Y':
13079         {
13080           if (LocaleCompare(attribute,"y") == 0)
13081             {
13082               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13083               y=geometry_info.rho;
13084               break;
13085             }
13086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13087             attribute);
13088           break;
13089         }
13090         default:
13091         {
13092           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13093             attribute);
13094           break;
13095         }
13096       }
13097     }
13098     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13099     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13100     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13101     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13102     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13103     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13104     if (draw_info->geometry == (char *) NULL)
13105       {
13106         draw_info->geometry=AcquireString((char *) NULL);
13107         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
13108           "%.15g,%.15g",x,y);
13109       }
13110     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13111     (void) CatchException(exception);
13112     if (status == MagickFalse)
13113       PUSHs(&sv_undef);
13114     else
13115       {
13116         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13117         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13118         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13119         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13120         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13121         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13122         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13123         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13124         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13125         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13126         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13127         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13128         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13129       }
13130     draw_info=DestroyDrawInfo(draw_info);
13131
13132   PerlException:
13133     if (package_info != (struct PackageInfo *) NULL)
13134       DestroyPackageInfo(package_info);
13135     InheritPerlException(exception,perl_exception);
13136     exception=DestroyExceptionInfo(exception);
13137     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13138   }
13139 \f
13140 #
13141 ###############################################################################
13142 #                                                                             #
13143 #                                                                             #
13144 #                                                                             #
13145 #   Q u e r y F o r m a t                                                     #
13146 #                                                                             #
13147 #                                                                             #
13148 #                                                                             #
13149 ###############################################################################
13150 #
13151 #
13152 void
13153 QueryFormat(ref,...)
13154   Image::Magick ref=NO_INIT
13155   ALIAS:
13156     queryformat = 1
13157   PPCODE:
13158   {
13159     char
13160       *name;
13161
13162     ExceptionInfo
13163       *exception;
13164
13165     register ssize_t
13166       i;
13167
13168     SV
13169       *perl_exception;
13170
13171     volatile const MagickInfo
13172       *magick_info;
13173
13174     PERL_UNUSED_VAR(ref);
13175     PERL_UNUSED_VAR(ix);
13176     exception=AcquireExceptionInfo();
13177     perl_exception=newSVpv("",0);
13178     if (items == 1)
13179       {
13180         char
13181           format[MaxTextExtent];
13182
13183         const MagickInfo
13184           **format_list;
13185
13186         size_t
13187           types;
13188
13189         format_list=GetMagickInfoList("*",&types,exception);
13190         EXTEND(sp,types);
13191         for (i=0; i < (ssize_t) types; i++)
13192         {
13193           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13194           LocaleLower(format);
13195           PUSHs(sv_2mortal(newSVpv(format,0)));
13196         }
13197         format_list=(const MagickInfo **)
13198           RelinquishMagickMemory((MagickInfo *) format_list);
13199         goto PerlException;
13200       }
13201     EXTEND(sp,8*items);
13202     for (i=1; i < items; i++)
13203     {
13204       name=(char *) SvPV(ST(i),na);
13205       magick_info=GetMagickInfo(name,exception);
13206       if (magick_info == (const MagickInfo *) NULL)
13207         {
13208           PUSHs(&sv_undef);
13209           continue;
13210         }
13211       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13212       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13213       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13214       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13215       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13216       if (magick_info->description == (char *) NULL)
13217         PUSHs(&sv_undef);
13218       else
13219         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13220       if (magick_info->module == (char *) NULL)
13221         PUSHs(&sv_undef);
13222       else
13223         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13224     }
13225
13226   PerlException:
13227     InheritPerlException(exception,perl_exception);
13228     exception=DestroyExceptionInfo(exception);
13229     SvREFCNT_dec(perl_exception);
13230   }
13231 \f
13232 #
13233 ###############################################################################
13234 #                                                                             #
13235 #                                                                             #
13236 #                                                                             #
13237 #   Q u e r y O p t i o n                                                     #
13238 #                                                                             #
13239 #                                                                             #
13240 #                                                                             #
13241 ###############################################################################
13242 #
13243 #
13244 void
13245 QueryOption(ref,...)
13246   Image::Magick ref=NO_INIT
13247   ALIAS:
13248     queryoption = 1
13249   PPCODE:
13250   {
13251     char
13252       **options;
13253
13254     ExceptionInfo
13255       *exception;
13256
13257     register ssize_t
13258       i;
13259
13260     ssize_t
13261       j,
13262       option;
13263
13264     SV
13265       *perl_exception;
13266
13267     PERL_UNUSED_VAR(ref);
13268     PERL_UNUSED_VAR(ix);
13269     exception=AcquireExceptionInfo();
13270     perl_exception=newSVpv("",0);
13271     EXTEND(sp,8*items);
13272     for (i=1; i < items; i++)
13273     {
13274       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13275         SvPV(ST(i),na));
13276       options=GetCommandOptions((CommandOption) option);
13277       if (options == (char **) NULL)
13278         PUSHs(&sv_undef);
13279       else
13280         {
13281           for (j=0; options[j] != (char *) NULL; j++)
13282             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13283           options=DestroyStringList(options);
13284         }
13285     }
13286
13287     InheritPerlException(exception,perl_exception);
13288     exception=DestroyExceptionInfo(exception);
13289     SvREFCNT_dec(perl_exception);
13290   }
13291 \f
13292 #
13293 ###############################################################################
13294 #                                                                             #
13295 #                                                                             #
13296 #                                                                             #
13297 #   R e a d                                                                   #
13298 #                                                                             #
13299 #                                                                             #
13300 #                                                                             #
13301 ###############################################################################
13302 #
13303 #
13304 void
13305 Read(ref,...)
13306   Image::Magick ref=NO_INIT
13307   ALIAS:
13308     ReadImage  = 1
13309     read       = 2
13310     readimage  = 3
13311   PPCODE:
13312   {
13313     AV
13314       *av;
13315
13316     char
13317       **keep,
13318       **list;
13319
13320     ExceptionInfo
13321       *exception;
13322
13323     HV
13324       *hv;
13325
13326     Image
13327       *image;
13328
13329     int
13330       n;
13331
13332     MagickBooleanType
13333       status;
13334
13335     register char
13336       **p;
13337
13338     register ssize_t
13339       i;
13340
13341     ssize_t
13342       ac,
13343       number_images;
13344
13345     STRLEN
13346       *length;
13347
13348     struct PackageInfo
13349       *info,
13350       *package_info;
13351
13352     SV
13353       *perl_exception,  /* Perl variable for storing messages */
13354       *reference,
13355       *rv,
13356       *sv;
13357
13358     PERL_UNUSED_VAR(ref);
13359     PERL_UNUSED_VAR(ix);
13360     exception=AcquireExceptionInfo();
13361     perl_exception=newSVpv("",0);
13362     sv=NULL;
13363     package_info=(struct PackageInfo *) NULL;
13364     number_images=0;
13365     ac=(items < 2) ? 1 : items-1;
13366     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13367     keep=list;
13368     length=(STRLEN *) NULL;
13369     if (list == (char **) NULL)
13370       {
13371         ThrowPerlException(exception,ResourceLimitError,
13372           "MemoryAllocationFailed",PackageName);
13373         goto PerlException;
13374       }
13375     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13376     if (length == (STRLEN *) NULL)
13377       {
13378         ThrowPerlException(exception,ResourceLimitError,
13379           "MemoryAllocationFailed",PackageName);
13380         goto PerlException;
13381       }
13382     if (sv_isobject(ST(0)) == 0)
13383       {
13384         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13385           PackageName);
13386         goto PerlException;
13387       }
13388     reference=SvRV(ST(0));
13389     hv=SvSTASH(reference);
13390     if (SvTYPE(reference) != SVt_PVAV)
13391       {
13392         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13393           PackageName);
13394         goto PerlException;
13395       }
13396     av=(AV *) reference;
13397     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13398       exception);
13399     package_info=ClonePackageInfo(info,exception);
13400     n=1;
13401     if (items <= 1)
13402       *list=(char *) (*package_info->image_info->filename ?
13403         package_info->image_info->filename : "XC:black");
13404     else
13405       for (n=0, i=0; i < ac; i++)
13406       {
13407         list[n]=(char *) SvPV(ST(i+1),length[n]);
13408         if ((items >= 3) && strEQcase(list[n],"blob"))
13409           {
13410             void
13411               *blob;
13412
13413             i++;
13414             blob=(void *) (SvPV(ST(i+1),length[n]));
13415             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13416           }
13417         if ((items >= 3) && strEQcase(list[n],"filename"))
13418           continue;
13419         if ((items >= 3) && strEQcase(list[n],"file"))
13420           {
13421             FILE
13422               *file;
13423
13424             PerlIO
13425               *io_info;
13426
13427             i++;
13428             io_info=IoIFP(sv_2io(ST(i+1)));
13429             if (io_info == (PerlIO *) NULL)
13430               {
13431                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13432                   PackageName);
13433                 continue;
13434               }
13435             file=PerlIO_findFILE(io_info);
13436             if (file == (FILE *) NULL)
13437               {
13438                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13439                   PackageName);
13440                 continue;
13441               }
13442             SetImageInfoFile(package_info->image_info,file);
13443           }
13444         if ((items >= 3) && strEQcase(list[n],"magick"))
13445           continue;
13446         n++;
13447       }
13448     list[n]=(char *) NULL;
13449     keep=list;
13450     status=ExpandFilenames(&n,&list);
13451     if (status == MagickFalse)
13452       {
13453         ThrowPerlException(exception,ResourceLimitError,
13454           "MemoryAllocationFailed",PackageName);
13455         goto PerlException;
13456       }
13457     number_images=0;
13458     for (i=0; i < n; i++)
13459     {
13460       if ((package_info->image_info->file == (FILE *) NULL) &&
13461           (package_info->image_info->blob == (void *) NULL))
13462         image=ReadImages(package_info->image_info,list[i],exception);
13463       else
13464         {
13465           image=ReadImages(package_info->image_info,
13466             package_info->image_info->filename,exception);
13467           if (image != (Image *) NULL)
13468             DisassociateImageStream(image);
13469         }
13470       if (image == (Image *) NULL)
13471         break;
13472       for ( ; image; image=image->next)
13473       {
13474         AddImageToRegistry(sv,image);
13475         rv=newRV(sv);
13476         av_push(av,sv_bless(rv,hv));
13477         SvREFCNT_dec(sv);
13478         number_images++;
13479       }
13480     }
13481     /*
13482       Free resources.
13483     */
13484     for (i=0; i < n; i++)
13485       if (list[i] != (char *) NULL)
13486         for (p=keep; list[i] != *p++; )
13487           if (*p == (char *) NULL)
13488             {
13489               list[i]=(char *) RelinquishMagickMemory(list[i]);
13490               break;
13491             }
13492
13493   PerlException:
13494     if (package_info != (struct PackageInfo *) NULL)
13495       DestroyPackageInfo(package_info);
13496     if (list && (list != keep))
13497       list=(char **) RelinquishMagickMemory(list);
13498     if (keep)
13499       keep=(char **) RelinquishMagickMemory(keep);
13500     if (length)
13501       length=(STRLEN *) RelinquishMagickMemory(length);
13502     InheritPerlException(exception,perl_exception);
13503     exception=DestroyExceptionInfo(exception);
13504     sv_setiv(perl_exception,(IV) number_images);
13505     SvPOK_on(perl_exception);
13506     ST(0)=sv_2mortal(perl_exception);
13507     XSRETURN(1);
13508   }
13509 \f
13510 #
13511 ###############################################################################
13512 #                                                                             #
13513 #                                                                             #
13514 #                                                                             #
13515 #   R e m o t e                                                               #
13516 #                                                                             #
13517 #                                                                             #
13518 #                                                                             #
13519 ###############################################################################
13520 #
13521 #
13522 void
13523 Remote(ref,...)
13524   Image::Magick ref=NO_INIT
13525   ALIAS:
13526     RemoteCommand  = 1
13527     remote         = 2
13528     remoteCommand  = 3
13529   PPCODE:
13530   {
13531     AV
13532       *av;
13533
13534     ExceptionInfo
13535       *exception;
13536
13537     register ssize_t
13538       i;
13539
13540     SV
13541       *perl_exception,
13542       *reference;
13543
13544     struct PackageInfo
13545       *info;
13546
13547     PERL_UNUSED_VAR(ref);
13548     PERL_UNUSED_VAR(ix);
13549     exception=AcquireExceptionInfo();
13550     perl_exception=newSVpv("",0);
13551     reference=SvRV(ST(0));
13552     av=(AV *) reference;
13553     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13554       exception);
13555     for (i=1; i < items; i++)
13556       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13557         SvPV(ST(i),na),exception);
13558     InheritPerlException(exception,perl_exception);
13559     exception=DestroyExceptionInfo(exception);
13560     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13561   }
13562 \f
13563 #
13564 ###############################################################################
13565 #                                                                             #
13566 #                                                                             #
13567 #                                                                             #
13568 #   S e t                                                                     #
13569 #                                                                             #
13570 #                                                                             #
13571 #                                                                             #
13572 ###############################################################################
13573 #
13574 #
13575 void
13576 Set(ref,...)
13577   Image::Magick ref=NO_INIT
13578   ALIAS:
13579     SetAttributes  = 1
13580     SetAttribute   = 2
13581     set            = 3
13582     setattributes  = 4
13583     setattribute   = 5
13584   PPCODE:
13585   {
13586     ExceptionInfo
13587       *exception;
13588
13589     Image
13590       *image;
13591
13592     register ssize_t
13593       i;
13594
13595     struct PackageInfo
13596       *info;
13597
13598     SV
13599       *perl_exception,
13600       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13601
13602     PERL_UNUSED_VAR(ref);
13603     PERL_UNUSED_VAR(ix);
13604     exception=AcquireExceptionInfo();
13605     perl_exception=newSVpv("",0);
13606     if (sv_isobject(ST(0)) == 0)
13607       {
13608         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13609           PackageName);
13610         goto PerlException;
13611       }
13612     reference=SvRV(ST(0));
13613     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13614     if (items == 2)
13615       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13616     else
13617       for (i=2; i < items; i+=2)
13618         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13619
13620   PerlException:
13621     InheritPerlException(exception,perl_exception);
13622     exception=DestroyExceptionInfo(exception);
13623     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13624     SvPOK_on(perl_exception);
13625     ST(0)=sv_2mortal(perl_exception);
13626     XSRETURN(1);
13627   }
13628 \f
13629 #
13630 ###############################################################################
13631 #                                                                             #
13632 #                                                                             #
13633 #                                                                             #
13634 #   S e t P i x e l                                                           #
13635 #                                                                             #
13636 #                                                                             #
13637 #                                                                             #
13638 ###############################################################################
13639 #
13640 #
13641 void
13642 SetPixel(ref,...)
13643   Image::Magick ref=NO_INIT
13644   ALIAS:
13645     setpixel = 1
13646     setPixel = 2
13647   PPCODE:
13648   {
13649     AV
13650       *av;
13651
13652     char
13653       *attribute;
13654
13655     ChannelType
13656       channel,
13657       channel_mask;
13658
13659     ExceptionInfo
13660       *exception;
13661
13662     Image
13663       *image;
13664
13665     MagickBooleanType
13666       normalize;
13667
13668     RectangleInfo
13669       region;
13670
13671     register ssize_t
13672       i;
13673
13674     register Quantum
13675       *q;
13676
13677     ssize_t
13678       option;
13679
13680     struct PackageInfo
13681       *info;
13682
13683     SV
13684       *perl_exception,
13685       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13686
13687     PERL_UNUSED_VAR(ref);
13688     PERL_UNUSED_VAR(ix);
13689     exception=AcquireExceptionInfo();
13690     perl_exception=newSVpv("",0);
13691     reference=SvRV(ST(0));
13692     av=(AV *) reference;
13693     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13694       exception);
13695     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13696     if (image == (Image *) NULL)
13697       {
13698         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13699           PackageName);
13700         goto PerlException;
13701       }
13702     av=(AV *) NULL;
13703     normalize=MagickTrue;
13704     region.x=0;
13705     region.y=0;
13706     region.width=image->columns;
13707     region.height=1;
13708     if (items == 1)
13709       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13710     channel=DefaultChannels;
13711     for (i=2; i < items; i+=2)
13712     {
13713       attribute=(char *) SvPV(ST(i-1),na);
13714       switch (*attribute)
13715       {
13716         case 'C':
13717         case 'c':
13718         {
13719           if (LocaleCompare(attribute,"channel") == 0)
13720             {
13721               ssize_t
13722                 option;
13723
13724               option=ParseChannelOption(SvPV(ST(i),na));
13725               if (option < 0)
13726                 {
13727                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13728                     SvPV(ST(i),na));
13729                   return;
13730                 }
13731               channel=(ChannelType) option;
13732               break;
13733             }
13734           if (LocaleCompare(attribute,"color") == 0)
13735             {
13736               if (SvTYPE(ST(i)) != SVt_RV)
13737                 {
13738                   char
13739                     message[MaxTextExtent];
13740
13741                   (void) FormatLocaleString(message,MaxTextExtent,
13742                     "invalid %.60s value",attribute);
13743                   ThrowPerlException(exception,OptionError,message,
13744                     SvPV(ST(i),na));
13745                 }
13746               av=(AV *) SvRV(ST(i));
13747               break;
13748             }
13749           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13750             attribute);
13751           break;
13752         }
13753         case 'g':
13754         case 'G':
13755         {
13756           if (LocaleCompare(attribute,"geometry") == 0)
13757             {
13758               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13759               break;
13760             }
13761           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13762             attribute);
13763           break;
13764         }
13765         case 'N':
13766         case 'n':
13767         {
13768           if (LocaleCompare(attribute,"normalize") == 0)
13769             {
13770               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13771                 SvPV(ST(i),na));
13772               if (option < 0)
13773                 {
13774                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13775                     SvPV(ST(i),na));
13776                   break;
13777                 }
13778              normalize=option != 0 ? MagickTrue : MagickFalse;
13779              break;
13780             }
13781           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13782             attribute);
13783           break;
13784         }
13785         case 'x':
13786         case 'X':
13787         {
13788           if (LocaleCompare(attribute,"x") == 0)
13789             {
13790               region.x=SvIV(ST(i));
13791               break;
13792             }
13793           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13794             attribute);
13795           break;
13796         }
13797         case 'y':
13798         case 'Y':
13799         {
13800           if (LocaleCompare(attribute,"y") == 0)
13801             {
13802               region.y=SvIV(ST(i));
13803               break;
13804             }
13805           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13806             attribute);
13807           break;
13808         }
13809         default:
13810         {
13811           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13812             attribute);
13813           break;
13814         }
13815       }
13816     }
13817     (void) SetImageStorageClass(image,DirectClass,exception);
13818     channel_mask=SetImageChannelMask(image,channel);
13819     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13820     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13821         (SvTYPE(av) != SVt_PVAV))
13822       PUSHs(&sv_undef);
13823     else
13824       {
13825         double
13826           scale;
13827
13828         register ssize_t
13829           i;
13830
13831         i=0;
13832         scale=1.0;
13833         if (normalize != MagickFalse)
13834           scale=QuantumRange;
13835         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13836             (i <= av_len(av)))
13837           {
13838             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13839               av_fetch(av,i,0)))),q);
13840             i++;
13841           }
13842         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13843             (i <= av_len(av)))
13844           {
13845             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13846               av_fetch(av,i,0)))),q);
13847             i++;
13848           }
13849         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13850             (i <= av_len(av)))
13851           {
13852             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13853               av_fetch(av,i,0)))),q);
13854             i++;
13855           }
13856         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13857             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13858           {
13859             SetPixelBlack(image,ClampToQuantum(scale*
13860               SvNV(*(av_fetch(av,i,0)))),q);
13861             i++;
13862           }
13863         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13864             (i <= av_len(av)))
13865           {
13866             SetPixelAlpha(image,ClampToQuantum(scale*
13867               SvNV(*(av_fetch(av,i,0)))),q);
13868             i++;
13869           }
13870         (void) SyncAuthenticPixels(image,exception);
13871       }
13872     (void) SetImageChannelMask(image,channel_mask);
13873
13874   PerlException:
13875     InheritPerlException(exception,perl_exception);
13876     exception=DestroyExceptionInfo(exception);
13877     SvREFCNT_dec(perl_exception);
13878   }
13879 \f
13880 #
13881 ###############################################################################
13882 #                                                                             #
13883 #                                                                             #
13884 #                                                                             #
13885 #   S m u s h                                                                 #
13886 #                                                                             #
13887 #                                                                             #
13888 #                                                                             #
13889 ###############################################################################
13890 #
13891 #
13892 void
13893 Smush(ref,...)
13894   Image::Magick ref=NO_INIT
13895   ALIAS:
13896     SmushImage  = 1
13897     smush       = 2
13898     smushimage  = 3
13899   PPCODE:
13900   {
13901     AV
13902       *av;
13903
13904     char
13905       *attribute;
13906
13907     ExceptionInfo
13908       *exception;
13909
13910     HV
13911       *hv;
13912
13913     Image
13914       *image;
13915
13916     register ssize_t
13917       i;
13918
13919     ssize_t
13920       offset,
13921       stack;
13922
13923     struct PackageInfo
13924       *info;
13925
13926     SV
13927       *av_reference,
13928       *perl_exception,
13929       *reference,
13930       *rv,
13931       *sv;
13932
13933     PERL_UNUSED_VAR(ref);
13934     PERL_UNUSED_VAR(ix);
13935     exception=AcquireExceptionInfo();
13936     perl_exception=newSVpv("",0);
13937     sv=NULL;
13938     attribute=NULL;
13939     av=NULL;
13940     if (sv_isobject(ST(0)) == 0)
13941       {
13942         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13943           PackageName);
13944         goto PerlException;
13945       }
13946     reference=SvRV(ST(0));
13947     hv=SvSTASH(reference);
13948     av=newAV();
13949     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13950     SvREFCNT_dec(av);
13951     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13952     if (image == (Image *) NULL)
13953       {
13954         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13955           PackageName);
13956         goto PerlException;
13957       }
13958     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13959     /*
13960       Get options.
13961     */
13962     offset=0;
13963     stack=MagickTrue;
13964     for (i=2; i < items; i+=2)
13965     {
13966       attribute=(char *) SvPV(ST(i-1),na);
13967       switch (*attribute)
13968       {
13969         case 'O':
13970         case 'o':
13971         {
13972           if (LocaleCompare(attribute,"offset") == 0)
13973             {
13974               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13975               break;
13976             }
13977           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13978             attribute);
13979           break;
13980         }
13981         case 'S':
13982         case 's':
13983         {
13984           if (LocaleCompare(attribute,"stack") == 0)
13985             {
13986               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13987                 SvPV(ST(i),na));
13988               if (stack < 0)
13989                 {
13990                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13991                     SvPV(ST(i),na));
13992                   return;
13993                 }
13994               break;
13995             }
13996           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13997             attribute);
13998           break;
13999         }
14000         default:
14001         {
14002           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14003             attribute);
14004           break;
14005         }
14006       }
14007     }
14008     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14009       exception);
14010     if (image == (Image *) NULL)
14011       goto PerlException;
14012     for ( ; image; image=image->next)
14013     {
14014       AddImageToRegistry(sv,image);
14015       rv=newRV(sv);
14016       av_push(av,sv_bless(rv,hv));
14017       SvREFCNT_dec(sv);
14018     }
14019     exception=DestroyExceptionInfo(exception);
14020     ST(0)=av_reference;
14021     SvREFCNT_dec(perl_exception);
14022     XSRETURN(1);
14023
14024   PerlException:
14025     InheritPerlException(exception,perl_exception);
14026     exception=DestroyExceptionInfo(exception);
14027     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14028     SvPOK_on(perl_exception);
14029     ST(0)=sv_2mortal(perl_exception);
14030     XSRETURN(1);
14031   }
14032 \f
14033 #
14034 ###############################################################################
14035 #                                                                             #
14036 #                                                                             #
14037 #                                                                             #
14038 #   S t a t i s t i c s                                                       #
14039 #                                                                             #
14040 #                                                                             #
14041 #                                                                             #
14042 ###############################################################################
14043 #
14044 #
14045 void
14046 Statistics(ref,...)
14047   Image::Magick ref=NO_INIT
14048   ALIAS:
14049     StatisticsImage = 1
14050     statistics      = 2
14051     statisticsimage = 3
14052   PPCODE:
14053   {
14054 #define ChannelStatistics(channel) \
14055 { \
14056   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14057     (double) channel_statistics[channel].depth); \
14058   PUSHs(sv_2mortal(newSVpv(message,0))); \
14059   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14060     channel_statistics[channel].minima/scale); \
14061   PUSHs(sv_2mortal(newSVpv(message,0))); \
14062   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14063     channel_statistics[channel].maxima/scale); \
14064   PUSHs(sv_2mortal(newSVpv(message,0))); \
14065   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14066     channel_statistics[channel].mean/scale); \
14067   PUSHs(sv_2mortal(newSVpv(message,0))); \
14068   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14069     channel_statistics[channel].standard_deviation/scale); \
14070   PUSHs(sv_2mortal(newSVpv(message,0))); \
14071   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14072     channel_statistics[channel].kurtosis); \
14073   PUSHs(sv_2mortal(newSVpv(message,0))); \
14074   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14075     channel_statistics[channel].skewness); \
14076   PUSHs(sv_2mortal(newSVpv(message,0))); \
14077 }
14078
14079     AV
14080       *av;
14081
14082     char
14083       message[MaxTextExtent];
14084
14085     ChannelStatistics
14086       *channel_statistics;
14087
14088     double
14089       scale;
14090
14091     ExceptionInfo
14092       *exception;
14093
14094     Image
14095       *image;
14096
14097     ssize_t
14098       count;
14099
14100     struct PackageInfo
14101       *info;
14102
14103     SV
14104       *perl_exception,
14105       *reference;
14106
14107     PERL_UNUSED_VAR(ref);
14108     PERL_UNUSED_VAR(ix);
14109     exception=AcquireExceptionInfo();
14110     perl_exception=newSVpv("",0);
14111     av=NULL;
14112     if (sv_isobject(ST(0)) == 0)
14113       {
14114         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14115           PackageName);
14116         goto PerlException;
14117       }
14118     reference=SvRV(ST(0));
14119     av=newAV();
14120     SvREFCNT_dec(av);
14121     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14122     if (image == (Image *) NULL)
14123       {
14124         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14125           PackageName);
14126         goto PerlException;
14127       }
14128     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14129     count=0;
14130     for ( ; image; image=image->next)
14131     {
14132       channel_statistics=GetImageStatistics(image,exception);
14133       if (channel_statistics == (ChannelStatistics *) NULL)
14134         continue;
14135       count++;
14136       EXTEND(sp,35*count);
14137       scale=(double) QuantumRange;
14138       ChannelStatistics(RedChannel);
14139       ChannelStatistics(GreenChannel);
14140       ChannelStatistics(BlueChannel);
14141       if (image->colorspace == CMYKColorspace)
14142         ChannelStatistics(BlackChannel);
14143       if (image->alpha_trait == BlendPixelTrait)
14144         ChannelStatistics(AlphaChannel);
14145       channel_statistics=(ChannelStatistics *)
14146         RelinquishMagickMemory(channel_statistics);
14147     }
14148
14149   PerlException:
14150     InheritPerlException(exception,perl_exception);
14151     exception=DestroyExceptionInfo(exception);
14152     SvREFCNT_dec(perl_exception);
14153   }
14154 \f
14155 #
14156 ###############################################################################
14157 #                                                                             #
14158 #                                                                             #
14159 #                                                                             #
14160 #   S y n c A u t h e n t i c P i x e l s                                     #
14161 #                                                                             #
14162 #                                                                             #
14163 #                                                                             #
14164 ###############################################################################
14165 #
14166 #
14167 void
14168 SyncAuthenticPixels(ref,...)
14169   Image::Magick ref = NO_INIT
14170   ALIAS:
14171     Syncauthenticpixels = 1
14172     SyncImagePixels = 2
14173     syncimagepixels = 3
14174   CODE:
14175   {
14176     ExceptionInfo
14177       *exception;
14178
14179     Image
14180       *image;
14181
14182     MagickBooleanType
14183       status;
14184
14185     struct PackageInfo
14186       *info;
14187
14188     SV
14189       *perl_exception,
14190       *reference;
14191
14192     PERL_UNUSED_VAR(ref);
14193     PERL_UNUSED_VAR(ix);
14194     exception=AcquireExceptionInfo();
14195     perl_exception=newSVpv("",0);
14196     if (sv_isobject(ST(0)) == 0)
14197       {
14198         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14199           PackageName);
14200         goto PerlException;
14201       }
14202
14203     reference=SvRV(ST(0));
14204     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14205     if (image == (Image *) NULL)
14206       {
14207         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14208           PackageName);
14209         goto PerlException;
14210       }
14211
14212     status=SyncAuthenticPixels(image,exception);
14213     if (status != MagickFalse)
14214       return;
14215
14216   PerlException:
14217     InheritPerlException(exception,perl_exception);
14218     exception=DestroyExceptionInfo(exception);
14219     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14220   }
14221 \f
14222 #
14223 ###############################################################################
14224 #                                                                             #
14225 #                                                                             #
14226 #                                                                             #
14227 #   T r a n s f o r m                                                         #
14228 #                                                                             #
14229 #                                                                             #
14230 #                                                                             #
14231 ###############################################################################
14232 #
14233 #
14234 void
14235 Transform(ref,...)
14236   Image::Magick ref=NO_INIT
14237   ALIAS:
14238     TransformImage = 1
14239     transform      = 2
14240     transformimage = 3
14241   PPCODE:
14242   {
14243     AV
14244       *av;
14245
14246     char
14247       *attribute,
14248       *crop_geometry,
14249       *geometry;
14250
14251     ExceptionInfo
14252       *exception;
14253
14254     HV
14255       *hv;
14256
14257     Image
14258       *clone,
14259       *image;
14260
14261     register ssize_t
14262       i;
14263
14264     struct PackageInfo
14265       *info;
14266
14267     SV
14268       *av_reference,
14269       *perl_exception,
14270       *reference,
14271       *rv,
14272       *sv;
14273
14274     PERL_UNUSED_VAR(ref);
14275     PERL_UNUSED_VAR(ix);
14276     exception=AcquireExceptionInfo();
14277     perl_exception=newSVpv("",0);
14278     sv=NULL;
14279     av=NULL;
14280     attribute=NULL;
14281     if (sv_isobject(ST(0)) == 0)
14282       {
14283         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14284           PackageName);
14285         goto PerlException;
14286       }
14287     reference=SvRV(ST(0));
14288     hv=SvSTASH(reference);
14289     av=newAV();
14290     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14291     SvREFCNT_dec(av);
14292     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14293     if (image == (Image *) NULL)
14294       {
14295         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14296           PackageName);
14297         goto PerlException;
14298       }
14299     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14300     /*
14301       Get attribute.
14302     */
14303     crop_geometry=(char *) NULL;
14304     geometry=(char *) NULL;
14305     for (i=2; i < items; i+=2)
14306     {
14307       attribute=(char *) SvPV(ST(i-1),na);
14308       switch (*attribute)
14309       {
14310         case 'c':
14311         case 'C':
14312         {
14313           if (LocaleCompare(attribute,"crop") == 0)
14314             {
14315               crop_geometry=SvPV(ST(i),na);
14316               break;
14317             }
14318           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14319             attribute);
14320           break;
14321         }
14322         case 'g':
14323         case 'G':
14324         {
14325           if (LocaleCompare(attribute,"geometry") == 0)
14326             {
14327               geometry=SvPV(ST(i),na);
14328               break;
14329             }
14330           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14331             attribute);
14332           break;
14333         }
14334         default:
14335         {
14336           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14337             attribute);
14338           break;
14339         }
14340       }
14341     }
14342     for ( ; image; image=image->next)
14343     {
14344       clone=CloneImage(image,0,0,MagickTrue,exception);
14345       if (clone == (Image *) NULL)
14346         goto PerlException;
14347       TransformImage(&clone,crop_geometry,geometry,exception);
14348       for ( ; clone; clone=clone->next)
14349       {
14350         AddImageToRegistry(sv,clone);
14351         rv=newRV(sv);
14352         av_push(av,sv_bless(rv,hv));
14353         SvREFCNT_dec(sv);
14354       }
14355     }
14356     exception=DestroyExceptionInfo(exception);
14357     ST(0)=av_reference;
14358     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14359     XSRETURN(1);
14360
14361   PerlException:
14362     InheritPerlException(exception,perl_exception);
14363     exception=DestroyExceptionInfo(exception);
14364     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14365     SvPOK_on(perl_exception);
14366     ST(0)=sv_2mortal(perl_exception);
14367     XSRETURN(1);
14368   }
14369 \f
14370 #
14371 ###############################################################################
14372 #                                                                             #
14373 #                                                                             #
14374 #                                                                             #
14375 #   W r i t e                                                                 #
14376 #                                                                             #
14377 #                                                                             #
14378 #                                                                             #
14379 ###############################################################################
14380 #
14381 #
14382 void
14383 Write(ref,...)
14384   Image::Magick ref=NO_INIT
14385   ALIAS:
14386     WriteImage    = 1
14387     write         = 2
14388     writeimage    = 3
14389   PPCODE:
14390   {
14391     char
14392       filename[MaxTextExtent];
14393
14394     ExceptionInfo
14395       *exception;
14396
14397     Image
14398       *image,
14399       *next;
14400
14401     register ssize_t
14402       i;
14403
14404     ssize_t
14405       number_images,
14406       scene;
14407
14408     struct PackageInfo
14409       *info,
14410       *package_info;
14411
14412     SV
14413       *perl_exception,
14414       *reference;
14415
14416     PERL_UNUSED_VAR(ref);
14417     PERL_UNUSED_VAR(ix);
14418     exception=AcquireExceptionInfo();
14419     perl_exception=newSVpv("",0);
14420     number_images=0;
14421     package_info=(struct PackageInfo *) NULL;
14422     if (sv_isobject(ST(0)) == 0)
14423       {
14424         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14425           PackageName);
14426         goto PerlException;
14427       }
14428     reference=SvRV(ST(0));
14429     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14430     if (image == (Image *) NULL)
14431       {
14432         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14433           PackageName);
14434         goto PerlException;
14435       }
14436     package_info=ClonePackageInfo(info,exception);
14437     if (items == 2)
14438       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14439     else
14440       if (items > 2)
14441         for (i=2; i < items; i+=2)
14442           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14443             exception);
14444     (void) CopyMagickString(filename,package_info->image_info->filename,
14445       MaxTextExtent);
14446     scene=0;
14447     for (next=image; next; next=next->next)
14448     {
14449       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14450       next->scene=scene++;
14451     }
14452     SetImageInfo(package_info->image_info,(unsigned int)
14453       GetImageListLength(image),exception);
14454     for (next=image; next; next=next->next)
14455     {
14456       (void) WriteImage(package_info->image_info,next,exception);
14457       number_images++;
14458       if (package_info->image_info->adjoin)
14459         break;
14460     }
14461
14462   PerlException:
14463     if (package_info != (struct PackageInfo *) NULL)
14464       DestroyPackageInfo(package_info);
14465     InheritPerlException(exception,perl_exception);
14466     exception=DestroyExceptionInfo(exception);
14467     sv_setiv(perl_exception,(IV) number_images);
14468     SvPOK_on(perl_exception);
14469     ST(0)=sv_2mortal(perl_exception);
14470     XSRETURN(1);
14471   }