]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[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-2013 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       {"amount", 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   };
546
547 static SplayTreeInfo
548   *magick_registry = (SplayTreeInfo *) NULL;
549 \f
550 /*
551   Forward declarations.
552 */
553 static Image
554   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
555
556 static ssize_t
557   strEQcase(const char *,const char *);
558 \f
559 /*
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 %                                                                             %
562 %                                                                             %
563 %                                                                             %
564 %   C l o n e P a c k a g e I n f o                                           %
565 %                                                                             %
566 %                                                                             %
567 %                                                                             %
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569 %
570 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
571 %  a new one.
572 %
573 %  The format of the ClonePackageInfo routine is:
574 %
575 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
576 %        exception)
577 %
578 %  A description of each parameter follows:
579 %
580 %    o info: a structure of type info.
581 %
582 %    o exception: Return any errors or warnings in this structure.
583 %
584 */
585 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
586   ExceptionInfo *exception)
587 {
588   struct PackageInfo
589     *clone_info;
590
591   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
592   if (clone_info == (struct PackageInfo *) NULL)
593     {
594       ThrowPerlException(exception,ResourceLimitError,
595         "UnableToClonePackageInfo",PackageName);
596       return((struct PackageInfo *) NULL);
597     }
598   if (info == (struct PackageInfo *) NULL)
599     {
600       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
601       return(clone_info);
602     }
603   *clone_info=(*info);
604   clone_info->image_info=CloneImageInfo(info->image_info);
605   return(clone_info);
606 }
607 \f
608 /*
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 %                                                                             %
611 %                                                                             %
612 %                                                                             %
613 %   c o n s t a n t                                                           %
614 %                                                                             %
615 %                                                                             %
616 %                                                                             %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 %
619 %  constant() returns a double value for the specified name.
620 %
621 %  The format of the constant routine is:
622 %
623 %      double constant(char *name,ssize_t sans)
624 %
625 %  A description of each parameter follows:
626 %
627 %    o value: Method constant returns a double value for the specified name.
628 %
629 %    o name: The name of the constant.
630 %
631 %    o sans: This integer value is not used.
632 %
633 */
634 static double constant(char *name,ssize_t sans)
635 {
636   (void) sans;
637   errno=0;
638   switch (*name)
639   {
640     case 'B':
641     {
642       if (strEQ(name,"BlobError"))
643         return(BlobError);
644       if (strEQ(name,"BlobWarning"))
645         return(BlobWarning);
646       break;
647     }
648     case 'C':
649     {
650       if (strEQ(name,"CacheError"))
651         return(CacheError);
652       if (strEQ(name,"CacheWarning"))
653         return(CacheWarning);
654       if (strEQ(name,"CoderError"))
655         return(CoderError);
656       if (strEQ(name,"CoderWarning"))
657         return(CoderWarning);
658       if (strEQ(name,"ConfigureError"))
659         return(ConfigureError);
660       if (strEQ(name,"ConfigureWarning"))
661         return(ConfigureWarning);
662       if (strEQ(name,"CorruptImageError"))
663         return(CorruptImageError);
664       if (strEQ(name,"CorruptImageWarning"))
665         return(CorruptImageWarning);
666       break;
667     }
668     case 'D':
669     {
670       if (strEQ(name,"DelegateError"))
671         return(DelegateError);
672       if (strEQ(name,"DelegateWarning"))
673         return(DelegateWarning);
674       if (strEQ(name,"DrawError"))
675         return(DrawError);
676       if (strEQ(name,"DrawWarning"))
677         return(DrawWarning);
678       break;
679     }
680     case 'E':
681     {
682       if (strEQ(name,"ErrorException"))
683         return(ErrorException);
684       if (strEQ(name,"ExceptionError"))
685         return(CoderError);
686       if (strEQ(name,"ExceptionWarning"))
687         return(CoderWarning);
688       break;
689     }
690     case 'F':
691     {
692       if (strEQ(name,"FatalErrorException"))
693         return(FatalErrorException);
694       if (strEQ(name,"FileOpenError"))
695         return(FileOpenError);
696       if (strEQ(name,"FileOpenWarning"))
697         return(FileOpenWarning);
698       break;
699     }
700     case 'I':
701     {
702       if (strEQ(name,"ImageError"))
703         return(ImageError);
704       if (strEQ(name,"ImageWarning"))
705         return(ImageWarning);
706       break;
707     }
708     case 'M':
709     {
710       if (strEQ(name,"MaxRGB"))
711         return(QuantumRange);
712       if (strEQ(name,"MissingDelegateError"))
713         return(MissingDelegateError);
714       if (strEQ(name,"MissingDelegateWarning"))
715         return(MissingDelegateWarning);
716       if (strEQ(name,"ModuleError"))
717         return(ModuleError);
718       if (strEQ(name,"ModuleWarning"))
719         return(ModuleWarning);
720       break;
721     }
722     case 'O':
723     {
724       if (strEQ(name,"Opaque"))
725         return(OpaqueAlpha);
726       if (strEQ(name,"OptionError"))
727         return(OptionError);
728       if (strEQ(name,"OptionWarning"))
729         return(OptionWarning);
730       break;
731     }
732     case 'Q':
733     {
734       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
735         return(MAGICKCORE_QUANTUM_DEPTH);
736       if (strEQ(name,"QuantumDepth"))
737         return(MAGICKCORE_QUANTUM_DEPTH);
738       if (strEQ(name,"QuantumRange"))
739         return(QuantumRange);
740       break;
741     }
742     case 'R':
743     {
744       if (strEQ(name,"ResourceLimitError"))
745         return(ResourceLimitError);
746       if (strEQ(name,"ResourceLimitWarning"))
747         return(ResourceLimitWarning);
748       if (strEQ(name,"RegistryError"))
749         return(RegistryError);
750       if (strEQ(name,"RegistryWarning"))
751         return(RegistryWarning);
752       break;
753     }
754     case 'S':
755     {
756       if (strEQ(name,"StreamError"))
757         return(StreamError);
758       if (strEQ(name,"StreamWarning"))
759         return(StreamWarning);
760       if (strEQ(name,"Success"))
761         return(0);
762       break;
763     }
764     case 'T':
765     {
766       if (strEQ(name,"Transparent"))
767         return(TransparentAlpha);
768       if (strEQ(name,"TypeError"))
769         return(TypeError);
770       if (strEQ(name,"TypeWarning"))
771         return(TypeWarning);
772       break;
773     }
774     case 'W':
775     {
776       if (strEQ(name,"WarningException"))
777         return(WarningException);
778       break;
779     }
780     case 'X':
781     {
782       if (strEQ(name,"XServerError"))
783         return(XServerError);
784       if (strEQ(name,"XServerWarning"))
785         return(XServerWarning);
786       break;
787     }
788   }
789   errno=EINVAL;
790   return(0);
791 }
792 \f
793 /*
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %                                                                             %
796 %                                                                             %
797 %                                                                             %
798 %   D e s t r o y P a c k a g e I n f o                                       %
799 %                                                                             %
800 %                                                                             %
801 %                                                                             %
802 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
803 %
804 %  Method DestroyPackageInfo frees a previously created info structure.
805 %
806 %  The format of the DestroyPackageInfo routine is:
807 %
808 %      DestroyPackageInfo(struct PackageInfo *info)
809 %
810 %  A description of each parameter follows:
811 %
812 %    o info: a structure of type info.
813 %
814 */
815 static void DestroyPackageInfo(struct PackageInfo *info)
816 {
817   info->image_info=DestroyImageInfo(info->image_info);
818   info=(struct PackageInfo *) RelinquishMagickMemory(info);
819 }
820 \f
821 /*
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 %                                                                             %
824 %                                                                             %
825 %                                                                             %
826 %   G e t L i s t                                                             %
827 %                                                                             %
828 %                                                                             %
829 %                                                                             %
830 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831 %
832 %  Method GetList is recursively called by SetupList to traverse the
833 %  Image__Magick reference.  If building an reference_vector (see SetupList),
834 %  *current is the current position in *reference_vector and *last is the final
835 %  entry in *reference_vector.
836 %
837 %  The format of the GetList routine is:
838 %
839 %      GetList(info)
840 %
841 %  A description of each parameter follows:
842 %
843 %    o info: a structure of type info.
844 %
845 */
846 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
847   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
848 {
849   Image
850     *image;
851
852   if (reference == (SV *) NULL)
853     return(NULL);
854   switch (SvTYPE(reference))
855   {
856     case SVt_PVAV:
857     {
858       AV
859         *av;
860
861       Image
862         *head,
863         *previous;
864
865       register ssize_t
866         i;
867
868       ssize_t
869         n;
870
871       /*
872         Array of images.
873       */
874       previous=(Image *) NULL;
875       head=(Image *) NULL;
876       av=(AV *) reference;
877       n=av_len(av);
878       for (i=0; i <= n; i++)
879       {
880         SV
881           **rv;
882
883         rv=av_fetch(av,i,0);
884         if (rv && *rv && sv_isobject(*rv))
885           {
886             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
887               exception);
888             if (image == (Image *) NULL)
889               continue;
890             if (image == previous)
891               {
892                 image=CloneImage(image,0,0,MagickTrue,exception);
893                 if (image == (Image *) NULL)
894                   return(NULL);
895               }
896             image->previous=previous;
897             *(previous ? &previous->next : &head)=image;
898             for (previous=image; previous->next; previous=previous->next) ;
899           }
900       }
901       return(head);
902     }
903     case SVt_PVMG:
904     {
905       /*
906         Blessed scalar, one image.
907       */
908       image=INT2PTR(Image *,SvIV(reference));
909       if (image == (Image *) NULL)
910         return(NULL);
911       image->previous=(Image *) NULL;
912       image->next=(Image *) NULL;
913       if (reference_vector)
914         {
915           if (*current == *last)
916             {
917               *last+=256;
918               if (*reference_vector == (SV **) NULL)
919                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
920                   sizeof(*reference_vector));
921               else
922                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
923                   *last,sizeof(*reference_vector));
924             }
925           if (*reference_vector == (SV **) NULL)
926             {
927               ThrowPerlException(exception,ResourceLimitError,
928                 "MemoryAllocationFailed",PackageName);
929               return((Image *) NULL);
930             }
931           (*reference_vector)[*current]=reference;
932           (*reference_vector)[++(*current)]=NULL;
933         }
934       return(image);
935     }
936     default:
937       break;
938   }
939   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
940     (double) SvTYPE(reference));
941   return((Image *) NULL);
942 }
943 \f
944 /*
945 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 %                                                                             %
947 %                                                                             %
948 %                                                                             %
949 %   G e t P a c k a g e I n f o                                               %
950 %                                                                             %
951 %                                                                             %
952 %                                                                             %
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
954 %
955 %  Method GetPackageInfo looks up or creates an info structure for the given
956 %  Image__Magick reference.  If it does create a new one, the information in
957 %  package_info is used to initialize it.
958 %
959 %  The format of the GetPackageInfo routine is:
960 %
961 %      struct PackageInfo *GetPackageInfo(void *reference,
962 %        struct PackageInfo *package_info,ExceptionInfo *exception)
963 %
964 %  A description of each parameter follows:
965 %
966 %    o info: a structure of type info.
967 %
968 %    o exception: Return any errors or warnings in this structure.
969 %
970 */
971 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
972   struct PackageInfo *package_info,ExceptionInfo *exception)
973 {
974   char
975     message[MaxTextExtent];
976
977   struct PackageInfo
978     *clone_info;
979
980   SV
981     *sv;
982
983   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
984     PackageName,XS_VERSION,reference);
985   sv=perl_get_sv(message,(TRUE | 0x02));
986   if (sv == (SV *) NULL)
987     {
988       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
989         message);
990       return(package_info);
991     }
992   if (SvREFCNT(sv) == 0)
993     (void) SvREFCNT_inc(sv);
994   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
995     return(clone_info);
996   clone_info=ClonePackageInfo(package_info,exception);
997   sv_setiv(sv,PTR2IV(clone_info));
998   return(clone_info);
999 }
1000 \f
1001 /*
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1003 %                                                                             %
1004 %                                                                             %
1005 %                                                                             %
1006 %   S e t A t t r i b u t e                                                   %
1007 %                                                                             %
1008 %                                                                             %
1009 %                                                                             %
1010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1011 %
1012 %  SetAttribute() sets the attribute to the value in sval.  This can change
1013 %  either or both of image or info.
1014 %
1015 %  The format of the SetAttribute routine is:
1016 %
1017 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1018 %        SV *sval,ExceptionInfo *exception)
1019 %
1020 %  A description of each parameter follows:
1021 %
1022 %    o list: a list of strings.
1023 %
1024 %    o string: a character string.
1025 %
1026 */
1027
1028 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1029 {
1030   char
1031     *q;
1032
1033   double
1034     value;
1035
1036   value=InterpretSiPrefixValue(string,&q);
1037   if (*q == '%')
1038     value*=interval/100.0;
1039   return(value);
1040 }
1041
1042 static inline double StringToDouble(const char *string,char **sentinal)
1043 {
1044   return(InterpretLocaleValue(string,sentinal));
1045 }
1046
1047 static double StringToDoubleInterval(const char *string,const double interval)
1048 {
1049   char
1050     *q;
1051
1052   double
1053     value;
1054
1055   value=InterpretLocaleValue(string,&q);
1056   if (*q == '%')
1057     value*=interval/100.0;
1058   return(value);
1059 }
1060
1061 static inline ssize_t StringToLong(const char *value)
1062 {
1063   return(strtol(value,(char **) NULL,10));
1064 }
1065
1066 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1067   const char *attribute,SV *sval,ExceptionInfo *exception)
1068 {
1069   GeometryInfo
1070     geometry_info;
1071
1072   long
1073     x,
1074     y;
1075
1076   PixelInfo
1077     pixel;
1078
1079   MagickStatusType
1080     flags;
1081
1082   PixelInfo
1083     *color,
1084     target_color;
1085
1086   ssize_t
1087     sp;
1088
1089   switch (*attribute)
1090   {
1091     case 'A':
1092     case 'a':
1093     {
1094       if (LocaleCompare(attribute,"adjoin") == 0)
1095         {
1096           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1097             SvPV(sval,na)) : SvIV(sval);
1098           if (sp < 0)
1099             {
1100               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1101                 SvPV(sval,na));
1102               break;
1103             }
1104           if (info)
1105             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1106           break;
1107         }
1108       if (LocaleCompare(attribute,"alpha") == 0)
1109         {
1110           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,MagickFalse,
1111             SvPV(sval,na)) : SvIV(sval);
1112           if (sp < 0)
1113             {
1114               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1115                 SvPV(sval,na));
1116               break;
1117             }
1118           for ( ; image; image=image->next)
1119             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,exception);
1120           break;
1121         }
1122       if (LocaleCompare(attribute,"antialias") == 0)
1123         {
1124           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1125             SvPV(sval,na)) : SvIV(sval);
1126           if (sp < 0)
1127             {
1128               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1129                 SvPV(sval,na));
1130               break;
1131             }
1132           if (info)
1133             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1134           break;
1135         }
1136       if (LocaleCompare(attribute,"area-limit") == 0)
1137         {
1138           MagickSizeType
1139             limit;
1140
1141           limit=MagickResourceInfinity;
1142           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1143             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1144               100.0);
1145           (void) SetMagickResourceLimit(AreaResource,limit);
1146           break;
1147         }
1148       if (LocaleCompare(attribute,"attenuate") == 0)
1149         {
1150           if (info)
1151             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1152           break;
1153         }
1154       if (LocaleCompare(attribute,"authenticate") == 0)
1155         {
1156           if (info)
1157             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1158           break;
1159         }
1160       if (info)
1161         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1162       for ( ; image; image=image->next)
1163         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1164       break;
1165     }
1166     case 'B':
1167     case 'b':
1168     {
1169       if (LocaleCompare(attribute,"background") == 0)
1170         {
1171           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1172             exception);
1173           if (info)
1174             info->image_info->background_color=target_color;
1175           for ( ; image; image=image->next)
1176             image->background_color=target_color;
1177           break;
1178         }
1179       if (LocaleCompare(attribute,"blue-primary") == 0)
1180         {
1181           for ( ; image; image=image->next)
1182           {
1183             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1184             image->chromaticity.blue_primary.x=geometry_info.rho;
1185             image->chromaticity.blue_primary.y=geometry_info.sigma;
1186             if ((flags & SigmaValue) == 0)
1187               image->chromaticity.blue_primary.y=
1188                 image->chromaticity.blue_primary.x;
1189           }
1190           break;
1191         }
1192       if (LocaleCompare(attribute,"bordercolor") == 0)
1193         {
1194           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1195             exception);
1196           if (info)
1197             info->image_info->border_color=target_color;
1198           for ( ; image; image=image->next)
1199             image->border_color=target_color;
1200           break;
1201         }
1202       if (info)
1203         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1204       for ( ; image; image=image->next)
1205         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1206       break;
1207     }
1208     case 'C':
1209     case 'c':
1210     {
1211       if (LocaleCompare(attribute,"cache-threshold") == 0)
1212         {
1213           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1214             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1215           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1216             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1217           break;
1218         }
1219       if (LocaleCompare(attribute,"clip-mask") == 0)
1220         {
1221           Image
1222             *clip_mask;
1223
1224           clip_mask=(Image *) NULL;
1225           if (SvPOK(sval))
1226             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1227           for ( ; image; image=image->next)
1228             SetImageMask(image,clip_mask,exception);
1229           break;
1230         }
1231       if (LocaleNCompare(attribute,"colormap",8) == 0)
1232         {
1233           for ( ; image; image=image->next)
1234           {
1235             int
1236               items;
1237
1238             long
1239               i;
1240
1241             if (image->storage_class == DirectClass)
1242               continue;
1243             i=0;
1244             items=sscanf(attribute,"%*[^[][%ld",&i);
1245             (void) items;
1246             if (i > (ssize_t) image->colors)
1247               i%=image->colors;
1248             if ((strchr(SvPV(sval,na),',') == 0) ||
1249                 (strchr(SvPV(sval,na),')') != 0))
1250               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1251                 image->colormap+i,exception);
1252             else
1253               {
1254                 color=image->colormap+i;
1255                 pixel.red=color->red;
1256                 pixel.green=color->green;
1257                 pixel.blue=color->blue;
1258                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1259                 pixel.red=geometry_info.rho;
1260                 pixel.green=geometry_info.sigma;
1261                 pixel.blue=geometry_info.xi;
1262                 color->red=ClampToQuantum(pixel.red);
1263                 color->green=ClampToQuantum(pixel.green);
1264                 color->blue=ClampToQuantum(pixel.blue);
1265               }
1266           }
1267           break;
1268         }
1269       if (LocaleCompare(attribute,"colorspace") == 0)
1270         {
1271           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1272             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1273           if (sp < 0)
1274             {
1275               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1276                 SvPV(sval,na));
1277               break;
1278             }
1279           for ( ; image; image=image->next)
1280             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1281               exception);
1282           break;
1283         }
1284       if (LocaleCompare(attribute,"comment") == 0)
1285         {
1286           for ( ; image; image=image->next)
1287             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1288               info ? info->image_info : (ImageInfo *) NULL,image,
1289               SvPV(sval,na),exception),exception);
1290           break;
1291         }
1292       if (LocaleCompare(attribute,"compression") == 0)
1293         {
1294           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1295             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1296           if (sp < 0)
1297             {
1298               ThrowPerlException(exception,OptionError,
1299                 "UnrecognizedImageCompression",SvPV(sval,na));
1300               break;
1301             }
1302           if (info)
1303             info->image_info->compression=(CompressionType) sp;
1304           for ( ; image; image=image->next)
1305             image->compression=(CompressionType) sp;
1306           break;
1307         }
1308       if (info)
1309         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1310       for ( ; image; image=image->next)
1311         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1312       break;
1313     }
1314     case 'D':
1315     case 'd':
1316     {
1317       if (LocaleCompare(attribute,"debug") == 0)
1318         {
1319           SetLogEventMask(SvPV(sval,na));
1320           break;
1321         }
1322       if (LocaleCompare(attribute,"delay") == 0)
1323         {
1324           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1325           for ( ; image; image=image->next)
1326           {
1327             image->delay=(size_t) floor(geometry_info.rho+0.5);
1328             if ((flags & SigmaValue) != 0)
1329               image->ticks_per_second=(ssize_t)
1330                 floor(geometry_info.sigma+0.5);
1331           }
1332           break;
1333         }
1334       if (LocaleCompare(attribute,"disk-limit") == 0)
1335         {
1336           MagickSizeType
1337             limit;
1338
1339           limit=MagickResourceInfinity;
1340           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1341             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1342               100.0);
1343           (void) SetMagickResourceLimit(DiskResource,limit);
1344           break;
1345         }
1346       if (LocaleCompare(attribute,"density") == 0)
1347         {
1348           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1349             {
1350               ThrowPerlException(exception,OptionError,"MissingGeometry",
1351                 SvPV(sval,na));
1352               break;
1353             }
1354           if (info)
1355             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1356           for ( ; image; image=image->next)
1357           {
1358             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1359             image->resolution.x=geometry_info.rho;
1360             image->resolution.y=geometry_info.sigma;
1361             if ((flags & SigmaValue) == 0)
1362               image->resolution.y=image->resolution.x;
1363           }
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"depth") == 0)
1367         {
1368           if (info)
1369             info->image_info->depth=SvIV(sval);
1370           for ( ; image; image=image->next)
1371             (void) SetImageDepth(image,SvIV(sval),exception);
1372           break;
1373         }
1374       if (LocaleCompare(attribute,"dispose") == 0)
1375         {
1376           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1377             SvPV(sval,na)) : SvIV(sval);
1378           if (sp < 0)
1379             {
1380               ThrowPerlException(exception,OptionError,
1381                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1382               break;
1383             }
1384           for ( ; image; image=image->next)
1385             image->dispose=(DisposeType) sp;
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"dither") == 0)
1389         {
1390           if (info)
1391             {
1392               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1393                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1394               if (sp < 0)
1395                 {
1396                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1397                     SvPV(sval,na));
1398                   break;
1399                 }
1400               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1401             }
1402           break;
1403         }
1404       if (LocaleCompare(attribute,"display") == 0)
1405         {
1406           display:
1407           if (info)
1408             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1409           break;
1410         }
1411       if (info)
1412         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1413       for ( ; image; image=image->next)
1414         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1415       break;
1416     }
1417     case 'E':
1418     case 'e':
1419     {
1420       if (LocaleCompare(attribute,"endian") == 0)
1421         {
1422           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1423             SvPV(sval,na)) : SvIV(sval);
1424           if (sp < 0)
1425             {
1426               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1427                 SvPV(sval,na));
1428               break;
1429             }
1430           if (info)
1431             info->image_info->endian=(EndianType) sp;
1432           for ( ; image; image=image->next)
1433             image->endian=(EndianType) sp;
1434           break;
1435         }
1436       if (LocaleCompare(attribute,"extract") == 0)
1437         {
1438           /*
1439             Set image extract geometry.
1440           */
1441           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1442           break;
1443         }
1444       if (info)
1445         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1446       for ( ; image; image=image->next)
1447         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1448       break;
1449     }
1450     case 'F':
1451     case 'f':
1452     {
1453       if (LocaleCompare(attribute,"filename") == 0)
1454         {
1455           if (info)
1456             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1457               MaxTextExtent);
1458           for ( ; image; image=image->next)
1459             (void) CopyMagickString(image->filename,SvPV(sval,na),
1460               MaxTextExtent);
1461           break;
1462         }
1463       if (LocaleCompare(attribute,"file") == 0)
1464         {
1465           FILE
1466             *file;
1467
1468           PerlIO
1469             *io_info;
1470
1471           if (info == (struct PackageInfo *) NULL)
1472             break;
1473           io_info=IoIFP(sv_2io(sval));
1474           if (io_info == (PerlIO *) NULL)
1475             {
1476               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1477                 PackageName);
1478               break;
1479             }
1480           file=PerlIO_findFILE(io_info);
1481           if (file == (FILE *) NULL)
1482             {
1483               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1484                 PackageName);
1485               break;
1486             }
1487           SetImageInfoFile(info->image_info,file);
1488           break;
1489         }
1490       if (LocaleCompare(attribute,"fill") == 0)
1491         {
1492           if (info)
1493             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1494           break;
1495         }
1496       if (LocaleCompare(attribute,"font") == 0)
1497         {
1498           if (info)
1499             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1500           break;
1501         }
1502       if (LocaleCompare(attribute,"foreground") == 0)
1503         break;
1504       if (LocaleCompare(attribute,"fuzz") == 0)
1505         {
1506           if (info)
1507             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1508               QuantumRange+1.0);
1509           for ( ; image; image=image->next)
1510             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1511               QuantumRange+1.0);
1512           break;
1513         }
1514       if (info)
1515         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1516       for ( ; image; image=image->next)
1517         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1518       break;
1519     }
1520     case 'G':
1521     case 'g':
1522     {
1523       if (LocaleCompare(attribute,"gamma") == 0)
1524         {
1525           for ( ; image; image=image->next)
1526             image->gamma=SvNV(sval);
1527           break;
1528         }
1529       if (LocaleCompare(attribute,"gravity") == 0)
1530         {
1531           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1532             SvPV(sval,na)) : SvIV(sval);
1533           if (sp < 0)
1534             {
1535               ThrowPerlException(exception,OptionError,
1536                 "UnrecognizedGravityType",SvPV(sval,na));
1537               break;
1538             }
1539           if (info)
1540             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1541           for ( ; image; image=image->next)
1542             image->gravity=(GravityType) sp;
1543           break;
1544         }
1545       if (LocaleCompare(attribute,"green-primary") == 0)
1546         {
1547           for ( ; image; image=image->next)
1548           {
1549             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1550             image->chromaticity.green_primary.x=geometry_info.rho;
1551             image->chromaticity.green_primary.y=geometry_info.sigma;
1552             if ((flags & SigmaValue) == 0)
1553               image->chromaticity.green_primary.y=
1554                 image->chromaticity.green_primary.x;
1555           }
1556           break;
1557         }
1558       if (info)
1559         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1560       for ( ; image; image=image->next)
1561         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1562       break;
1563     }
1564     case 'I':
1565     case 'i':
1566     {
1567       if (LocaleNCompare(attribute,"index",5) == 0)
1568         {
1569           int
1570             items;
1571
1572           long
1573             index;
1574
1575           register Quantum
1576             *q;
1577
1578           CacheView
1579             *image_view;
1580
1581           for ( ; image; image=image->next)
1582           {
1583             if (image->storage_class != PseudoClass)
1584               continue;
1585             x=0;
1586             y=0;
1587             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1588             (void) items;
1589             image_view=AcquireAuthenticCacheView(image,exception);
1590             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1591             if (q != (Quantum *) NULL)
1592               {
1593                 items=sscanf(SvPV(sval,na),"%ld",&index);
1594                 if ((index >= 0) && (index < (ssize_t) image->colors))
1595                   SetPixelIndex(image,index,q);
1596                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1597               }
1598             image_view=DestroyCacheView(image_view);
1599           }
1600           break;
1601         }
1602       if (LocaleCompare(attribute,"iterations") == 0)
1603         {
1604   iterations:
1605           for ( ; image; image=image->next)
1606             image->iterations=SvIV(sval);
1607           break;
1608         }
1609       if (LocaleCompare(attribute,"interlace") == 0)
1610         {
1611           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1612             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1613           if (sp < 0)
1614             {
1615               ThrowPerlException(exception,OptionError,
1616                 "UnrecognizedInterlaceType",SvPV(sval,na));
1617               break;
1618             }
1619           if (info)
1620             info->image_info->interlace=(InterlaceType) sp;
1621           for ( ; image; image=image->next)
1622             image->interlace=(InterlaceType) sp;
1623           break;
1624         }
1625       if (info)
1626         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1627       for ( ; image; image=image->next)
1628         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1629       break;
1630     }
1631     case 'L':
1632     case 'l':
1633     {
1634       if (LocaleCompare(attribute,"label") == 0)
1635         {
1636           for ( ; image; image=image->next)
1637             (void) SetImageProperty(image,"label",InterpretImageProperties(
1638               info ? info->image_info : (ImageInfo *) NULL,image,
1639               SvPV(sval,na),exception),exception);
1640           break;
1641         }
1642       if (LocaleCompare(attribute,"loop") == 0)
1643         goto iterations;
1644       if (info)
1645         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1646       for ( ; image; image=image->next)
1647         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1648       break;
1649     }
1650     case 'M':
1651     case 'm':
1652     {
1653       if (LocaleCompare(attribute,"magick") == 0)
1654         {
1655           if (info)
1656             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1657               "%s:",SvPV(sval,na));
1658           for ( ; image; image=image->next)
1659             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1660           break;
1661         }
1662       if (LocaleCompare(attribute,"map-limit") == 0)
1663         {
1664           MagickSizeType
1665             limit;
1666
1667           limit=MagickResourceInfinity;
1668           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1669             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1670               100.0);
1671           (void) SetMagickResourceLimit(MapResource,limit);
1672           break;
1673         }
1674       if (LocaleCompare(attribute,"mask") == 0)
1675         {
1676           Image
1677             *mask;
1678
1679           mask=(Image *) NULL;
1680           if (SvPOK(sval))
1681             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1682           for ( ; image; image=image->next)
1683             SetImageMask(image,mask,exception);
1684           break;
1685         }
1686       if (LocaleCompare(attribute,"mattecolor") == 0)
1687         {
1688           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1689             exception);
1690           if (info)
1691             info->image_info->matte_color=target_color;
1692           for ( ; image; image=image->next)
1693             image->matte_color=target_color;
1694           break;
1695         }
1696       if (LocaleCompare(attribute,"matte") == 0)
1697         {
1698           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1699             SvPV(sval,na)) : SvIV(sval);
1700           if (sp < 0)
1701             {
1702               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1703                 SvPV(sval,na));
1704               break;
1705             }
1706           for ( ; image; image=image->next)
1707             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1708           break;
1709         }
1710       if (LocaleCompare(attribute,"memory-limit") == 0)
1711         {
1712           MagickSizeType
1713             limit;
1714
1715           limit=MagickResourceInfinity;
1716           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1717             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1718               100.0);
1719           (void) SetMagickResourceLimit(MemoryResource,limit);
1720           break;
1721         }
1722       if (LocaleCompare(attribute,"monochrome") == 0)
1723         {
1724           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1725             SvPV(sval,na)) : SvIV(sval);
1726           if (sp < 0)
1727             {
1728               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1729                 SvPV(sval,na));
1730               break;
1731             }
1732           if (info)
1733             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1734           for ( ; image; image=image->next)
1735             (void) SetImageType(image,BilevelType,exception);
1736           break;
1737         }
1738       if (info)
1739         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1740       for ( ; image; image=image->next)
1741         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1742       break;
1743     }
1744     case 'O':
1745     case 'o':
1746     {
1747       if (LocaleCompare(attribute,"option") == 0)
1748         {
1749           if (info)
1750             DefineImageOption(info->image_info,SvPV(sval,na));
1751           break;
1752         }
1753       if (LocaleCompare(attribute,"orientation") == 0)
1754         {
1755           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1756             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1757           if (sp < 0)
1758             {
1759               ThrowPerlException(exception,OptionError,
1760                 "UnrecognizedOrientationType",SvPV(sval,na));
1761               break;
1762             }
1763           if (info)
1764             info->image_info->orientation=(OrientationType) sp;
1765           for ( ; image; image=image->next)
1766             image->orientation=(OrientationType) sp;
1767           break;
1768         }
1769       if (info)
1770         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1771       for ( ; image; image=image->next)
1772         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1773       break;
1774     }
1775     case 'P':
1776     case 'p':
1777     {
1778       if (LocaleCompare(attribute,"page") == 0)
1779         {
1780           char
1781             *geometry;
1782
1783           geometry=GetPageGeometry(SvPV(sval,na));
1784           if (info)
1785             (void) CloneString(&info->image_info->page,geometry);
1786           for ( ; image; image=image->next)
1787             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1788           geometry=(char *) RelinquishMagickMemory(geometry);
1789           break;
1790         }
1791       if (LocaleNCompare(attribute,"pixel",5) == 0)
1792         {
1793           int
1794             items;
1795
1796           PixelInfo
1797             pixel;
1798
1799           register Quantum
1800             *q;
1801
1802           CacheView
1803             *image_view;
1804
1805           for ( ; image; image=image->next)
1806           {
1807             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1808               break;
1809             x=0;
1810             y=0;
1811             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1812             (void) items;
1813             image_view=AcquireVirtualCacheView(image,exception);
1814             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1815             if (q != (Quantum *) NULL)
1816               {
1817                 if ((strchr(SvPV(sval,na),',') == 0) ||
1818                     (strchr(SvPV(sval,na),')') != 0))
1819                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1820                     &pixel,exception);
1821                 else
1822                   {
1823                     GetPixelInfo(image,&pixel);
1824                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1825                     pixel.red=geometry_info.rho;
1826                     if ((flags & SigmaValue) != 0)
1827                       pixel.green=geometry_info.sigma;
1828                     if ((flags & XiValue) != 0)
1829                       pixel.blue=geometry_info.xi;
1830                     if ((flags & PsiValue) != 0)
1831                       pixel.alpha=geometry_info.psi;
1832                     if ((flags & ChiValue) != 0)
1833                       pixel.black=geometry_info.chi;
1834                   }
1835                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1836                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1837                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1838                 if (image->colorspace == CMYKColorspace)
1839                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1840                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1841                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1842               }
1843             image_view=DestroyCacheView(image_view);
1844           }
1845           break;
1846         }
1847       if (LocaleCompare(attribute,"pointsize") == 0)
1848         {
1849           if (info)
1850             {
1851               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1852               info->image_info->pointsize=geometry_info.rho;
1853             }
1854           break;
1855         }
1856       if (LocaleCompare(attribute,"preview") == 0)
1857         {
1858           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1859             SvPV(sval,na)) : SvIV(sval);
1860           if (sp < 0)
1861             {
1862               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1863                 SvPV(sval,na));
1864               break;
1865             }
1866           if (info)
1867             info->image_info->preview_type=(PreviewType) sp;
1868           break;
1869         }
1870       if (info)
1871         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1872       for ( ; image; image=image->next)
1873         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1874       break;
1875     }
1876     case 'Q':
1877     case 'q':
1878     {
1879       if (LocaleCompare(attribute,"quality") == 0)
1880         {
1881           if (info)
1882             info->image_info->quality=SvIV(sval);
1883           for ( ; image; image=image->next)
1884             image->quality=SvIV(sval);
1885           break;
1886         }
1887       if (info)
1888         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1889       for ( ; image; image=image->next)
1890         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1891       break;
1892     }
1893     case 'R':
1894     case 'r':
1895     {
1896       if (LocaleCompare(attribute,"red-primary") == 0)
1897         {
1898           for ( ; image; image=image->next)
1899           {
1900             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1901             image->chromaticity.red_primary.x=geometry_info.rho;
1902             image->chromaticity.red_primary.y=geometry_info.sigma;
1903             if ((flags & SigmaValue) == 0)
1904               image->chromaticity.red_primary.y=
1905                 image->chromaticity.red_primary.x;
1906           }
1907           break;
1908         }
1909       if (LocaleCompare(attribute,"render") == 0)
1910         {
1911           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1912             SvPV(sval,na)) : SvIV(sval);
1913           if (sp < 0)
1914             {
1915               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1916                 SvPV(sval,na));
1917               break;
1918             }
1919          for ( ; image; image=image->next)
1920            image->rendering_intent=(RenderingIntent) sp;
1921          break;
1922        }
1923       if (LocaleCompare(attribute,"repage") == 0)
1924         {
1925           RectangleInfo
1926             geometry;
1927
1928           for ( ; image; image=image->next)
1929           {
1930             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1931             if ((flags & WidthValue) != 0)
1932               {
1933                 if ((flags & HeightValue) == 0)
1934                   geometry.height=geometry.width;
1935                 image->page.width=geometry.width;
1936                 image->page.height=geometry.height;
1937               }
1938             if ((flags & AspectValue) != 0)
1939               {
1940                 if ((flags & XValue) != 0)
1941                   image->page.x+=geometry.x;
1942                 if ((flags & YValue) != 0)
1943                   image->page.y+=geometry.y;
1944               }
1945             else
1946               {
1947                 if ((flags & XValue) != 0)
1948                   {
1949                     image->page.x=geometry.x;
1950                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1951                       image->page.width=image->columns+geometry.x;
1952                   }
1953                 if ((flags & YValue) != 0)
1954                   {
1955                     image->page.y=geometry.y;
1956                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1957                       image->page.height=image->rows+geometry.y;
1958                   }
1959               }
1960           }
1961           break;
1962         }
1963       if (info)
1964         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1965       for ( ; image; image=image->next)
1966         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1967       break;
1968     }
1969     case 'S':
1970     case 's':
1971     {
1972       if (LocaleCompare(attribute,"sampling-factor") == 0)
1973         {
1974           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1975             {
1976               ThrowPerlException(exception,OptionError,"MissingGeometry",
1977                 SvPV(sval,na));
1978               break;
1979             }
1980           if (info)
1981             (void) CloneString(&info->image_info->sampling_factor,
1982               SvPV(sval,na));
1983           break;
1984         }
1985       if (LocaleCompare(attribute,"scene") == 0)
1986         {
1987           for ( ; image; image=image->next)
1988             image->scene=SvIV(sval);
1989           break;
1990         }
1991       if (LocaleCompare(attribute,"server") == 0)
1992         goto display;
1993       if (LocaleCompare(attribute,"size") == 0)
1994         {
1995           if (info)
1996             {
1997               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1998                 {
1999                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2000                     SvPV(sval,na));
2001                   break;
2002                 }
2003               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2004             }
2005           break;
2006         }
2007       if (LocaleCompare(attribute,"stroke") == 0)
2008         {
2009           if (info)
2010             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2011           break;
2012         }
2013       if (info)
2014         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2015       for ( ; image; image=image->next)
2016         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2017       break;
2018     }
2019     case 'T':
2020     case 't':
2021     {
2022       if (LocaleCompare(attribute,"texture") == 0)
2023         {
2024           if (info)
2025             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2026           break;
2027         }
2028       if (LocaleCompare(attribute,"thread-limit") == 0)
2029         {
2030           MagickSizeType
2031             limit;
2032
2033           limit=MagickResourceInfinity;
2034           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2035             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2036               100.0);
2037           (void) SetMagickResourceLimit(ThreadResource,limit);
2038           break;
2039         }
2040       if (LocaleCompare(attribute,"tile-offset") == 0)
2041         {
2042           char
2043             *geometry;
2044
2045           geometry=GetPageGeometry(SvPV(sval,na));
2046           if (info)
2047             (void) CloneString(&info->image_info->page,geometry);
2048           for ( ; image; image=image->next)
2049             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2050               exception);
2051           geometry=(char *) RelinquishMagickMemory(geometry);
2052           break;
2053         }
2054       if (LocaleCompare(attribute,"time-limit") == 0)
2055         {
2056           MagickSizeType
2057             limit;
2058
2059           limit=MagickResourceInfinity;
2060           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2061             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2062               100.0);
2063           (void) SetMagickResourceLimit(TimeResource,limit);
2064           break;
2065         }
2066       if (LocaleCompare(attribute,"transparent-color") == 0)
2067         {
2068           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2069             exception);
2070           if (info)
2071             info->image_info->transparent_color=target_color;
2072           for ( ; image; image=image->next)
2073             image->transparent_color=target_color;
2074           break;
2075         }
2076       if (LocaleCompare(attribute,"type") == 0)
2077         {
2078           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2079             SvPV(sval,na)) : SvIV(sval);
2080           if (sp < 0)
2081             {
2082               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2083                 SvPV(sval,na));
2084               break;
2085             }
2086           if (info)
2087             info->image_info->type=(ImageType) sp;
2088           for ( ; image; image=image->next)
2089             SetImageType(image,(ImageType) sp,exception);
2090           break;
2091         }
2092       if (info)
2093         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2094       for ( ; image; image=image->next)
2095         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2096       break;
2097     }
2098     case 'U':
2099     case 'u':
2100     {
2101       if (LocaleCompare(attribute,"units") == 0)
2102         {
2103           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2104             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2105           if (sp < 0)
2106             {
2107               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2108                 SvPV(sval,na));
2109               break;
2110             }
2111           if (info)
2112             info->image_info->units=(ResolutionType) sp;
2113           for ( ; image; image=image->next)
2114           {
2115             ResolutionType
2116               units;
2117
2118             units=(ResolutionType) sp;
2119             if (image->units != units)
2120               switch (image->units)
2121               {
2122                 case UndefinedResolution:
2123                 case PixelsPerInchResolution:
2124                 {
2125                   if (units == PixelsPerCentimeterResolution)
2126                     {
2127                       image->resolution.x*=2.54;
2128                       image->resolution.y*=2.54;
2129                     }
2130                   break;
2131                 }
2132                 case PixelsPerCentimeterResolution:
2133                 {
2134                   if (units == PixelsPerInchResolution)
2135                     {
2136                       image->resolution.x/=2.54;
2137                       image->resolution.y/=2.54;
2138                     }
2139                   break;
2140                 }
2141               }
2142             image->units=units;
2143           }
2144           break;
2145         }
2146       if (info)
2147         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2148       for ( ; image; image=image->next)
2149         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2150       break;
2151     }
2152     case 'V':
2153     case 'v':
2154     {
2155       if (LocaleCompare(attribute,"verbose") == 0)
2156         {
2157           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2158             SvPV(sval,na)) : SvIV(sval);
2159           if (sp < 0)
2160             {
2161               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2162                 SvPV(sval,na));
2163               break;
2164             }
2165           if (info)
2166             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2167           break;
2168         }
2169       if (LocaleCompare(attribute,"view") == 0)
2170         {
2171           if (info)
2172             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2173           break;
2174         }
2175       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2176         {
2177           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2178             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2179           if (sp < 0)
2180             {
2181               ThrowPerlException(exception,OptionError,
2182                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2183               break;
2184             }
2185           for ( ; image; image=image->next)
2186             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2187           break;
2188         }
2189       if (info)
2190         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2191       for ( ; image; image=image->next)
2192         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2193       break;
2194     }
2195     case 'W':
2196     case 'w':
2197     {
2198       if (LocaleCompare(attribute,"white-point") == 0)
2199         {
2200           for ( ; image; image=image->next)
2201           {
2202             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2203             image->chromaticity.white_point.x=geometry_info.rho;
2204             image->chromaticity.white_point.y=geometry_info.sigma;
2205             if ((flags & SigmaValue) == 0)
2206               image->chromaticity.white_point.y=
2207                 image->chromaticity.white_point.x;
2208           }
2209           break;
2210         }
2211       if (info)
2212         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2213       for ( ; image; image=image->next)
2214         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2215       break;
2216     }
2217     default:
2218     {
2219       if (info)
2220         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2221       for ( ; image; image=image->next)
2222         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2223       break;
2224     }
2225   }
2226 }
2227 \f
2228 /*
2229 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2230 %                                                                             %
2231 %                                                                             %
2232 %                                                                             %
2233 %   S e t u p L i s t                                                         %
2234 %                                                                             %
2235 %                                                                             %
2236 %                                                                             %
2237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2238 %
2239 %  Method SetupList returns the list of all the images linked by their
2240 %  image->next and image->previous link lists for use with ImageMagick.  If
2241 %  info is non-NULL, an info structure is returned in *info.  If
2242 %  reference_vector is non-NULL,an array of SV* are returned in
2243 %  *reference_vector.  Reference_vector is used when the images are going to be
2244 %  replaced with new Image*'s.
2245 %
2246 %  The format of the SetupList routine is:
2247 %
2248 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2249 %        SV ***reference_vector,ExceptionInfo *exception)
2250 %
2251 %  A description of each parameter follows:
2252 %
2253 %    o list: a list of strings.
2254 %
2255 %    o string: a character string.
2256 %
2257 %    o exception: Return any errors or warnings in this structure.
2258 %
2259 */
2260 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2261   SV ***reference_vector,ExceptionInfo *exception)
2262 {
2263   Image
2264     *image;
2265
2266   ssize_t
2267     current,
2268     last;
2269
2270   if (reference_vector)
2271     *reference_vector=NULL;
2272   if (info)
2273     *info=NULL;
2274   current=0;
2275   last=0;
2276   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2277   if (info && (SvTYPE(reference) == SVt_PVAV))
2278     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2279       exception);
2280   return(image);
2281 }
2282 \f
2283 /*
2284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2285 %                                                                             %
2286 %                                                                             %
2287 %                                                                             %
2288 %   s t r E Q c a s e                                                         %
2289 %                                                                             %
2290 %                                                                             %
2291 %                                                                             %
2292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2293 %
2294 %  strEQcase() compares two strings and returns 0 if they are the
2295 %  same or if the second string runs out first.  The comparison is case
2296 %  insensitive.
2297 %
2298 %  The format of the strEQcase routine is:
2299 %
2300 %      ssize_t strEQcase(const char *p,const char *q)
2301 %
2302 %  A description of each parameter follows:
2303 %
2304 %    o p: a character string.
2305 %
2306 %    o q: a character string.
2307 %
2308 %
2309 */
2310 static ssize_t strEQcase(const char *p,const char *q)
2311 {
2312   char
2313     c;
2314
2315   register ssize_t
2316     i;
2317
2318   for (i=0 ; (c=(*q)) != 0; i++)
2319   {
2320     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2321         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2322       return(0);
2323     p++;
2324     q++;
2325   }
2326   return(((*q == 0) && (*p == 0)) ? i : 0);
2327 }
2328 \f
2329 /*
2330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2331 %                                                                             %
2332 %                                                                             %
2333 %                                                                             %
2334 %   I m a g e : : M a g i c k                                                 %
2335 %                                                                             %
2336 %                                                                             %
2337 %                                                                             %
2338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2339 %
2340 %
2341 */
2342 MODULE = Image::Magick PACKAGE = Image::Magick
2343
2344 PROTOTYPES: ENABLE
2345
2346 BOOT:
2347   MagickCoreGenesis("PerlMagick",MagickFalse);
2348   SetWarningHandler(NULL);
2349   SetErrorHandler(NULL);
2350   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2351     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2352
2353 void
2354 UNLOAD()
2355   PPCODE:
2356   {
2357     if (magick_registry != (SplayTreeInfo *) NULL)
2358       magick_registry=DestroySplayTree(magick_registry);
2359     MagickCoreTerminus();
2360   }
2361
2362 double
2363 constant(name,argument)
2364   char *name
2365   ssize_t argument
2366 \f
2367 #
2368 ###############################################################################
2369 #                                                                             #
2370 #                                                                             #
2371 #                                                                             #
2372 #   A n i m a t e                                                             #
2373 #                                                                             #
2374 #                                                                             #
2375 #                                                                             #
2376 ###############################################################################
2377 #
2378 #
2379 void
2380 Animate(ref,...)
2381   Image::Magick ref=NO_INIT
2382   ALIAS:
2383     AnimateImage  = 1
2384     animate       = 2
2385     animateimage  = 3
2386   PPCODE:
2387   {
2388     ExceptionInfo
2389       *exception;
2390
2391     Image
2392       *image;
2393
2394     register ssize_t
2395       i;
2396
2397     struct PackageInfo
2398       *info,
2399       *package_info;
2400
2401     SV
2402       *perl_exception,
2403       *reference;
2404
2405     PERL_UNUSED_VAR(ref);
2406     PERL_UNUSED_VAR(ix);
2407     exception=AcquireExceptionInfo();
2408     perl_exception=newSVpv("",0);
2409     package_info=(struct PackageInfo *) NULL;
2410     if (sv_isobject(ST(0)) == 0)
2411       {
2412         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2413           PackageName);
2414         goto PerlException;
2415       }
2416     reference=SvRV(ST(0));
2417     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2418     if (image == (Image *) NULL)
2419       {
2420         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2421           PackageName);
2422         goto PerlException;
2423       }
2424     package_info=ClonePackageInfo(info,exception);
2425     if (items == 2)
2426       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2427     else
2428       if (items > 2)
2429         for (i=2; i < items; i+=2)
2430           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2431             exception);
2432     (void) AnimateImages(package_info->image_info,image,exception);
2433     (void) CatchImageException(image);
2434
2435   PerlException:
2436     if (package_info != (struct PackageInfo *) NULL)
2437       DestroyPackageInfo(package_info);
2438     InheritPerlException(exception,perl_exception);
2439     exception=DestroyExceptionInfo(exception);
2440     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2441     SvPOK_on(perl_exception);
2442     ST(0)=sv_2mortal(perl_exception);
2443     XSRETURN(1);
2444   }
2445 \f
2446 #
2447 ###############################################################################
2448 #                                                                             #
2449 #                                                                             #
2450 #                                                                             #
2451 #   A p p e n d                                                               #
2452 #                                                                             #
2453 #                                                                             #
2454 #                                                                             #
2455 ###############################################################################
2456 #
2457 #
2458 void
2459 Append(ref,...)
2460   Image::Magick ref=NO_INIT
2461   ALIAS:
2462     AppendImage  = 1
2463     append       = 2
2464     appendimage  = 3
2465   PPCODE:
2466   {
2467     AV
2468       *av;
2469
2470     char
2471       *attribute;
2472
2473     ExceptionInfo
2474       *exception;
2475
2476     HV
2477       *hv;
2478
2479     Image
2480       *image;
2481
2482     register ssize_t
2483       i;
2484
2485     ssize_t
2486       stack;
2487
2488     struct PackageInfo
2489       *info;
2490
2491     SV
2492       *av_reference,
2493       *perl_exception,
2494       *reference,
2495       *rv,
2496       *sv;
2497
2498     PERL_UNUSED_VAR(ref);
2499     PERL_UNUSED_VAR(ix);
2500     exception=AcquireExceptionInfo();
2501     perl_exception=newSVpv("",0);
2502     sv=NULL;
2503     attribute=NULL;
2504     av=NULL;
2505     if (sv_isobject(ST(0)) == 0)
2506       {
2507         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2508           PackageName);
2509         goto PerlException;
2510       }
2511     reference=SvRV(ST(0));
2512     hv=SvSTASH(reference);
2513     av=newAV();
2514     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2515     SvREFCNT_dec(av);
2516     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2517     if (image == (Image *) NULL)
2518       {
2519         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2520           PackageName);
2521         goto PerlException;
2522       }
2523     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2524     /*
2525       Get options.
2526     */
2527     stack=MagickTrue;
2528     for (i=2; i < items; i+=2)
2529     {
2530       attribute=(char *) SvPV(ST(i-1),na);
2531       switch (*attribute)
2532       {
2533         case 'S':
2534         case 's':
2535         {
2536           if (LocaleCompare(attribute,"stack") == 0)
2537             {
2538               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2539                 SvPV(ST(i),na));
2540               if (stack < 0)
2541                 {
2542                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2543                     SvPV(ST(i),na));
2544                   return;
2545                 }
2546               break;
2547             }
2548           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2549             attribute);
2550           break;
2551         }
2552         default:
2553         {
2554           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2555             attribute);
2556           break;
2557         }
2558       }
2559     }
2560     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2561     if (image == (Image *) NULL)
2562       goto PerlException;
2563     for ( ; image; image=image->next)
2564     {
2565       AddImageToRegistry(sv,image);
2566       rv=newRV(sv);
2567       av_push(av,sv_bless(rv,hv));
2568       SvREFCNT_dec(sv);
2569     }
2570     exception=DestroyExceptionInfo(exception);
2571     ST(0)=av_reference;
2572     SvREFCNT_dec(perl_exception);
2573     XSRETURN(1);
2574
2575   PerlException:
2576     InheritPerlException(exception,perl_exception);
2577     exception=DestroyExceptionInfo(exception);
2578     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2579     SvPOK_on(perl_exception);
2580     ST(0)=sv_2mortal(perl_exception);
2581     XSRETURN(1);
2582   }
2583 \f
2584 #
2585 ###############################################################################
2586 #                                                                             #
2587 #                                                                             #
2588 #                                                                             #
2589 #   A v e r a g e                                                             #
2590 #                                                                             #
2591 #                                                                             #
2592 #                                                                             #
2593 ###############################################################################
2594 #
2595 #
2596 void
2597 Average(ref)
2598   Image::Magick ref=NO_INIT
2599   ALIAS:
2600     AverageImage   = 1
2601     average        = 2
2602     averageimage   = 3
2603   PPCODE:
2604   {
2605     AV
2606       *av;
2607
2608     char
2609       *p;
2610
2611     ExceptionInfo
2612       *exception;
2613
2614     HV
2615       *hv;
2616
2617     Image
2618       *image;
2619
2620     struct PackageInfo
2621       *info;
2622
2623     SV
2624       *perl_exception,
2625       *reference,
2626       *rv,
2627       *sv;
2628
2629     PERL_UNUSED_VAR(ref);
2630     PERL_UNUSED_VAR(ix);
2631     exception=AcquireExceptionInfo();
2632     perl_exception=newSVpv("",0);
2633     sv=NULL;
2634     if (sv_isobject(ST(0)) == 0)
2635       {
2636         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2637           PackageName);
2638         goto PerlException;
2639       }
2640     reference=SvRV(ST(0));
2641     hv=SvSTASH(reference);
2642     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2643     if (image == (Image *) NULL)
2644       {
2645         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2646           PackageName);
2647         goto PerlException;
2648       }
2649     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2650     if (image == (Image *) NULL)
2651       goto PerlException;
2652     /*
2653       Create blessed Perl array for the returned image.
2654     */
2655     av=newAV();
2656     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2657     SvREFCNT_dec(av);
2658     AddImageToRegistry(sv,image);
2659     rv=newRV(sv);
2660     av_push(av,sv_bless(rv,hv));
2661     SvREFCNT_dec(sv);
2662     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2663     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2664       "average-%.*s",(int) (MaxTextExtent-9),
2665       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2666     (void) CopyMagickString(image->filename,info->image_info->filename,
2667       MaxTextExtent);
2668     SetImageInfo(info->image_info,0,exception);
2669     exception=DestroyExceptionInfo(exception);
2670     SvREFCNT_dec(perl_exception);
2671     XSRETURN(1);
2672
2673   PerlException:
2674     InheritPerlException(exception,perl_exception);
2675     exception=DestroyExceptionInfo(exception);
2676     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2677     SvPOK_on(perl_exception);
2678     ST(0)=sv_2mortal(perl_exception);
2679     XSRETURN(1);
2680   }
2681 \f
2682 #
2683 ###############################################################################
2684 #                                                                             #
2685 #                                                                             #
2686 #                                                                             #
2687 #   B l o b T o I m a g e                                                     #
2688 #                                                                             #
2689 #                                                                             #
2690 #                                                                             #
2691 ###############################################################################
2692 #
2693 #
2694 void
2695 BlobToImage(ref,...)
2696   Image::Magick ref=NO_INIT
2697   ALIAS:
2698     BlobToImage  = 1
2699     blobtoimage  = 2
2700     blobto       = 3
2701   PPCODE:
2702   {
2703     AV
2704       *av;
2705
2706     char
2707       **keep,
2708       **list;
2709
2710     ExceptionInfo
2711       *exception;
2712
2713     HV
2714       *hv;
2715
2716     Image
2717       *image;
2718
2719     register char
2720       **p;
2721
2722     register ssize_t
2723       i;
2724
2725     ssize_t
2726       ac,
2727       n,
2728       number_images;
2729
2730     STRLEN
2731       *length;
2732
2733     struct PackageInfo
2734       *info;
2735
2736     SV
2737       *perl_exception,
2738       *reference,
2739       *rv,
2740       *sv;
2741
2742     PERL_UNUSED_VAR(ref);
2743     PERL_UNUSED_VAR(ix);
2744     exception=AcquireExceptionInfo();
2745     perl_exception=newSVpv("",0);
2746     sv=NULL;
2747     number_images=0;
2748     ac=(items < 2) ? 1 : items-1;
2749     length=(STRLEN *) NULL;
2750     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2751     if (list == (char **) NULL)
2752       {
2753         ThrowPerlException(exception,ResourceLimitError,
2754           "MemoryAllocationFailed",PackageName);
2755         goto PerlException;
2756       }
2757     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2758     if (length == (STRLEN *) NULL)
2759       {
2760         ThrowPerlException(exception,ResourceLimitError,
2761           "MemoryAllocationFailed",PackageName);
2762         goto PerlException;
2763       }
2764     if (sv_isobject(ST(0)) == 0)
2765       {
2766         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2767           PackageName);
2768         goto PerlException;
2769       }
2770     reference=SvRV(ST(0));
2771     hv=SvSTASH(reference);
2772     if (SvTYPE(reference) != SVt_PVAV)
2773       {
2774         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2775           PackageName);
2776         goto PerlException;
2777       }
2778     av=(AV *) reference;
2779     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2780       exception);
2781     n=1;
2782     if (items <= 1)
2783       {
2784         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2785         goto PerlException;
2786       }
2787     for (n=0, i=0; i < ac; i++)
2788     {
2789       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2790       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2791         {
2792           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2793           continue;
2794         }
2795       n++;
2796     }
2797     list[n]=(char *) NULL;
2798     keep=list;
2799     for (i=number_images=0; i < n; i++)
2800     {
2801       image=BlobToImage(info->image_info,list[i],length[i],exception);
2802       if (image == (Image *) NULL)
2803         break;
2804       for ( ; image; image=image->next)
2805       {
2806         AddImageToRegistry(sv,image);
2807         rv=newRV(sv);
2808         av_push(av,sv_bless(rv,hv));
2809         SvREFCNT_dec(sv);
2810         number_images++;
2811       }
2812     }
2813     /*
2814       Free resources.
2815     */
2816     for (i=0; i < n; i++)
2817       if (list[i] != (char *) NULL)
2818         for (p=keep; list[i] != *p++; )
2819           if (*p == (char *) NULL)
2820             {
2821               list[i]=(char *) RelinquishMagickMemory(list[i]);
2822               break;
2823             }
2824
2825   PerlException:
2826     if (list)
2827       list=(char **) RelinquishMagickMemory(list);
2828     if (length)
2829       length=(STRLEN *) RelinquishMagickMemory(length);
2830     InheritPerlException(exception,perl_exception);
2831     exception=DestroyExceptionInfo(exception);
2832     sv_setiv(perl_exception,(IV) number_images);
2833     SvPOK_on(perl_exception);
2834     ST(0)=sv_2mortal(perl_exception);
2835     XSRETURN(1);
2836   }
2837 \f
2838 #
2839 ###############################################################################
2840 #                                                                             #
2841 #                                                                             #
2842 #                                                                             #
2843 #   C h a n n e l F x                                                         #
2844 #                                                                             #
2845 #                                                                             #
2846 #                                                                             #
2847 ###############################################################################
2848 #
2849 #
2850 void
2851 ChannelFx(ref,...)
2852   Image::Magick ref=NO_INIT
2853   ALIAS:
2854     ChannelFxImage  = 1
2855     channelfx       = 2
2856     channelfximage  = 3
2857   PPCODE:
2858   {
2859     AV
2860       *av;
2861
2862     char
2863       *attribute,
2864       expression[MaxTextExtent];
2865
2866     ChannelType
2867       channel,
2868       channel_mask;
2869
2870     ExceptionInfo
2871       *exception;
2872
2873     HV
2874       *hv;
2875
2876     Image
2877       *image;
2878
2879     register ssize_t
2880       i;
2881
2882     struct PackageInfo
2883       *info;
2884
2885     SV
2886       *av_reference,
2887       *perl_exception,
2888       *reference,
2889       *rv,
2890       *sv;
2891
2892     PERL_UNUSED_VAR(ref);
2893     PERL_UNUSED_VAR(ix);
2894     exception=AcquireExceptionInfo();
2895     perl_exception=newSVpv("",0);
2896     sv=NULL;
2897     attribute=NULL;
2898     av=NULL;
2899     if (sv_isobject(ST(0)) == 0)
2900       {
2901         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2902           PackageName);
2903         goto PerlException;
2904       }
2905     reference=SvRV(ST(0));
2906     hv=SvSTASH(reference);
2907     av=newAV();
2908     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2909     SvREFCNT_dec(av);
2910     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2911     if (image == (Image *) NULL)
2912       {
2913         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2914           PackageName);
2915         goto PerlException;
2916       }
2917     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2918     /*
2919       Get options.
2920     */
2921     channel=DefaultChannels;
2922     (void) CopyMagickString(expression,"u",MaxTextExtent);
2923     if (items == 2)
2924       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2925     else
2926       for (i=2; i < items; i+=2)
2927       {
2928         attribute=(char *) SvPV(ST(i-1),na);
2929         switch (*attribute)
2930         {
2931           case 'C':
2932           case 'c':
2933           {
2934             if (LocaleCompare(attribute,"channel") == 0)
2935               {
2936                 ssize_t
2937                   option;
2938
2939                 option=ParseChannelOption(SvPV(ST(i),na));
2940                 if (option < 0)
2941                   {
2942                     ThrowPerlException(exception,OptionError,
2943                       "UnrecognizedType",SvPV(ST(i),na));
2944                     return;
2945                   }
2946                 channel=(ChannelType) option;
2947                 break;
2948               }
2949             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2950               attribute);
2951             break;
2952           }
2953           case 'E':
2954           case 'e':
2955           {
2956             if (LocaleCompare(attribute,"expression") == 0)
2957               {
2958                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2959                   MaxTextExtent);
2960                 break;
2961               }
2962             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2963               attribute);
2964             break;
2965           }
2966           default:
2967           {
2968             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2969               attribute);
2970             break;
2971           }
2972         }
2973       }
2974     channel_mask=SetImageChannelMask(image,channel);
2975     image=ChannelFxImage(image,expression,exception);
2976     if (image != (Image *) NULL)
2977       (void) SetImageChannelMask(image,channel_mask);
2978     if (image == (Image *) NULL)
2979       goto PerlException;
2980     for ( ; image; image=image->next)
2981     {
2982       AddImageToRegistry(sv,image);
2983       rv=newRV(sv);
2984       av_push(av,sv_bless(rv,hv));
2985       SvREFCNT_dec(sv);
2986     }
2987     exception=DestroyExceptionInfo(exception);
2988     ST(0)=av_reference;
2989     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2990     XSRETURN(1);
2991
2992   PerlException:
2993     InheritPerlException(exception,perl_exception);
2994     exception=DestroyExceptionInfo(exception);
2995     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2996     SvPOK_on(perl_exception);
2997     ST(0)=sv_2mortal(perl_exception);
2998     XSRETURN(1);
2999   }
3000 \f
3001 #
3002 ###############################################################################
3003 #                                                                             #
3004 #                                                                             #
3005 #                                                                             #
3006 #   C l o n e                                                                 #
3007 #                                                                             #
3008 #                                                                             #
3009 #                                                                             #
3010 ###############################################################################
3011 #
3012 #
3013 void
3014 Clone(ref)
3015   Image::Magick ref=NO_INIT
3016   ALIAS:
3017     CopyImage   = 1
3018     copy        = 2
3019     copyimage   = 3
3020     CloneImage  = 4
3021     clone       = 5
3022     cloneimage  = 6
3023     Clone       = 7
3024   PPCODE:
3025   {
3026     AV
3027       *av;
3028
3029     ExceptionInfo
3030       *exception;
3031
3032     HV
3033       *hv;
3034
3035     Image
3036       *clone,
3037       *image;
3038
3039     struct PackageInfo
3040       *info;
3041
3042     SV
3043       *perl_exception,
3044       *reference,
3045       *rv,
3046       *sv;
3047
3048     PERL_UNUSED_VAR(ref);
3049     PERL_UNUSED_VAR(ix);
3050     exception=AcquireExceptionInfo();
3051     perl_exception=newSVpv("",0);
3052     sv=NULL;
3053     if (sv_isobject(ST(0)) == 0)
3054       {
3055         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3056           PackageName);
3057         goto PerlException;
3058       }
3059     reference=SvRV(ST(0));
3060     hv=SvSTASH(reference);
3061     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3062     if (image == (Image *) NULL)
3063       {
3064         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3065           PackageName);
3066         goto PerlException;
3067       }
3068     /*
3069       Create blessed Perl array for the returned image.
3070     */
3071     av=newAV();
3072     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3073     SvREFCNT_dec(av);
3074     for ( ; image; image=image->next)
3075     {
3076       clone=CloneImage(image,0,0,MagickTrue,exception);
3077       if (clone == (Image *) NULL)
3078         break;
3079       AddImageToRegistry(sv,clone);
3080       rv=newRV(sv);
3081       av_push(av,sv_bless(rv,hv));
3082       SvREFCNT_dec(sv);
3083     }
3084     exception=DestroyExceptionInfo(exception);
3085     SvREFCNT_dec(perl_exception);
3086     XSRETURN(1);
3087
3088   PerlException:
3089     InheritPerlException(exception,perl_exception);
3090     exception=DestroyExceptionInfo(exception);
3091     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3092     SvPOK_on(perl_exception);
3093     ST(0)=sv_2mortal(perl_exception);
3094     XSRETURN(1);
3095   }
3096 \f
3097 #
3098 ###############################################################################
3099 #                                                                             #
3100 #                                                                             #
3101 #                                                                             #
3102 #   C L O N E                                                                 #
3103 #                                                                             #
3104 #                                                                             #
3105 #                                                                             #
3106 ###############################################################################
3107 #
3108 #
3109 void
3110 CLONE(ref,...)
3111   SV *ref;
3112   CODE:
3113   {
3114     PERL_UNUSED_VAR(ref);
3115     if (magick_registry != (SplayTreeInfo *) NULL)
3116       {
3117         register Image
3118           *p;
3119
3120         ResetSplayTreeIterator(magick_registry);
3121         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3122         while (p != (Image *) NULL)
3123         {
3124           ReferenceImage(p);
3125           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3126         }
3127       }
3128   }
3129 \f
3130 #
3131 ###############################################################################
3132 #                                                                             #
3133 #                                                                             #
3134 #                                                                             #
3135 #   C o a l e s c e                                                           #
3136 #                                                                             #
3137 #                                                                             #
3138 #                                                                             #
3139 ###############################################################################
3140 #
3141 #
3142 void
3143 Coalesce(ref)
3144   Image::Magick ref=NO_INIT
3145   ALIAS:
3146     CoalesceImage   = 1
3147     coalesce        = 2
3148     coalesceimage   = 3
3149   PPCODE:
3150   {
3151     AV
3152       *av;
3153
3154     ExceptionInfo
3155       *exception;
3156
3157     HV
3158       *hv;
3159
3160     Image
3161       *image;
3162
3163     struct PackageInfo
3164       *info;
3165
3166     SV
3167       *av_reference,
3168       *perl_exception,
3169       *reference,
3170       *rv,
3171       *sv;
3172
3173     PERL_UNUSED_VAR(ref);
3174     PERL_UNUSED_VAR(ix);
3175     exception=AcquireExceptionInfo();
3176     perl_exception=newSVpv("",0);
3177     sv=NULL;
3178     if (sv_isobject(ST(0)) == 0)
3179       {
3180         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3181           PackageName);
3182         goto PerlException;
3183       }
3184     reference=SvRV(ST(0));
3185     hv=SvSTASH(reference);
3186     av=newAV();
3187     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3188     SvREFCNT_dec(av);
3189     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3190     if (image == (Image *) NULL)
3191       {
3192         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3193           PackageName);
3194         goto PerlException;
3195       }
3196     image=CoalesceImages(image,exception);
3197     if (image == (Image *) NULL)
3198       goto PerlException;
3199     for ( ; image; image=image->next)
3200     {
3201       AddImageToRegistry(sv,image);
3202       rv=newRV(sv);
3203       av_push(av,sv_bless(rv,hv));
3204       SvREFCNT_dec(sv);
3205     }
3206     exception=DestroyExceptionInfo(exception);
3207     ST(0)=av_reference;
3208     SvREFCNT_dec(perl_exception);
3209     XSRETURN(1);
3210
3211   PerlException:
3212     InheritPerlException(exception,perl_exception);
3213     exception=DestroyExceptionInfo(exception);
3214     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3215     SvPOK_on(perl_exception);
3216     ST(0)=sv_2mortal(perl_exception);
3217     XSRETURN(1);
3218   }
3219 \f
3220 #
3221 ###############################################################################
3222 #                                                                             #
3223 #                                                                             #
3224 #                                                                             #
3225 #   C o m p a r e                                                             #
3226 #                                                                             #
3227 #                                                                             #
3228 #                                                                             #
3229 ###############################################################################
3230 #
3231 #
3232 void
3233 Compare(ref,...)
3234   Image::Magick ref=NO_INIT
3235   ALIAS:
3236     CompareImages = 1
3237     compare      = 2
3238     compareimage = 3
3239   PPCODE:
3240   {
3241     AV
3242       *av;
3243
3244     char
3245       *attribute;
3246
3247     double
3248       distortion;
3249
3250     ExceptionInfo
3251       *exception;
3252
3253     HV
3254       *hv;
3255
3256     Image
3257       *difference_image,
3258       *image,
3259       *reconstruct_image;
3260
3261     MetricType
3262       metric;
3263
3264     register ssize_t
3265       i;
3266
3267     ssize_t
3268       option;
3269
3270     struct PackageInfo
3271       *info;
3272
3273     SV
3274       *av_reference,
3275       *perl_exception,
3276       *reference,
3277       *rv,
3278       *sv;
3279
3280     PERL_UNUSED_VAR(ref);
3281     PERL_UNUSED_VAR(ix);
3282     exception=AcquireExceptionInfo();
3283     perl_exception=newSVpv("",0);
3284     sv=NULL;
3285     av=NULL;
3286     attribute=NULL;
3287     if (sv_isobject(ST(0)) == 0)
3288       {
3289         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3290           PackageName);
3291         goto PerlException;
3292       }
3293     reference=SvRV(ST(0));
3294     hv=SvSTASH(reference);
3295     av=newAV();
3296     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3297     SvREFCNT_dec(av);
3298     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3299     if (image == (Image *) NULL)
3300       {
3301         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3302           PackageName);
3303         goto PerlException;
3304       }
3305     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3306     /*
3307       Get attribute.
3308     */
3309     reconstruct_image=image;
3310     metric=RootMeanSquaredErrorMetric;
3311     for (i=2; i < items; i+=2)
3312     {
3313       attribute=(char *) SvPV(ST(i-1),na);
3314       switch (*attribute)
3315       {
3316         case 'C':
3317         case 'c':
3318         {
3319           if (LocaleCompare(attribute,"channel") == 0)
3320             {
3321               ssize_t
3322                 option;
3323
3324               option=ParseChannelOption(SvPV(ST(i),na));
3325               if (option < 0)
3326                 {
3327                   ThrowPerlException(exception,OptionError,
3328                     "UnrecognizedType",SvPV(ST(i),na));
3329                   return;
3330                 }
3331               SetPixelChannelMask(image,(ChannelType) option);
3332               break;
3333             }
3334           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3335             attribute);
3336           break;
3337         }
3338         case 'F':
3339         case 'f':
3340         {
3341           if (LocaleCompare(attribute,"fuzz") == 0)
3342             {
3343               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3344               break;
3345             }
3346           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3347             attribute);
3348           break;
3349         }
3350         case 'I':
3351         case 'i':
3352         {
3353           if (LocaleCompare(attribute,"image") == 0)
3354             {
3355               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3356                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3357               break;
3358             }
3359           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3360             attribute);
3361           break;
3362         }
3363         case 'M':
3364         case 'm':
3365         {
3366           if (LocaleCompare(attribute,"metric") == 0)
3367             {
3368               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3369                 SvPV(ST(i),na));
3370               if (option < 0)
3371                 {
3372                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3373                     SvPV(ST(i),na));
3374                   break;
3375                 }
3376               metric=(MetricType) option;
3377               break;
3378             }
3379           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3380             attribute);
3381           break;
3382         }
3383         default:
3384         {
3385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386             attribute);
3387           break;
3388         }
3389       }
3390     }
3391     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3392       exception);
3393     if (difference_image != (Image *) NULL)
3394       {
3395         difference_image->error.mean_error_per_pixel=distortion;
3396         AddImageToRegistry(sv,difference_image);
3397         rv=newRV(sv);
3398         av_push(av,sv_bless(rv,hv));
3399         SvREFCNT_dec(sv);
3400       }
3401     exception=DestroyExceptionInfo(exception);
3402     ST(0)=av_reference;
3403     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3404     XSRETURN(1);
3405
3406   PerlException:
3407     InheritPerlException(exception,perl_exception);
3408     exception=DestroyExceptionInfo(exception);
3409     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3410     SvPOK_on(perl_exception);
3411     ST(0)=sv_2mortal(perl_exception);
3412     XSRETURN(1);
3413   }
3414 \f
3415 #
3416 ###############################################################################
3417 #                                                                             #
3418 #                                                                             #
3419 #                                                                             #
3420 #   C o m p a r e L a y e r s                                                 #
3421 #                                                                             #
3422 #                                                                             #
3423 #                                                                             #
3424 ###############################################################################
3425 #
3426 #
3427 void
3428 CompareLayers(ref)
3429   Image::Magick ref=NO_INIT
3430   ALIAS:
3431     CompareImagesLayers   = 1
3432     comparelayers        = 2
3433     compareimagelayers   = 3
3434   PPCODE:
3435   {
3436     AV
3437       *av;
3438
3439     char
3440       *attribute;
3441
3442     ExceptionInfo
3443       *exception;
3444
3445     HV
3446       *hv;
3447
3448     Image
3449       *image;
3450
3451     LayerMethod
3452       method;
3453
3454     register ssize_t
3455       i;
3456
3457     ssize_t
3458       option;
3459
3460     struct PackageInfo
3461       *info;
3462
3463     SV
3464       *av_reference,
3465       *perl_exception,
3466       *reference,
3467       *rv,
3468       *sv;
3469
3470     PERL_UNUSED_VAR(ref);
3471     PERL_UNUSED_VAR(ix);
3472     exception=AcquireExceptionInfo();
3473     perl_exception=newSVpv("",0);
3474     sv=NULL;
3475     if (sv_isobject(ST(0)) == 0)
3476       {
3477         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3478           PackageName);
3479         goto PerlException;
3480       }
3481     reference=SvRV(ST(0));
3482     hv=SvSTASH(reference);
3483     av=newAV();
3484     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3485     SvREFCNT_dec(av);
3486     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3487     if (image == (Image *) NULL)
3488       {
3489         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3490           PackageName);
3491         goto PerlException;
3492       }
3493     method=CompareAnyLayer;
3494     for (i=2; i < items; i+=2)
3495     {
3496       attribute=(char *) SvPV(ST(i-1),na);
3497       switch (*attribute)
3498       {
3499         case 'M':
3500         case 'm':
3501         {
3502           if (LocaleCompare(attribute,"method") == 0)
3503             {
3504               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3505                 SvPV(ST(i),na));
3506               if (option < 0)
3507                 {
3508                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3509                     SvPV(ST(i),na));
3510                   break;
3511                 }
3512                method=(LayerMethod) option;
3513               break;
3514             }
3515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3516             attribute);
3517           break;
3518         }
3519         default:
3520         {
3521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3522             attribute);
3523           break;
3524         }
3525       }
3526     }
3527     image=CompareImagesLayers(image,method,exception);
3528     if (image == (Image *) NULL)
3529       goto PerlException;
3530     for ( ; image; image=image->next)
3531     {
3532       AddImageToRegistry(sv,image);
3533       rv=newRV(sv);
3534       av_push(av,sv_bless(rv,hv));
3535       SvREFCNT_dec(sv);
3536     }
3537     exception=DestroyExceptionInfo(exception);
3538     ST(0)=av_reference;
3539     SvREFCNT_dec(perl_exception);
3540     XSRETURN(1);
3541
3542   PerlException:
3543     InheritPerlException(exception,perl_exception);
3544     exception=DestroyExceptionInfo(exception);
3545     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3546     SvPOK_on(perl_exception);
3547     ST(0)=sv_2mortal(perl_exception);
3548     XSRETURN(1);
3549   }
3550 \f
3551 #
3552 ###############################################################################
3553 #                                                                             #
3554 #                                                                             #
3555 #                                                                             #
3556 #   D e s t r o y                                                             #
3557 #                                                                             #
3558 #                                                                             #
3559 #                                                                             #
3560 ###############################################################################
3561 #
3562 #
3563 void
3564 DESTROY(ref)
3565   Image::Magick ref=NO_INIT
3566   PPCODE:
3567   {
3568     SV
3569       *reference;
3570
3571     PERL_UNUSED_VAR(ref);
3572     if (sv_isobject(ST(0)) == 0)
3573       croak("ReferenceIsNotMyType");
3574     reference=SvRV(ST(0));
3575     switch (SvTYPE(reference))
3576     {
3577       case SVt_PVAV:
3578       {
3579         char
3580           message[MaxTextExtent];
3581
3582         const SV
3583           *key;
3584
3585         HV
3586           *hv;
3587
3588         GV
3589           **gvp;
3590
3591         struct PackageInfo
3592           *info;
3593
3594         SV
3595           *sv;
3596
3597         /*
3598           Array (AV *) reference
3599         */
3600         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3601           XS_VERSION,reference);
3602         hv=gv_stashpv(PackageName, FALSE);
3603         if (!hv)
3604           break;
3605         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3606         if (!gvp)
3607           break;
3608         sv=GvSV(*gvp);
3609         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3610           {
3611             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3612             DestroyPackageInfo(info);
3613           }
3614         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3615         (void) key;
3616         break;
3617       }
3618       case SVt_PVMG:
3619       {
3620         Image
3621           *image;
3622
3623         /*
3624           Blessed scalar = (Image *) SvIV(reference)
3625         */
3626         image=INT2PTR(Image *,SvIV(reference));
3627         if (image != (Image *) NULL)
3628           DeleteImageFromRegistry(reference,image);
3629         break;
3630       }
3631       default:
3632         break;
3633     }
3634   }
3635 \f
3636 #
3637 ###############################################################################
3638 #                                                                             #
3639 #                                                                             #
3640 #                                                                             #
3641 #   D i s p l a y                                                             #
3642 #                                                                             #
3643 #                                                                             #
3644 #                                                                             #
3645 ###############################################################################
3646 #
3647 #
3648 void
3649 Display(ref,...)
3650   Image::Magick ref=NO_INIT
3651   ALIAS:
3652     DisplayImage  = 1
3653     display       = 2
3654     displayimage  = 3
3655   PPCODE:
3656   {
3657     ExceptionInfo
3658       *exception;
3659
3660     Image
3661       *image;
3662
3663     register ssize_t
3664       i;
3665
3666     struct PackageInfo
3667       *info,
3668       *package_info;
3669
3670     SV
3671       *perl_exception,
3672       *reference;
3673
3674     PERL_UNUSED_VAR(ref);
3675     PERL_UNUSED_VAR(ix);
3676     exception=AcquireExceptionInfo();
3677     perl_exception=newSVpv("",0);
3678     package_info=(struct PackageInfo *) NULL;
3679     if (sv_isobject(ST(0)) == 0)
3680       {
3681         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3682           PackageName);
3683         goto PerlException;
3684       }
3685     reference=SvRV(ST(0));
3686     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3687     if (image == (Image *) NULL)
3688       {
3689         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3690           PackageName);
3691         goto PerlException;
3692       }
3693     package_info=ClonePackageInfo(info,exception);
3694     if (items == 2)
3695       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3696     else
3697       if (items > 2)
3698         for (i=2; i < items; i+=2)
3699           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3700             exception);
3701     (void) DisplayImages(package_info->image_info,image,exception);
3702     (void) CatchImageException(image);
3703
3704   PerlException:
3705     if (package_info != (struct PackageInfo *) NULL)
3706       DestroyPackageInfo(package_info);
3707     InheritPerlException(exception,perl_exception);
3708     exception=DestroyExceptionInfo(exception);
3709     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3710     SvPOK_on(perl_exception);
3711     ST(0)=sv_2mortal(perl_exception);
3712     XSRETURN(1);
3713   }
3714 \f
3715 #
3716 ###############################################################################
3717 #                                                                             #
3718 #                                                                             #
3719 #                                                                             #
3720 #   E v a l u a t e I m a g e s                                               #
3721 #                                                                             #
3722 #                                                                             #
3723 #                                                                             #
3724 ###############################################################################
3725 #
3726 #
3727 void
3728 EvaluateImages(ref)
3729   Image::Magick ref=NO_INIT
3730   ALIAS:
3731     EvaluateImages   = 1
3732     evaluateimages   = 2
3733   PPCODE:
3734   {
3735     AV
3736       *av;
3737
3738     char
3739       *attribute,
3740       *p;
3741
3742     ExceptionInfo
3743       *exception;
3744
3745     HV
3746       *hv;
3747
3748     Image
3749       *image;
3750
3751     MagickEvaluateOperator
3752       op;
3753
3754     register ssize_t
3755       i;
3756
3757     struct PackageInfo
3758       *info;
3759
3760     SV
3761       *perl_exception,
3762       *reference,
3763       *rv,
3764       *sv;
3765
3766     PERL_UNUSED_VAR(ref);
3767     PERL_UNUSED_VAR(ix);
3768     exception=AcquireExceptionInfo();
3769     perl_exception=newSVpv("",0);
3770     sv=NULL;
3771     if (sv_isobject(ST(0)) == 0)
3772       {
3773         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3774           PackageName);
3775         goto PerlException;
3776       }
3777     reference=SvRV(ST(0));
3778     hv=SvSTASH(reference);
3779     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3780     if (image == (Image *) NULL)
3781       {
3782         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3783           PackageName);
3784         goto PerlException;
3785       }
3786     op=MeanEvaluateOperator;
3787     if (items == 2)
3788       {
3789         ssize_t
3790           in;
3791
3792         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3793           SvPV(ST(1),na));
3794         if (in < 0)
3795           {
3796             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3797               SvPV(ST(1),na));
3798             return;
3799           }
3800         op=(MagickEvaluateOperator) in;
3801       }
3802     else
3803       for (i=2; i < items; i+=2)
3804       {
3805         attribute=(char *) SvPV(ST(i-1),na);
3806         switch (*attribute)
3807         {
3808           case 'O':
3809           case 'o':
3810           {
3811             if (LocaleCompare(attribute,"operator") == 0)
3812               {
3813                 ssize_t
3814                   in;
3815
3816                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3817                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3818                 if (in < 0)
3819                   {
3820                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3821                       SvPV(ST(i),na));
3822                     return;
3823                   }
3824                 op=(MagickEvaluateOperator) in;
3825                 break;
3826               }
3827             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3828               attribute);
3829             break;
3830           }
3831           default:
3832           {
3833             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3834               attribute);
3835             break;
3836           }
3837         }
3838       }
3839     image=EvaluateImages(image,op,exception);
3840     if (image == (Image *) NULL)
3841       goto PerlException;
3842     /*
3843       Create blessed Perl array for the returned image.
3844     */
3845     av=newAV();
3846     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3847     SvREFCNT_dec(av);
3848     AddImageToRegistry(sv,image);
3849     rv=newRV(sv);
3850     av_push(av,sv_bless(rv,hv));
3851     SvREFCNT_dec(sv);
3852     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3853     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3854       "evaluate-%.*s",(int) (MaxTextExtent-9),
3855       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3856     (void) CopyMagickString(image->filename,info->image_info->filename,
3857       MaxTextExtent);
3858     SetImageInfo(info->image_info,0,exception);
3859     exception=DestroyExceptionInfo(exception);
3860     SvREFCNT_dec(perl_exception);
3861     XSRETURN(1);
3862
3863   PerlException:
3864     InheritPerlException(exception,perl_exception);
3865     exception=DestroyExceptionInfo(exception);
3866     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3867     SvPOK_on(perl_exception);
3868     ST(0)=sv_2mortal(perl_exception);
3869     XSRETURN(1);
3870   }
3871 \f
3872 #
3873 ###############################################################################
3874 #                                                                             #
3875 #                                                                             #
3876 #                                                                             #
3877 #   F e a t u r e s                                                           #
3878 #                                                                             #
3879 #                                                                             #
3880 #                                                                             #
3881 ###############################################################################
3882 #
3883 #
3884 void
3885 Features(ref,...)
3886   Image::Magick ref=NO_INIT
3887   ALIAS:
3888     FeaturesImage = 1
3889     features      = 2
3890     featuresimage = 3
3891   PPCODE:
3892   {
3893 #define ChannelFeatures(channel,direction) \
3894 { \
3895   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3896     channel_features[channel].angular_second_moment[direction]); \
3897   PUSHs(sv_2mortal(newSVpv(message,0))); \
3898   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3899     channel_features[channel].contrast[direction]); \
3900   PUSHs(sv_2mortal(newSVpv(message,0))); \
3901   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3902     channel_features[channel].contrast[direction]); \
3903   PUSHs(sv_2mortal(newSVpv(message,0))); \
3904   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3905     channel_features[channel].variance_sum_of_squares[direction]); \
3906   PUSHs(sv_2mortal(newSVpv(message,0))); \
3907   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3908     channel_features[channel].inverse_difference_moment[direction]); \
3909   PUSHs(sv_2mortal(newSVpv(message,0))); \
3910   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3911     channel_features[channel].sum_average[direction]); \
3912   PUSHs(sv_2mortal(newSVpv(message,0))); \
3913   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3914     channel_features[channel].sum_variance[direction]); \
3915   PUSHs(sv_2mortal(newSVpv(message,0))); \
3916   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3917     channel_features[channel].sum_entropy[direction]); \
3918   PUSHs(sv_2mortal(newSVpv(message,0))); \
3919   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3920     channel_features[channel].entropy[direction]); \
3921   PUSHs(sv_2mortal(newSVpv(message,0))); \
3922   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3923     channel_features[channel].difference_variance[direction]); \
3924   PUSHs(sv_2mortal(newSVpv(message,0))); \
3925   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3926     channel_features[channel].difference_entropy[direction]); \
3927   PUSHs(sv_2mortal(newSVpv(message,0))); \
3928   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3929     channel_features[channel].measure_of_correlation_1[direction]); \
3930   PUSHs(sv_2mortal(newSVpv(message,0))); \
3931   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3932     channel_features[channel].measure_of_correlation_2[direction]); \
3933   PUSHs(sv_2mortal(newSVpv(message,0))); \
3934   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3935     channel_features[channel].maximum_correlation_coefficient[direction]); \
3936   PUSHs(sv_2mortal(newSVpv(message,0))); \
3937 }
3938
3939     AV
3940       *av;
3941
3942     char
3943       *attribute,
3944       message[MaxTextExtent];
3945
3946     ChannelFeatures
3947       *channel_features;
3948
3949     double
3950       distance;
3951
3952     ExceptionInfo
3953       *exception;
3954
3955     Image
3956       *image;
3957
3958     register ssize_t
3959       i;
3960
3961     ssize_t
3962       count;
3963
3964     struct PackageInfo
3965       *info;
3966
3967     SV
3968       *perl_exception,
3969       *reference;
3970
3971     PERL_UNUSED_VAR(ref);
3972     PERL_UNUSED_VAR(ix);
3973     exception=AcquireExceptionInfo();
3974     perl_exception=newSVpv("",0);
3975     av=NULL;
3976     if (sv_isobject(ST(0)) == 0)
3977       {
3978         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3979           PackageName);
3980         goto PerlException;
3981       }
3982     reference=SvRV(ST(0));
3983     av=newAV();
3984     SvREFCNT_dec(av);
3985     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3986     if (image == (Image *) NULL)
3987       {
3988         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3989           PackageName);
3990         goto PerlException;
3991       }
3992     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3993     distance=1;
3994     for (i=2; i < items; i+=2)
3995     {
3996       attribute=(char *) SvPV(ST(i-1),na);
3997       switch (*attribute)
3998       {
3999         case 'D':
4000         case 'd':
4001         {
4002           if (LocaleCompare(attribute,"distance") == 0)
4003             {
4004               distance=StringToLong((char *) SvPV(ST(1),na));
4005               break;
4006             }
4007           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4008             attribute);
4009           break;
4010         }
4011         default:
4012         {
4013           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4014             attribute);
4015           break;
4016         }
4017       }
4018     }
4019     count=0;
4020     for ( ; image; image=image->next)
4021     {
4022       channel_features=GetImageFeatures(image,distance,exception);
4023       if (channel_features == (ChannelFeatures *) NULL)
4024         continue;
4025       count++;
4026       EXTEND(sp,75*count);
4027       for (i=0; i < 4; i++)
4028       {
4029         ChannelFeatures(RedChannel,i);
4030         ChannelFeatures(GreenChannel,i);
4031         ChannelFeatures(BlueChannel,i);
4032         if (image->colorspace == CMYKColorspace)
4033           ChannelFeatures(BlackChannel,i);
4034         if (image->alpha_trait == BlendPixelTrait)
4035           ChannelFeatures(AlphaChannel,i);
4036       }
4037       channel_features=(ChannelFeatures *)
4038         RelinquishMagickMemory(channel_features);
4039     }
4040
4041   PerlException:
4042     InheritPerlException(exception,perl_exception);
4043     exception=DestroyExceptionInfo(exception);
4044     SvREFCNT_dec(perl_exception);
4045   }
4046 \f
4047 #
4048 ###############################################################################
4049 #                                                                             #
4050 #                                                                             #
4051 #                                                                             #
4052 #   F l a t t e n                                                             #
4053 #                                                                             #
4054 #                                                                             #
4055 #                                                                             #
4056 ###############################################################################
4057 #
4058 #
4059 void
4060 Flatten(ref)
4061   Image::Magick ref=NO_INIT
4062   ALIAS:
4063     FlattenImage   = 1
4064     flatten        = 2
4065     flattenimage   = 3
4066   PPCODE:
4067   {
4068     AV
4069       *av;
4070
4071     char
4072       *attribute,
4073       *p;
4074
4075     ExceptionInfo
4076       *exception;
4077
4078     HV
4079       *hv;
4080
4081     Image
4082       *image;
4083
4084     PixelInfo
4085       background_color;
4086
4087     register ssize_t
4088       i;
4089
4090     struct PackageInfo
4091       *info;
4092
4093     SV
4094       *perl_exception,
4095       *reference,
4096       *rv,
4097       *sv;
4098
4099     PERL_UNUSED_VAR(ref);
4100     PERL_UNUSED_VAR(ix);
4101     exception=AcquireExceptionInfo();
4102     perl_exception=newSVpv("",0);
4103     sv=NULL;
4104     if (sv_isobject(ST(0)) == 0)
4105       {
4106         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4107           PackageName);
4108         goto PerlException;
4109       }
4110     reference=SvRV(ST(0));
4111     hv=SvSTASH(reference);
4112     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4113     if (image == (Image *) NULL)
4114       {
4115         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4116           PackageName);
4117         goto PerlException;
4118       }
4119     background_color=image->background_color;
4120     if (items == 2)
4121       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4122         &background_color,exception);
4123     else
4124       for (i=2; i < items; i+=2)
4125       {
4126         attribute=(char *) SvPV(ST(i-1),na);
4127         switch (*attribute)
4128         {
4129           case 'B':
4130           case 'b':
4131           {
4132             if (LocaleCompare(attribute,"background") == 0)
4133               {
4134                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4135                   AllCompliance,&background_color,exception);
4136                 break;
4137               }
4138             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4139               attribute);
4140             break;
4141           }
4142           default:
4143           {
4144             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4145               attribute);
4146             break;
4147           }
4148         }
4149       }
4150     image->background_color=background_color;
4151     image=MergeImageLayers(image,FlattenLayer,exception);
4152     if (image == (Image *) NULL)
4153       goto PerlException;
4154     /*
4155       Create blessed Perl array for the returned image.
4156     */
4157     av=newAV();
4158     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4159     SvREFCNT_dec(av);
4160     AddImageToRegistry(sv,image);
4161     rv=newRV(sv);
4162     av_push(av,sv_bless(rv,hv));
4163     SvREFCNT_dec(sv);
4164     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4165     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4166       "flatten-%.*s",(int) (MaxTextExtent-9),
4167       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4168     (void) CopyMagickString(image->filename,info->image_info->filename,
4169       MaxTextExtent);
4170     SetImageInfo(info->image_info,0,exception);
4171     exception=DestroyExceptionInfo(exception);
4172     SvREFCNT_dec(perl_exception);
4173     XSRETURN(1);
4174
4175   PerlException:
4176     InheritPerlException(exception,perl_exception);
4177     exception=DestroyExceptionInfo(exception);
4178     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4179     SvPOK_on(perl_exception);  /* return messages in string context */
4180     ST(0)=sv_2mortal(perl_exception);
4181     XSRETURN(1);
4182   }
4183 \f
4184 #
4185 ###############################################################################
4186 #                                                                             #
4187 #                                                                             #
4188 #                                                                             #
4189 #   F x                                                                       #
4190 #                                                                             #
4191 #                                                                             #
4192 #                                                                             #
4193 ###############################################################################
4194 #
4195 #
4196 void
4197 Fx(ref,...)
4198   Image::Magick ref=NO_INIT
4199   ALIAS:
4200     FxImage  = 1
4201     fx       = 2
4202     fximage  = 3
4203   PPCODE:
4204   {
4205     AV
4206       *av;
4207
4208     char
4209       *attribute,
4210       expression[MaxTextExtent];
4211
4212     ChannelType
4213       channel,
4214       channel_mask;
4215
4216     ExceptionInfo
4217       *exception;
4218
4219     HV
4220       *hv;
4221
4222     Image
4223       *image;
4224
4225     register ssize_t
4226       i;
4227
4228     struct PackageInfo
4229       *info;
4230
4231     SV
4232       *av_reference,
4233       *perl_exception,
4234       *reference,
4235       *rv,
4236       *sv;
4237
4238     PERL_UNUSED_VAR(ref);
4239     PERL_UNUSED_VAR(ix);
4240     exception=AcquireExceptionInfo();
4241     perl_exception=newSVpv("",0);
4242     sv=NULL;
4243     attribute=NULL;
4244     av=NULL;
4245     if (sv_isobject(ST(0)) == 0)
4246       {
4247         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4248           PackageName);
4249         goto PerlException;
4250       }
4251     reference=SvRV(ST(0));
4252     hv=SvSTASH(reference);
4253     av=newAV();
4254     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4255     SvREFCNT_dec(av);
4256     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4257     if (image == (Image *) NULL)
4258       {
4259         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4260           PackageName);
4261         goto PerlException;
4262       }
4263     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4264     /*
4265       Get options.
4266     */
4267     channel=DefaultChannels;
4268     (void) CopyMagickString(expression,"u",MaxTextExtent);
4269     if (items == 2)
4270       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4271     else
4272       for (i=2; i < items; i+=2)
4273       {
4274         attribute=(char *) SvPV(ST(i-1),na);
4275         switch (*attribute)
4276         {
4277           case 'C':
4278           case 'c':
4279           {
4280             if (LocaleCompare(attribute,"channel") == 0)
4281               {
4282                 ssize_t
4283                   option;
4284
4285                 option=ParseChannelOption(SvPV(ST(i),na));
4286                 if (option < 0)
4287                   {
4288                     ThrowPerlException(exception,OptionError,
4289                       "UnrecognizedType",SvPV(ST(i),na));
4290                     return;
4291                   }
4292                 channel=(ChannelType) option;
4293                 break;
4294               }
4295             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4296               attribute);
4297             break;
4298           }
4299           case 'E':
4300           case 'e':
4301           {
4302             if (LocaleCompare(attribute,"expression") == 0)
4303               {
4304                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4305                   MaxTextExtent);
4306                 break;
4307               }
4308             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4309               attribute);
4310             break;
4311           }
4312           default:
4313           {
4314             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4315               attribute);
4316             break;
4317           }
4318         }
4319       }
4320     channel_mask=SetImageChannelMask(image,channel);
4321     image=FxImage(image,expression,exception);
4322     if (image != (Image *) NULL)
4323       (void) SetImageChannelMask(image,channel_mask);
4324     if (image == (Image *) NULL)
4325       goto PerlException;
4326     for ( ; image; image=image->next)
4327     {
4328       AddImageToRegistry(sv,image);
4329       rv=newRV(sv);
4330       av_push(av,sv_bless(rv,hv));
4331       SvREFCNT_dec(sv);
4332     }
4333     exception=DestroyExceptionInfo(exception);
4334     ST(0)=av_reference;
4335     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4336     XSRETURN(1);
4337
4338   PerlException:
4339     InheritPerlException(exception,perl_exception);
4340     exception=DestroyExceptionInfo(exception);
4341     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4342     SvPOK_on(perl_exception);
4343     ST(0)=sv_2mortal(perl_exception);
4344     XSRETURN(1);
4345   }
4346 \f
4347 #
4348 ###############################################################################
4349 #                                                                             #
4350 #                                                                             #
4351 #                                                                             #
4352 #   G e t                                                                     #
4353 #                                                                             #
4354 #                                                                             #
4355 #                                                                             #
4356 ###############################################################################
4357 #
4358 #
4359 void
4360 Get(ref,...)
4361   Image::Magick ref=NO_INIT
4362   ALIAS:
4363     GetAttributes = 1
4364     GetAttribute  = 2
4365     get           = 3
4366     getattributes = 4
4367     getattribute  = 5
4368   PPCODE:
4369   {
4370     char
4371       *attribute,
4372       color[MaxTextExtent];
4373
4374     const char
4375       *value;
4376
4377     ExceptionInfo
4378       *exception;
4379
4380     Image
4381       *image;
4382
4383     long
4384       j;
4385
4386     register ssize_t
4387       i;
4388
4389     struct PackageInfo
4390       *info;
4391
4392     SV
4393       *perl_exception,
4394       *reference,
4395       *s;
4396
4397     PERL_UNUSED_VAR(ref);
4398     PERL_UNUSED_VAR(ix);
4399     exception=AcquireExceptionInfo();
4400     perl_exception=newSVpv("",0);
4401     if (sv_isobject(ST(0)) == 0)
4402       {
4403         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4404           PackageName);
4405         XSRETURN_EMPTY;
4406       }
4407     reference=SvRV(ST(0));
4408     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4409     if (image == (Image *) NULL && !info)
4410       XSRETURN_EMPTY;
4411     EXTEND(sp,items);
4412     for (i=1; i < items; i++)
4413     {
4414       attribute=(char *) SvPV(ST(i),na);
4415       s=NULL;
4416       switch (*attribute)
4417       {
4418         case 'A':
4419         case 'a':
4420         {
4421           if (LocaleCompare(attribute,"adjoin") == 0)
4422             {
4423               if (info)
4424                 s=newSViv((ssize_t) info->image_info->adjoin);
4425               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4426               continue;
4427             }
4428           if (LocaleCompare(attribute,"antialias") == 0)
4429             {
4430               if (info)
4431                 s=newSViv((ssize_t) info->image_info->antialias);
4432               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4433               continue;
4434             }
4435           if (LocaleCompare(attribute,"area") == 0)
4436             {
4437               s=newSViv(GetMagickResource(AreaResource));
4438               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4439               continue;
4440             }
4441           if (LocaleCompare(attribute,"attenuate") == 0)
4442             {
4443               const char
4444                 *value;
4445
4446               value=GetImageProperty(image,attribute,exception);
4447               if (value != (const char *) NULL)
4448                 s=newSVpv(value,0);
4449               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4450               continue;
4451             }
4452           if (LocaleCompare(attribute,"authenticate") == 0)
4453             {
4454               if (info)
4455                 {
4456                   const char
4457                     *option;
4458
4459                   option=GetImageOption(info->image_info,attribute);
4460                   if (option != (const char *) NULL)
4461                     s=newSVpv(option,0);
4462                 }
4463               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4464               continue;
4465             }
4466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4467             attribute);
4468           break;
4469         }
4470         case 'B':
4471         case 'b':
4472         {
4473           if (LocaleCompare(attribute,"background") == 0)
4474             {
4475               if (image == (Image *) NULL)
4476                 break;
4477               (void) FormatLocaleString(color,MaxTextExtent,
4478                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4479                 image->background_color.green,image->background_color.blue,
4480                 image->background_color.alpha);
4481               s=newSVpv(color,0);
4482               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4483               continue;
4484             }
4485           if (LocaleCompare(attribute,"base-columns") == 0)
4486             {
4487               if (image != (Image *) NULL)
4488                 s=newSViv((ssize_t) image->magick_columns);
4489               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4490               continue;
4491             }
4492           if (LocaleCompare(attribute,"base-filename") == 0)
4493             {
4494               if (image != (Image *) NULL)
4495                 s=newSVpv(image->magick_filename,0);
4496               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4497               continue;
4498             }
4499           if (LocaleCompare(attribute,"base-height") == 0)
4500             {
4501               if (image != (Image *) NULL)
4502                 s=newSViv((ssize_t) image->magick_rows);
4503               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4504               continue;
4505             }
4506           if (LocaleCompare(attribute,"base-rows") == 0)
4507             {
4508               if (image != (Image *) NULL)
4509                 s=newSViv((ssize_t) image->magick_rows);
4510               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4511               continue;
4512             }
4513           if (LocaleCompare(attribute,"base-width") == 0)
4514             {
4515               if (image != (Image *) NULL)
4516                 s=newSViv((ssize_t) image->magick_columns);
4517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4518               continue;
4519             }
4520           if (LocaleCompare(attribute,"blue-primary") == 0)
4521             {
4522               if (image == (Image *) NULL)
4523                 break;
4524               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4525                 image->chromaticity.blue_primary.x,
4526                 image->chromaticity.blue_primary.y);
4527               s=newSVpv(color,0);
4528               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4529               continue;
4530             }
4531           if (LocaleCompare(attribute,"bordercolor") == 0)
4532             {
4533               if (image == (Image *) NULL)
4534                 break;
4535               (void) FormatLocaleString(color,MaxTextExtent,
4536                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4537                 image->border_color.green,image->border_color.blue,
4538                 image->border_color.alpha);
4539               s=newSVpv(color,0);
4540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4541               continue;
4542             }
4543           if (LocaleCompare(attribute,"bounding-box") == 0)
4544             {
4545               char
4546                 geometry[MaxTextExtent];
4547
4548               RectangleInfo
4549                 page;
4550
4551               if (image == (Image *) NULL)
4552                 break;
4553               page=GetImageBoundingBox(image,exception);
4554               (void) FormatLocaleString(geometry,MaxTextExtent,
4555                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4556                 page.height,(double) page.x,(double) page.y);
4557               s=newSVpv(geometry,0);
4558               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4559               continue;
4560             }
4561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4562             attribute);
4563           break;
4564         }
4565         case 'C':
4566         case 'c':
4567         {
4568           if (LocaleCompare(attribute,"class") == 0)
4569             {
4570               if (image == (Image *) NULL)
4571                 break;
4572               s=newSViv(image->storage_class);
4573               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4574                 image->storage_class));
4575               SvIOK_on(s);
4576               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4577               continue;
4578             }
4579           if (LocaleCompare(attribute,"clip-mask") == 0)
4580             {
4581               if (image != (Image *) NULL)
4582                 {
4583                   Image
4584                     *mask_image;
4585
4586                   SV
4587                     *sv;
4588
4589                   sv=NULL;
4590                   if (image->mask == MagickFalse)
4591                     ClipImage(image,exception);
4592                   mask_image=GetImageMask(image,exception);
4593                   if (mask_image != (Image *) NULL)
4594                     {
4595                       AddImageToRegistry(sv,mask_image);
4596                       s=sv_bless(newRV(sv),SvSTASH(reference));
4597                     }
4598                 }
4599               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4600               continue;
4601             }
4602           if (LocaleCompare(attribute,"clip-path") == 0)
4603             {
4604               if (image != (Image *) NULL)
4605                 {
4606                   Image
4607                     *mask_image;
4608
4609                   SV
4610                     *sv;
4611
4612                   sv=NULL;
4613                   if (image->mask != MagickFalse)
4614                     ClipImage(image,exception);
4615                   mask_image=GetImageMask(image,exception);
4616                   if (mask_image != (Image *) NULL)
4617                     {
4618                       AddImageToRegistry(sv,mask_image);
4619                       s=sv_bless(newRV(sv),SvSTASH(reference));
4620                     }
4621                 }
4622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4623               continue;
4624             }
4625           if (LocaleCompare(attribute,"compression") == 0)
4626             {
4627               j=info ? info->image_info->compression : image ?
4628                 image->compression : UndefinedCompression;
4629               if (info)
4630                 if (info->image_info->compression == UndefinedCompression)
4631                   j=image->compression;
4632               s=newSViv(j);
4633               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4634                 j));
4635               SvIOK_on(s);
4636               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4637               continue;
4638             }
4639           if (LocaleCompare(attribute,"colorspace") == 0)
4640             {
4641               j=image ? image->colorspace : RGBColorspace;
4642               s=newSViv(j);
4643               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4644                 j));
4645               SvIOK_on(s);
4646               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4647               continue;
4648             }
4649           if (LocaleCompare(attribute,"colors") == 0)
4650             {
4651               if (image != (Image *) NULL)
4652                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4653                   exception));
4654               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4655               continue;
4656             }
4657           if (LocaleNCompare(attribute,"colormap",8) == 0)
4658             {
4659               int
4660                 items;
4661
4662               if (image == (Image *) NULL || !image->colormap)
4663                 break;
4664               j=0;
4665               items=sscanf(attribute,"%*[^[][%ld",&j);
4666               (void) items;
4667               if (j > (ssize_t) image->colors)
4668                 j%=image->colors;
4669               (void) FormatLocaleString(color,MaxTextExtent,
4670                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4671                 image->colormap[j].green,image->colormap[j].blue,
4672                 image->colormap[j].alpha);
4673               s=newSVpv(color,0);
4674               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4675               continue;
4676             }
4677           if (LocaleCompare(attribute,"columns") == 0)
4678             {
4679               if (image != (Image *) NULL)
4680                 s=newSViv((ssize_t) image->columns);
4681               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4682               continue;
4683             }
4684           if (LocaleCompare(attribute,"comment") == 0)
4685             {
4686               const char
4687                 *value;
4688
4689               value=GetImageProperty(image,attribute,exception);
4690               if (value != (const char *) NULL)
4691                 s=newSVpv(value,0);
4692               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4693               continue;
4694             }
4695           if (LocaleCompare(attribute,"copyright") == 0)
4696             {
4697               s=newSVpv(GetMagickCopyright(),0);
4698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4699               continue;
4700             }
4701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4702             attribute);
4703           break;
4704         }
4705         case 'D':
4706         case 'd':
4707         {
4708           if (LocaleCompare(attribute,"density") == 0)
4709             {
4710               char
4711                 geometry[MaxTextExtent];
4712
4713               if (image == (Image *) NULL)
4714                 break;
4715               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4716                 image->resolution.x,image->resolution.y);
4717               s=newSVpv(geometry,0);
4718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4719               continue;
4720             }
4721           if (LocaleCompare(attribute,"delay") == 0)
4722             {
4723               if (image != (Image *) NULL)
4724                 s=newSViv((ssize_t) image->delay);
4725               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4726               continue;
4727             }
4728           if (LocaleCompare(attribute,"depth") == 0)
4729             {
4730               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4731               if (image != (Image *) NULL)
4732                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4733               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4734               continue;
4735             }
4736           if (LocaleCompare(attribute,"directory") == 0)
4737             {
4738               if (image && image->directory)
4739                 s=newSVpv(image->directory,0);
4740               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4741               continue;
4742             }
4743           if (LocaleCompare(attribute,"dispose") == 0)
4744             {
4745               if (image == (Image *) NULL)
4746                 break;
4747
4748               s=newSViv(image->dispose);
4749               (void) sv_setpv(s,
4750                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4751               SvIOK_on(s);
4752               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4753               continue;
4754             }
4755           if (LocaleCompare(attribute,"disk") == 0)
4756             {
4757               s=newSViv(GetMagickResource(DiskResource));
4758               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4759               continue;
4760             }
4761           if (LocaleCompare(attribute,"dither") == 0)
4762             {
4763               if (info)
4764                 s=newSViv((ssize_t) info->image_info->dither);
4765               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4766               continue;
4767             }
4768           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4769             {
4770               if (info && info->image_info->server_name)
4771                 s=newSVpv(info->image_info->server_name,0);
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4776             attribute);
4777           break;
4778         }
4779         case 'E':
4780         case 'e':
4781         {
4782           if (LocaleCompare(attribute,"elapsed-time") == 0)
4783             {
4784               if (image != (Image *) NULL)
4785                 s=newSVnv(GetElapsedTime(&image->timer));
4786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4787               continue;
4788             }
4789           if (LocaleCompare(attribute,"endian") == 0)
4790             {
4791               j=info ? info->image_info->endian : image ? image->endian :
4792                 UndefinedEndian;
4793               s=newSViv(j);
4794               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4795               SvIOK_on(s);
4796               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4797               continue;
4798             }
4799           if (LocaleCompare(attribute,"error") == 0)
4800             {
4801               if (image != (Image *) NULL)
4802                 s=newSVnv(image->error.mean_error_per_pixel);
4803               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4804               continue;
4805             }
4806           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4807             attribute);
4808           break;
4809         }
4810         case 'F':
4811         case 'f':
4812         {
4813           if (LocaleCompare(attribute,"filesize") == 0)
4814             {
4815               if (image != (Image *) NULL)
4816                 s=newSViv((ssize_t) GetBlobSize(image));
4817               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4818               continue;
4819             }
4820           if (LocaleCompare(attribute,"filename") == 0)
4821             {
4822               if (info && info->image_info->filename &&
4823                   *info->image_info->filename)
4824                 s=newSVpv(info->image_info->filename,0);
4825               if (image != (Image *) NULL)
4826                 s=newSVpv(image->filename,0);
4827               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4828               continue;
4829             }
4830           if (LocaleCompare(attribute,"filter") == 0)
4831             {
4832               s=image ? newSViv(image->filter) : newSViv(0);
4833               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4834                 image->filter));
4835               SvIOK_on(s);
4836               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4837               continue;
4838             }
4839           if (LocaleCompare(attribute,"font") == 0)
4840             {
4841               if (info && info->image_info->font)
4842                 s=newSVpv(info->image_info->font,0);
4843               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4844               continue;
4845             }
4846           if (LocaleCompare(attribute,"foreground") == 0)
4847             continue;
4848           if (LocaleCompare(attribute,"format") == 0)
4849             {
4850               const MagickInfo
4851                 *magick_info;
4852
4853               magick_info=(const MagickInfo *) NULL;
4854               if (info && (*info->image_info->magick != '\0'))
4855                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4856               if (image != (Image *) NULL)
4857                 magick_info=GetMagickInfo(image->magick,exception);
4858               if ((magick_info != (const MagickInfo *) NULL) &&
4859                   (*magick_info->description != '\0'))
4860                 s=newSVpv((char *) magick_info->description,0);
4861               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4862               continue;
4863             }
4864           if (LocaleCompare(attribute,"fuzz") == 0)
4865             {
4866               if (info)
4867                 s=newSVnv(info->image_info->fuzz);
4868               if (image != (Image *) NULL)
4869                 s=newSVnv(image->fuzz);
4870               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4871               continue;
4872             }
4873           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4874             attribute);
4875           break;
4876         }
4877         case 'G':
4878         case 'g':
4879         {
4880           if (LocaleCompare(attribute,"gamma") == 0)
4881             {
4882               if (image != (Image *) NULL)
4883                 s=newSVnv(image->gamma);
4884               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4885               continue;
4886             }
4887           if (LocaleCompare(attribute,"geometry") == 0)
4888             {
4889               if (image && image->geometry)
4890                 s=newSVpv(image->geometry,0);
4891               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4892               continue;
4893             }
4894           if (LocaleCompare(attribute,"gravity") == 0)
4895             {
4896               s=image ? newSViv(image->gravity) : newSViv(0);
4897               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4898                 image->gravity));
4899               SvIOK_on(s);
4900               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4901               continue;
4902             }
4903           if (LocaleCompare(attribute,"green-primary") == 0)
4904             {
4905               if (image == (Image *) NULL)
4906                 break;
4907               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4908                 image->chromaticity.green_primary.x,
4909                 image->chromaticity.green_primary.y);
4910               s=newSVpv(color,0);
4911               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4912               continue;
4913             }
4914           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4915             attribute);
4916           break;
4917         }
4918         case 'H':
4919         case 'h':
4920         {
4921           if (LocaleCompare(attribute,"height") == 0)
4922             {
4923               if (image != (Image *) NULL)
4924                 s=newSViv((ssize_t) image->rows);
4925               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926               continue;
4927             }
4928           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4929             attribute);
4930           break;
4931         }
4932         case 'I':
4933         case 'i':
4934         {
4935           if (LocaleCompare(attribute,"icc") == 0)
4936             {
4937               if (image != (Image *) NULL)
4938                 {
4939                   const StringInfo
4940                     *profile;
4941
4942                   profile=GetImageProfile(image,"icc");
4943                   if (profile != (StringInfo *) NULL)
4944                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4945                       GetStringInfoLength(profile));
4946                 }
4947               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4948               continue;
4949             }
4950           if (LocaleCompare(attribute,"icm") == 0)
4951             {
4952               if (image != (Image *) NULL)
4953                 {
4954                   const StringInfo
4955                     *profile;
4956
4957                   profile=GetImageProfile(image,"icm");
4958                   if (profile != (const StringInfo *) NULL)
4959                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4960                       GetStringInfoLength(profile));
4961                 }
4962               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4963               continue;
4964             }
4965           if (LocaleCompare(attribute,"id") == 0)
4966             {
4967               if (image != (Image *) NULL)
4968                 {
4969                   char
4970                     key[MaxTextExtent];
4971
4972                   MagickBooleanType
4973                     status;
4974
4975                   static ssize_t
4976                     id = 0;
4977
4978                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4979                     id);
4980                   status=SetImageRegistry(ImageRegistryType,key,image,
4981                     exception);
4982                   (void) status;
4983                   s=newSViv(id++);
4984                 }
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleNCompare(attribute,"index",5) == 0)
4989             {
4990               char
4991                 name[MaxTextExtent];
4992
4993               int
4994                 items;
4995
4996               long
4997                 x,
4998                 y;
4999
5000               register const Quantum
5001                 *p;
5002
5003               CacheView
5004                 *image_view;
5005
5006               if (image == (Image *) NULL)
5007                 break;
5008               if (image->storage_class != PseudoClass)
5009                 break;
5010               x=0;
5011               y=0;
5012               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5013               (void) items;
5014               image_view=AcquireVirtualCacheView(image,exception);
5015               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5016               if (p != (const Quantum *) NULL)
5017                 {
5018                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5019                     GetPixelIndex(image,p));
5020                   s=newSVpv(name,0);
5021                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5022                 }
5023               image_view=DestroyCacheView(image_view);
5024               continue;
5025             }
5026           if (LocaleCompare(attribute,"iptc") == 0)
5027             {
5028               if (image != (Image *) NULL)
5029                 {
5030                   const StringInfo
5031                     *profile;
5032
5033                   profile=GetImageProfile(image,"iptc");
5034                   if (profile != (const StringInfo *) NULL)
5035                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5036                       GetStringInfoLength(profile));
5037                 }
5038               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5039               continue;
5040             }
5041           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5042             {
5043               if (image != (Image *) NULL)
5044                 s=newSViv((ssize_t) image->iterations);
5045               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5046               continue;
5047             }
5048           if (LocaleCompare(attribute,"interlace") == 0)
5049             {
5050               j=info ? info->image_info->interlace : image ? image->interlace :
5051                 UndefinedInterlace;
5052               s=newSViv(j);
5053               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5054                 j));
5055               SvIOK_on(s);
5056               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5057               continue;
5058             }
5059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5060             attribute);
5061           break;
5062         }
5063         case 'L':
5064         case 'l':
5065         {
5066           if (LocaleCompare(attribute,"label") == 0)
5067             {
5068               const char
5069                 *value;
5070
5071               if (image == (Image *) NULL)
5072                 break;
5073               value=GetImageProperty(image,"Label",exception);
5074               if (value != (const char *) NULL)
5075                 s=newSVpv(value,0);
5076               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5077               continue;
5078             }
5079           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5080             {
5081               if (image != (Image *) NULL)
5082                 s=newSViv((ssize_t) image->iterations);
5083               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5084               continue;
5085             }
5086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5087             attribute);
5088           break;
5089         }
5090         case 'M':
5091         case 'm':
5092         {
5093           if (LocaleCompare(attribute,"magick") == 0)
5094             {
5095               if (info && *info->image_info->magick)
5096                 s=newSVpv(info->image_info->magick,0);
5097               if (image != (Image *) NULL)
5098                 s=newSVpv(image->magick,0);
5099               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5100               continue;
5101             }
5102           if (LocaleCompare(attribute,"map") == 0)
5103             {
5104               s=newSViv(GetMagickResource(MapResource));
5105               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5106               continue;
5107             }
5108           if (LocaleCompare(attribute,"maximum-error") == 0)
5109             {
5110               if (image != (Image *) NULL)
5111                 s=newSVnv(image->error.normalized_maximum_error);
5112               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5113               continue;
5114             }
5115           if (LocaleCompare(attribute,"memory") == 0)
5116             {
5117               s=newSViv(GetMagickResource(MemoryResource));
5118               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5119               continue;
5120             }
5121           if (LocaleCompare(attribute,"mean-error") == 0)
5122             {
5123               if (image != (Image *) NULL)
5124                 s=newSVnv(image->error.normalized_mean_error);
5125               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5126               continue;
5127             }
5128           if (LocaleCompare(attribute,"mime") == 0)
5129             {
5130               if (info && *info->image_info->magick)
5131                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5132               if (image != (Image *) NULL)
5133                 s=newSVpv(MagickToMime(image->magick),0);
5134               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5135               continue;
5136             }
5137           if (LocaleCompare(attribute,"mattecolor") == 0)
5138             {
5139               if (image == (Image *) NULL)
5140                 break;
5141               (void) FormatLocaleString(color,MaxTextExtent,
5142                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5143                 image->matte_color.green,image->matte_color.blue,
5144                 image->matte_color.alpha);
5145               s=newSVpv(color,0);
5146               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5147               continue;
5148             }
5149           if (LocaleCompare(attribute,"matte") == 0)
5150             {
5151               if (image != (Image *) NULL)
5152                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5153                   1 : 0);
5154               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5155               continue;
5156             }
5157           if (LocaleCompare(attribute,"mime") == 0)
5158             {
5159               const char
5160                 *magick;
5161
5162               magick=NULL;
5163               if (info && *info->image_info->magick)
5164                 magick=info->image_info->magick;
5165               if (image != (Image *) NULL)
5166                 magick=image->magick;
5167               if (magick)
5168                 {
5169                   char
5170                     *mime;
5171
5172                   mime=MagickToMime(magick);
5173                   s=newSVpv(mime,0);
5174                   mime=(char *) RelinquishMagickMemory(mime);
5175                 }
5176               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5177               continue;
5178             }
5179           if (LocaleCompare(attribute,"monochrome") == 0)
5180             {
5181               if (image == (Image *) NULL)
5182                 continue;
5183               j=info ? info->image_info->monochrome :
5184                 IsImageMonochrome(image,exception);
5185               s=newSViv(j);
5186               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5187               continue;
5188             }
5189           if (LocaleCompare(attribute,"montage") == 0)
5190             {
5191               if (image && image->montage)
5192                 s=newSVpv(image->montage,0);
5193               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5194               continue;
5195             }
5196           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5197             attribute);
5198           break;
5199         }
5200         case 'O':
5201         case 'o':
5202         {
5203           if (LocaleCompare(attribute,"orientation") == 0)
5204             {
5205               j=info ? info->image_info->orientation : image ?
5206                 image->orientation : UndefinedOrientation;
5207               s=newSViv(j);
5208               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5209                 j));
5210               SvIOK_on(s);
5211               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5212               continue;
5213             }
5214           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5215             attribute);
5216           break;
5217         }
5218         case 'P':
5219         case 'p':
5220         {
5221           if (LocaleCompare(attribute,"page") == 0)
5222             {
5223               if (info && info->image_info->page)
5224                 s=newSVpv(info->image_info->page,0);
5225               if (image != (Image *) NULL)
5226                 {
5227                   char
5228                     geometry[MaxTextExtent];
5229
5230                   (void) FormatLocaleString(geometry,MaxTextExtent,
5231                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5232                     (double) image->page.height,(double) image->page.x,(double)
5233                     image->page.y);
5234                   s=newSVpv(geometry,0);
5235                 }
5236               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5237               continue;
5238             }
5239           if (LocaleCompare(attribute,"page.x") == 0)
5240             {
5241               if (image != (Image *) NULL)
5242                 s=newSViv((ssize_t) image->page.x);
5243               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5244               continue;
5245             }
5246           if (LocaleCompare(attribute,"page.y") == 0)
5247             {
5248               if (image != (Image *) NULL)
5249                 s=newSViv((ssize_t) image->page.y);
5250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5251               continue;
5252             }
5253           if (LocaleNCompare(attribute,"pixel",5) == 0)
5254             {
5255               char
5256                 tuple[MaxTextExtent];
5257
5258               int
5259                 items;
5260
5261               long
5262                 x,
5263                 y;
5264
5265               register const Quantum
5266                 *p;
5267
5268               if (image == (Image *) NULL)
5269                 break;
5270               x=0;
5271               y=0;
5272               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5273               (void) items;
5274               p=GetVirtualPixels(image,x,y,1,1,exception);
5275               if (image->colorspace != CMYKColorspace)
5276                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5277                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5278                   GetPixelRed(image,p),GetPixelGreen(image,p),
5279                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5280               else
5281                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5282                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5283                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5284                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5285                   GetPixelAlpha(image,p));
5286               s=newSVpv(tuple,0);
5287               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5288               continue;
5289             }
5290           if (LocaleCompare(attribute,"pointsize") == 0)
5291             {
5292               if (info)
5293                 s=newSViv((ssize_t) info->image_info->pointsize);
5294               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5295               continue;
5296             }
5297           if (LocaleCompare(attribute,"preview") == 0)
5298             {
5299               s=newSViv(info->image_info->preview_type);
5300               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5301                 info->image_info->preview_type));
5302               SvIOK_on(s);
5303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5304               continue;
5305             }
5306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5307             attribute);
5308           break;
5309         }
5310         case 'Q':
5311         case 'q':
5312         {
5313           if (LocaleCompare(attribute,"quality") == 0)
5314             {
5315               if (info)
5316                 s=newSViv((ssize_t) info->image_info->quality);
5317               if (image != (Image *) NULL)
5318                 s=newSViv((ssize_t) image->quality);
5319               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5320               continue;
5321             }
5322           if (LocaleCompare(attribute,"quantum") == 0)
5323             {
5324               if (info)
5325                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5326               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5327               continue;
5328             }
5329           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5330             attribute);
5331           break;
5332         }
5333         case 'R':
5334         case 'r':
5335         {
5336           if (LocaleCompare(attribute,"rendering-intent") == 0)
5337             {
5338               s=newSViv(image->rendering_intent);
5339               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5340                 image->rendering_intent));
5341               SvIOK_on(s);
5342               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5343               continue;
5344             }
5345           if (LocaleCompare(attribute,"red-primary") == 0)
5346             {
5347               if (image == (Image *) NULL)
5348                 break;
5349               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5350                 image->chromaticity.red_primary.x,
5351                 image->chromaticity.red_primary.y);
5352               s=newSVpv(color,0);
5353               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5354               continue;
5355             }
5356           if (LocaleCompare(attribute,"rows") == 0)
5357             {
5358               if (image != (Image *) NULL)
5359                 s=newSViv((ssize_t) image->rows);
5360               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5361               continue;
5362             }
5363           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5364             attribute);
5365           break;
5366         }
5367         case 'S':
5368         case 's':
5369         {
5370           if (LocaleCompare(attribute,"sampling-factor") == 0)
5371             {
5372               if (info && info->image_info->sampling_factor)
5373                 s=newSVpv(info->image_info->sampling_factor,0);
5374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5375               continue;
5376             }
5377           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5378             {
5379               if (info && info->image_info->server_name)
5380                 s=newSVpv(info->image_info->server_name,0);
5381               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5382               continue;
5383             }
5384           if (LocaleCompare(attribute,"size") == 0)
5385             {
5386               if (info && info->image_info->size)
5387                 s=newSVpv(info->image_info->size,0);
5388               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5389               continue;
5390             }
5391           if (LocaleCompare(attribute,"scene") == 0)
5392             {
5393               if (image != (Image *) NULL)
5394                 s=newSViv((ssize_t) image->scene);
5395               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5396               continue;
5397             }
5398           if (LocaleCompare(attribute,"scenes") == 0)
5399             {
5400               if (image != (Image *) NULL)
5401                 s=newSViv((ssize_t) info->image_info->number_scenes);
5402               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403               continue;
5404             }
5405           if (LocaleCompare(attribute,"signature") == 0)
5406             {
5407               const char
5408                 *value;
5409
5410               if (image == (Image *) NULL)
5411                 break;
5412               (void) SignatureImage(image,exception);
5413               value=GetImageProperty(image,"Signature",exception);
5414               if (value != (const char *) NULL)
5415                 s=newSVpv(value,0);
5416               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5417               continue;
5418             }
5419           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5420             attribute);
5421           break;
5422         }
5423         case 'T':
5424         case 't':
5425         {
5426           if (LocaleCompare(attribute,"taint") == 0)
5427             {
5428               if (image != (Image *) NULL)
5429                 s=newSViv((ssize_t) IsTaintImage(image));
5430               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5431               continue;
5432             }
5433           if (LocaleCompare(attribute,"texture") == 0)
5434             {
5435               if (info && info->image_info->texture)
5436                 s=newSVpv(info->image_info->texture,0);
5437               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5438               continue;
5439             }
5440           if (LocaleCompare(attribute,"total-ink-density") == 0)
5441             {
5442               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5443               if (image != (Image *) NULL)
5444                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5445               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5446               continue;
5447             }
5448           if (LocaleCompare(attribute,"transparent-color") == 0)
5449             {
5450               if (image == (Image *) NULL)
5451                 break;
5452               (void) FormatLocaleString(color,MaxTextExtent,
5453                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5454                 image->transparent_color.green,image->transparent_color.blue,
5455                 image->transparent_color.alpha);
5456               s=newSVpv(color,0);
5457               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5458               continue;
5459             }
5460           if (LocaleCompare(attribute,"type") == 0)
5461             {
5462               if (image == (Image *) NULL)
5463                 break;
5464               j=(ssize_t) GetImageType(image,exception);
5465               s=newSViv(j);
5466               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5467               SvIOK_on(s);
5468               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5469               continue;
5470             }
5471           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5472             attribute);
5473           break;
5474         }
5475         case 'U':
5476         case 'u':
5477         {
5478           if (LocaleCompare(attribute,"units") == 0)
5479             {
5480               j=info ? info->image_info->units : image ? image->units :
5481                 UndefinedResolution;
5482               if (info && (info->image_info->units == UndefinedResolution))
5483                 if (image)
5484                   j=image->units;
5485               if (j == UndefinedResolution)
5486                 s=newSVpv("undefined units",0);
5487               else
5488                 if (j == PixelsPerInchResolution)
5489                   s=newSVpv("pixels / inch",0);
5490                 else
5491                   s=newSVpv("pixels / centimeter",0);
5492               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5493               continue;
5494             }
5495           if (LocaleCompare(attribute,"user-time") == 0)
5496             {
5497               if (image != (Image *) NULL)
5498                 s=newSVnv(GetUserTime(&image->timer));
5499               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5500               continue;
5501             }
5502           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5503             attribute);
5504           break;
5505         }
5506         case 'V':
5507         case 'v':
5508         {
5509           if (LocaleCompare(attribute,"verbose") == 0)
5510             {
5511               if (info)
5512                 s=newSViv((ssize_t) info->image_info->verbose);
5513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5514               continue;
5515             }
5516           if (LocaleCompare(attribute,"version") == 0)
5517             {
5518               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5519               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5520               continue;
5521             }
5522           if (LocaleCompare(attribute,"view") == 0)
5523             {
5524               if (info && info->image_info->view)
5525                 s=newSVpv(info->image_info->view,0);
5526               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5527               continue;
5528             }
5529           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5530             {
5531               if (image == (Image *) NULL)
5532                 break;
5533               j=(ssize_t) GetImageVirtualPixelMethod(image);
5534               s=newSViv(j);
5535               (void) sv_setpv(s,CommandOptionToMnemonic(
5536                 MagickVirtualPixelOptions,j));
5537               SvIOK_on(s);
5538               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5539               continue;
5540             }
5541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5542             attribute);
5543           break;
5544         }
5545         case 'W':
5546         case 'w':
5547         {
5548           if (LocaleCompare(attribute,"white-point") == 0)
5549             {
5550               if (image == (Image *) NULL)
5551                 break;
5552               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5553                 image->chromaticity.white_point.x,
5554                 image->chromaticity.white_point.y);
5555               s=newSVpv(color,0);
5556               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5557               continue;
5558             }
5559           if (LocaleCompare(attribute,"width") == 0)
5560             {
5561               if (image != (Image *) NULL)
5562                 s=newSViv((ssize_t) image->columns);
5563               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5564               continue;
5565             }
5566           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5567              attribute);
5568           break;
5569         }
5570         case 'X':
5571         case 'x':
5572         {
5573           if (LocaleCompare(attribute,"x-resolution") == 0)
5574             {
5575               if (image != (Image *) NULL)
5576                 s=newSVnv(image->resolution.x);
5577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5578               continue;
5579             }
5580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5581             attribute);
5582           break;
5583         }
5584         case 'Y':
5585         case 'y':
5586         {
5587           if (LocaleCompare(attribute,"y-resolution") == 0)
5588             {
5589               if (image != (Image *) NULL)
5590                 s=newSVnv(image->resolution.y);
5591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5592               continue;
5593             }
5594           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5595             attribute);
5596           break;
5597         }
5598         default:
5599           break;
5600       }
5601       if (image == (Image *) NULL)
5602         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5603           attribute)
5604       else
5605         {
5606           value=GetImageProperty(image,attribute,exception);
5607           if (value != (const char *) NULL)
5608             {
5609               s=newSVpv(value,0);
5610               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5611             }
5612           else
5613             if (*attribute != '%')
5614               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5615                 attribute)
5616             else
5617               {
5618                  char
5619                    *meta;
5620
5621                  meta=InterpretImageProperties(info ? info->image_info :
5622                    (ImageInfo *) NULL,image,attribute,exception);
5623                  s=newSVpv(meta,0);
5624                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5625                  meta=(char *) RelinquishMagickMemory(meta);
5626               }
5627         }
5628     }
5629     exception=DestroyExceptionInfo(exception);
5630     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5631   }
5632 \f
5633 #
5634 ###############################################################################
5635 #                                                                             #
5636 #                                                                             #
5637 #                                                                             #
5638 #   G e t A u t h e n t i c P i x e l s                                       #
5639 #                                                                             #
5640 #                                                                             #
5641 #                                                                             #
5642 ###############################################################################
5643 #
5644 #
5645 void *
5646 GetAuthenticPixels(ref,...)
5647   Image::Magick ref = NO_INIT
5648   ALIAS:
5649     getauthenticpixels = 1
5650     GetImagePixels = 2
5651     getimagepixels = 3
5652   CODE:
5653   {
5654     char
5655       *attribute;
5656
5657     ExceptionInfo
5658       *exception;
5659
5660     Image
5661       *image;
5662
5663     RectangleInfo
5664       region;
5665
5666     ssize_t
5667       i;
5668
5669     struct PackageInfo
5670       *info;
5671
5672     SV
5673       *perl_exception,
5674       *reference;
5675
5676     void
5677       *blob = NULL;
5678
5679     PERL_UNUSED_VAR(ref);
5680     PERL_UNUSED_VAR(ix);
5681     exception=AcquireExceptionInfo();
5682     perl_exception=newSVpv("",0);
5683     if (sv_isobject(ST(0)) == 0)
5684       {
5685         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5686           PackageName);
5687         goto PerlException;
5688       }
5689     reference=SvRV(ST(0));
5690
5691     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5692     if (image == (Image *) NULL)
5693       {
5694         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5695           PackageName);
5696         goto PerlException;
5697       }
5698
5699     region.x=0;
5700     region.y=0;
5701     region.width=image->columns;
5702     region.height=1;
5703     if (items == 1)
5704       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5705     for (i=2; i < items; i+=2)
5706     {
5707       attribute=(char *) SvPV(ST(i-1),na);
5708       switch (*attribute)
5709       {
5710         case 'g':
5711         case 'G':
5712         {
5713           if (LocaleCompare(attribute,"geometry") == 0)
5714             {
5715               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5716               break;
5717             }
5718           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5719             attribute);
5720           break;
5721         }
5722         case 'H':
5723         case 'h':
5724         {
5725           if (LocaleCompare(attribute,"height") == 0)
5726             {
5727               region.height=SvIV(ST(i));
5728               continue;
5729             }
5730           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5731             attribute);
5732           break;
5733         }
5734         case 'X':
5735         case 'x':
5736         {
5737           if (LocaleCompare(attribute,"x") == 0)
5738             {
5739               region.x=SvIV(ST(i));
5740               continue;
5741             }
5742           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5743             attribute);
5744           break;
5745         }
5746         case 'Y':
5747         case 'y':
5748         {
5749           if (LocaleCompare(attribute,"y") == 0)
5750             {
5751               region.y=SvIV(ST(i));
5752               continue;
5753             }
5754           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5755             attribute);
5756           break;
5757         }
5758         case 'W':
5759         case 'w':
5760         {
5761           if (LocaleCompare(attribute,"width") == 0)
5762             {
5763               region.width=SvIV(ST(i));
5764               continue;
5765             }
5766           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5767             attribute);
5768           break;
5769         }
5770       }
5771     }
5772     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5773       region.height,exception);
5774     if (blob != (void *) NULL)
5775       goto PerlEnd;
5776
5777   PerlException:
5778     InheritPerlException(exception,perl_exception);
5779     exception=DestroyExceptionInfo(exception);
5780     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5781
5782   PerlEnd:
5783     RETVAL = blob;
5784   }
5785   OUTPUT:
5786     RETVAL
5787 \f
5788 #
5789 ###############################################################################
5790 #                                                                             #
5791 #                                                                             #
5792 #                                                                             #
5793 #   G e t V i r t u a l P i x e l s                                           #
5794 #                                                                             #
5795 #                                                                             #
5796 #                                                                             #
5797 ###############################################################################
5798 #
5799 #
5800 void *
5801 GetVirtualPixels(ref,...)
5802   Image::Magick ref = NO_INIT
5803   ALIAS:
5804     getvirtualpixels = 1
5805     AcquireImagePixels = 2
5806     acquireimagepixels = 3
5807   CODE:
5808   {
5809     char
5810       *attribute;
5811
5812     const void
5813       *blob = NULL;
5814
5815     ExceptionInfo
5816       *exception;
5817
5818     Image
5819       *image;
5820
5821     RectangleInfo
5822       region;
5823
5824     ssize_t
5825       i;
5826
5827     struct PackageInfo
5828       *info;
5829
5830     SV
5831       *perl_exception,
5832       *reference;
5833
5834     PERL_UNUSED_VAR(ref);
5835     PERL_UNUSED_VAR(ix);
5836     exception=AcquireExceptionInfo();
5837     perl_exception=newSVpv("",0);
5838     if (sv_isobject(ST(0)) == 0)
5839       {
5840         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5841           PackageName);
5842         goto PerlException;
5843       }
5844     reference=SvRV(ST(0));
5845
5846     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5847     if (image == (Image *) NULL)
5848       {
5849         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5850           PackageName);
5851         goto PerlException;
5852       }
5853
5854     region.x=0;
5855     region.y=0;
5856     region.width=image->columns;
5857     region.height=1;
5858     if (items == 1)
5859       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5860     for (i=2; i < items; i+=2)
5861     {
5862       attribute=(char *) SvPV(ST(i-1),na);
5863       switch (*attribute)
5864       {
5865         case 'g':
5866         case 'G':
5867         {
5868           if (LocaleCompare(attribute,"geometry") == 0)
5869             {
5870               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5871               break;
5872             }
5873           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5874             attribute);
5875           break;
5876         }
5877         case 'H':
5878         case 'h':
5879         {
5880           if (LocaleCompare(attribute,"height") == 0)
5881             {
5882               region.height=SvIV(ST(i));
5883               continue;
5884             }
5885           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5886             attribute);
5887           break;
5888         }
5889         case 'X':
5890         case 'x':
5891         {
5892           if (LocaleCompare(attribute,"x") == 0)
5893             {
5894               region.x=SvIV(ST(i));
5895               continue;
5896             }
5897           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5898             attribute);
5899           break;
5900         }
5901         case 'Y':
5902         case 'y':
5903         {
5904           if (LocaleCompare(attribute,"y") == 0)
5905             {
5906               region.y=SvIV(ST(i));
5907               continue;
5908             }
5909           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5910             attribute);
5911           break;
5912         }
5913         case 'W':
5914         case 'w':
5915         {
5916           if (LocaleCompare(attribute,"width") == 0)
5917             {
5918               region.width=SvIV(ST(i));
5919               continue;
5920             }
5921           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5922             attribute);
5923           break;
5924         }
5925       }
5926     }
5927     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5928       region.height,exception);
5929     if (blob != (void *) NULL)
5930       goto PerlEnd;
5931
5932   PerlException:
5933     InheritPerlException(exception,perl_exception);
5934     exception=DestroyExceptionInfo(exception);
5935     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5936
5937   PerlEnd:
5938     RETVAL = (void *) blob;
5939   }
5940   OUTPUT:
5941     RETVAL
5942 \f
5943 #
5944 ###############################################################################
5945 #                                                                             #
5946 #                                                                             #
5947 #                                                                             #
5948 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5949 #                                                                             #
5950 #                                                                             #
5951 #                                                                             #
5952 ###############################################################################
5953 #
5954 #
5955 void *
5956 GetAuthenticMetacontent(ref,...)
5957   Image::Magick ref = NO_INIT
5958   ALIAS:
5959     getauthenticmetacontent = 1
5960     GetMetacontent = 2
5961     getmetacontent = 3
5962   CODE:
5963   {
5964     ExceptionInfo
5965       *exception;
5966
5967     Image
5968       *image;
5969
5970     struct PackageInfo
5971       *info;
5972
5973     SV
5974       *perl_exception,
5975       *reference;
5976
5977     void
5978       *blob = NULL;
5979
5980     PERL_UNUSED_VAR(ref);
5981     PERL_UNUSED_VAR(ix);
5982     exception=AcquireExceptionInfo();
5983     perl_exception=newSVpv("",0);
5984     if (sv_isobject(ST(0)) == 0)
5985       {
5986         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5987           PackageName);
5988         goto PerlException;
5989       }
5990     reference=SvRV(ST(0));
5991
5992     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5993     if (image == (Image *) NULL)
5994       {
5995         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5996           PackageName);
5997         goto PerlException;
5998       }
5999
6000     blob=(void *) GetAuthenticMetacontent(image);
6001     if (blob != (void *) NULL)
6002       goto PerlEnd;
6003
6004   PerlException:
6005     InheritPerlException(exception,perl_exception);
6006     exception=DestroyExceptionInfo(exception);
6007     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6008
6009   PerlEnd:
6010     RETVAL = blob;
6011   }
6012   OUTPUT:
6013     RETVAL
6014 \f
6015 #
6016 ###############################################################################
6017 #                                                                             #
6018 #                                                                             #
6019 #                                                                             #
6020 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6021 #                                                                             #
6022 #                                                                             #
6023 #                                                                             #
6024 ###############################################################################
6025 #
6026 #
6027 void *
6028 GetVirtualMetacontent(ref,...)
6029   Image::Magick ref = NO_INIT
6030   ALIAS:
6031     getvirtualmetacontent = 1
6032   CODE:
6033   {
6034     ExceptionInfo
6035       *exception;
6036
6037     Image
6038       *image;
6039
6040     struct PackageInfo
6041       *info;
6042
6043     SV
6044       *perl_exception,
6045       *reference;
6046
6047     void
6048       *blob = NULL;
6049
6050     PERL_UNUSED_VAR(ref);
6051     PERL_UNUSED_VAR(ix);
6052     exception=AcquireExceptionInfo();
6053     perl_exception=newSVpv("",0);
6054     if (sv_isobject(ST(0)) == 0)
6055       {
6056         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6057           PackageName);
6058         goto PerlException;
6059       }
6060     reference=SvRV(ST(0));
6061
6062     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6063     if (image == (Image *) NULL)
6064       {
6065         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6066           PackageName);
6067         goto PerlException;
6068       }
6069
6070     blob=(void *) GetVirtualMetacontent(image);
6071     if (blob != (void *) NULL)
6072       goto PerlEnd;
6073
6074   PerlException:
6075     InheritPerlException(exception,perl_exception);
6076     exception=DestroyExceptionInfo(exception);
6077     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6078
6079   PerlEnd:
6080     RETVAL = blob;
6081   }
6082   OUTPUT:
6083     RETVAL
6084 \f
6085 #
6086 ###############################################################################
6087 #                                                                             #
6088 #                                                                             #
6089 #                                                                             #
6090 #   H i s t o g r a m                                                         #
6091 #                                                                             #
6092 #                                                                             #
6093 #                                                                             #
6094 ###############################################################################
6095 #
6096 #
6097 void
6098 Histogram(ref,...)
6099   Image::Magick ref=NO_INIT
6100   ALIAS:
6101     HistogramImage = 1
6102     histogram      = 2
6103     histogramimage = 3
6104   PPCODE:
6105   {
6106     AV
6107       *av;
6108
6109     char
6110       message[MaxTextExtent];
6111
6112     PixelInfo
6113       *histogram;
6114
6115     ExceptionInfo
6116       *exception;
6117
6118     Image
6119       *image;
6120
6121     register ssize_t
6122       i;
6123
6124     ssize_t
6125       count;
6126
6127     struct PackageInfo
6128       *info;
6129
6130     SV
6131       *perl_exception,
6132       *reference;
6133
6134     size_t
6135       number_colors;
6136
6137     PERL_UNUSED_VAR(ref);
6138     PERL_UNUSED_VAR(ix);
6139     exception=AcquireExceptionInfo();
6140     perl_exception=newSVpv("",0);
6141     av=NULL;
6142     if (sv_isobject(ST(0)) == 0)
6143       {
6144         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6145           PackageName);
6146         goto PerlException;
6147       }
6148     reference=SvRV(ST(0));
6149     av=newAV();
6150     SvREFCNT_dec(av);
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     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6159     count=0;
6160     for ( ; image; image=image->next)
6161     {
6162       histogram=GetImageHistogram(image,&number_colors,exception);
6163       if (histogram == (PixelInfo *) NULL)
6164         continue;
6165       count+=(ssize_t) number_colors;
6166       EXTEND(sp,6*count);
6167       for (i=0; i < (ssize_t) number_colors; i++)
6168       {
6169         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6170           histogram[i].red);
6171         PUSHs(sv_2mortal(newSVpv(message,0)));
6172         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6173           histogram[i].green);
6174         PUSHs(sv_2mortal(newSVpv(message,0)));
6175         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6176           histogram[i].blue);
6177         PUSHs(sv_2mortal(newSVpv(message,0)));
6178         if (image->colorspace == CMYKColorspace)
6179           {
6180             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6181               histogram[i].black);
6182             PUSHs(sv_2mortal(newSVpv(message,0)));
6183           }
6184         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6185           histogram[i].alpha);
6186         PUSHs(sv_2mortal(newSVpv(message,0)));
6187         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6188           histogram[i].count);
6189         PUSHs(sv_2mortal(newSVpv(message,0)));
6190       }
6191       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6192     }
6193
6194   PerlException:
6195     InheritPerlException(exception,perl_exception);
6196     exception=DestroyExceptionInfo(exception);
6197     SvREFCNT_dec(perl_exception);
6198   }
6199 \f
6200 #
6201 ###############################################################################
6202 #                                                                             #
6203 #                                                                             #
6204 #                                                                             #
6205 #   G e t P i x e l                                                           #
6206 #                                                                             #
6207 #                                                                             #
6208 #                                                                             #
6209 ###############################################################################
6210 #
6211 #
6212 void
6213 GetPixel(ref,...)
6214   Image::Magick ref=NO_INIT
6215   ALIAS:
6216     getpixel = 1
6217     getPixel = 2
6218   PPCODE:
6219   {
6220     AV
6221       *av;
6222
6223     char
6224       *attribute;
6225
6226     ExceptionInfo
6227       *exception;
6228
6229     Image
6230       *image;
6231
6232     MagickBooleanType
6233       normalize;
6234
6235     RectangleInfo
6236       region;
6237
6238     register const Quantum
6239       *p;
6240
6241     register ssize_t
6242       i;
6243
6244     ssize_t
6245       option;
6246
6247     struct PackageInfo
6248       *info;
6249
6250     SV
6251       *perl_exception,
6252       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6253
6254     PERL_UNUSED_VAR(ref);
6255     PERL_UNUSED_VAR(ix);
6256     exception=AcquireExceptionInfo();
6257     perl_exception=newSVpv("",0);
6258     reference=SvRV(ST(0));
6259     av=(AV *) reference;
6260     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6261       exception);
6262     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6263     if (image == (Image *) NULL)
6264       {
6265         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6266           PackageName);
6267         goto PerlException;
6268       }
6269     normalize=MagickTrue;
6270     region.x=0;
6271     region.y=0;
6272     region.width=image->columns;
6273     region.height=1;
6274     if (items == 1)
6275       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6276     for (i=2; i < items; i+=2)
6277     {
6278       attribute=(char *) SvPV(ST(i-1),na);
6279       switch (*attribute)
6280       {
6281         case 'C':
6282         case 'c':
6283         {
6284           if (LocaleCompare(attribute,"channel") == 0)
6285             {
6286               ssize_t
6287                 option;
6288
6289               option=ParseChannelOption(SvPV(ST(i),na));
6290               if (option < 0)
6291                 {
6292                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6293                     SvPV(ST(i),na));
6294                   return;
6295                 }
6296               SetPixelChannelMask(image,(ChannelType) option);
6297               break;
6298             }
6299           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6300             attribute);
6301           break;
6302         }
6303         case 'g':
6304         case 'G':
6305         {
6306           if (LocaleCompare(attribute,"geometry") == 0)
6307             {
6308               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6309               break;
6310             }
6311           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6312             attribute);
6313           break;
6314         }
6315         case 'N':
6316         case 'n':
6317         {
6318           if (LocaleCompare(attribute,"normalize") == 0)
6319             {
6320               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6321                 SvPV(ST(i),na));
6322               if (option < 0)
6323                 {
6324                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6325                     SvPV(ST(i),na));
6326                   break;
6327                 }
6328              normalize=option != 0 ? MagickTrue : MagickFalse;
6329              break;
6330             }
6331           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6332             attribute);
6333           break;
6334         }
6335         case 'x':
6336         case 'X':
6337         {
6338           if (LocaleCompare(attribute,"x") == 0)
6339             {
6340               region.x=SvIV(ST(i));
6341               break;
6342             }
6343           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6344             attribute);
6345           break;
6346         }
6347         case 'y':
6348         case 'Y':
6349         {
6350           if (LocaleCompare(attribute,"y") == 0)
6351             {
6352               region.y=SvIV(ST(i));
6353               break;
6354             }
6355           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6356             attribute);
6357           break;
6358         }
6359         default:
6360         {
6361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6362             attribute);
6363           break;
6364         }
6365       }
6366     }
6367     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6368     if (p == (const Quantum *) NULL)
6369       PUSHs(&sv_undef);
6370     else
6371       {
6372         double
6373           scale;
6374
6375         scale=1.0;
6376         if (normalize != MagickFalse)
6377           scale=1.0/QuantumRange;
6378         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6379           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6380         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6381           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6382         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6383           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6384         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6385             (image->colorspace == CMYKColorspace))
6386           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6387         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6388           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6389       }
6390
6391   PerlException:
6392     InheritPerlException(exception,perl_exception);
6393     exception=DestroyExceptionInfo(exception);
6394     SvREFCNT_dec(perl_exception);
6395   }
6396 \f
6397 #
6398 ###############################################################################
6399 #                                                                             #
6400 #                                                                             #
6401 #                                                                             #
6402 #   G e t P i x e l s                                                         #
6403 #                                                                             #
6404 #                                                                             #
6405 #                                                                             #
6406 ###############################################################################
6407 #
6408 #
6409 void
6410 GetPixels(ref,...)
6411   Image::Magick ref=NO_INIT
6412   ALIAS:
6413     getpixels = 1
6414     getPixels = 2
6415   PPCODE:
6416   {
6417     AV
6418       *av;
6419
6420     char
6421       *attribute;
6422
6423     const char
6424       *map;
6425
6426     ExceptionInfo
6427       *exception;
6428
6429     Image
6430       *image;
6431
6432     MagickBooleanType
6433       normalize,
6434       status;
6435
6436     RectangleInfo
6437       region;
6438
6439     register ssize_t
6440       i;
6441
6442     ssize_t
6443       option;
6444
6445     struct PackageInfo
6446       *info;
6447
6448     SV
6449       *perl_exception,
6450       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6451
6452     PERL_UNUSED_VAR(ref);
6453     PERL_UNUSED_VAR(ix);
6454     exception=AcquireExceptionInfo();
6455     perl_exception=newSVpv("",0);
6456     reference=SvRV(ST(0));
6457     av=(AV *) reference;
6458     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6459       exception);
6460     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6461     if (image == (Image *) NULL)
6462       {
6463         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6464           PackageName);
6465         goto PerlException;
6466       }
6467     map="RGB";
6468     if (image->alpha_trait == BlendPixelTrait)
6469       map="RGBA";
6470     if (image->colorspace == CMYKColorspace)
6471       {
6472         map="CMYK";
6473         if (image->alpha_trait == BlendPixelTrait)
6474           map="CMYKA";
6475       }
6476     normalize=MagickFalse;
6477     region.x=0;
6478     region.y=0;
6479     region.width=image->columns;
6480     region.height=1;
6481     if (items == 1)
6482       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6483     for (i=2; i < items; i+=2)
6484     {
6485       attribute=(char *) SvPV(ST(i-1),na);
6486       switch (*attribute)
6487       {
6488         case 'g':
6489         case 'G':
6490         {
6491           if (LocaleCompare(attribute,"geometry") == 0)
6492             {
6493               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6494               break;
6495             }
6496           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6497             attribute);
6498           break;
6499         }
6500         case 'H':
6501         case 'h':
6502         {
6503           if (LocaleCompare(attribute,"height") == 0)
6504             {
6505               region.height=SvIV(ST(i));
6506               break;
6507             }
6508           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6509             attribute);
6510           break;
6511         }
6512         case 'M':
6513         case 'm':
6514         {
6515           if (LocaleCompare(attribute,"map") == 0)
6516             {
6517               map=SvPV(ST(i),na);
6518               break;
6519             }
6520           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6521             attribute);
6522           break;
6523         }
6524         case 'N':
6525         case 'n':
6526         {
6527           if (LocaleCompare(attribute,"normalize") == 0)
6528             {
6529               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6530                 SvPV(ST(i),na));
6531               if (option < 0)
6532                 {
6533                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6534                     SvPV(ST(i),na));
6535                   break;
6536                 }
6537              normalize=option != 0 ? MagickTrue : MagickFalse;
6538              break;
6539             }
6540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6541             attribute);
6542           break;
6543         }
6544         case 'W':
6545         case 'w':
6546         {
6547           if (LocaleCompare(attribute,"width") == 0)
6548             {
6549               region.width=SvIV(ST(i));
6550               break;
6551             }
6552           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6553             attribute);
6554           break;
6555         }
6556         case 'x':
6557         case 'X':
6558         {
6559           if (LocaleCompare(attribute,"x") == 0)
6560             {
6561               region.x=SvIV(ST(i));
6562               break;
6563             }
6564           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6565             attribute);
6566           break;
6567         }
6568         case 'y':
6569         case 'Y':
6570         {
6571           if (LocaleCompare(attribute,"y") == 0)
6572             {
6573               region.y=SvIV(ST(i));
6574               break;
6575             }
6576           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6577             attribute);
6578           break;
6579         }
6580         default:
6581         {
6582           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6583             attribute);
6584           break;
6585         }
6586       }
6587     }
6588     if (normalize != MagickFalse)
6589       {
6590         float
6591           *pixels;
6592
6593         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6594           region.height*sizeof(*pixels));
6595         if (pixels == (float *) NULL)
6596           {
6597             ThrowPerlException(exception,ResourceLimitError,
6598               "MemoryAllocationFailed",PackageName);
6599             goto PerlException;
6600           }
6601         status=ExportImagePixels(image,region.x,region.y,region.width,
6602           region.height,map,FloatPixel,pixels,exception);
6603         if (status == MagickFalse)
6604           PUSHs(&sv_undef);
6605         else
6606           {
6607             EXTEND(sp,strlen(map)*region.width*region.height);
6608             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6609               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6610           }
6611         pixels=(float *) RelinquishMagickMemory(pixels);
6612       }
6613     else
6614       {
6615         Quantum
6616           *pixels;
6617
6618         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6619           region.height*sizeof(*pixels));
6620         if (pixels == (Quantum *) NULL)
6621           {
6622             ThrowPerlException(exception,ResourceLimitError,
6623               "MemoryAllocationFailed",PackageName);
6624             goto PerlException;
6625           }
6626         status=ExportImagePixels(image,region.x,region.y,region.width,
6627           region.height,map,QuantumPixel,pixels,exception);
6628         if (status == MagickFalse)
6629           PUSHs(&sv_undef);
6630         else
6631           {
6632             EXTEND(sp,strlen(map)*region.width*region.height);
6633             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6634               PUSHs(sv_2mortal(newSViv(pixels[i])));
6635           }
6636         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6637       }
6638
6639   PerlException:
6640     InheritPerlException(exception,perl_exception);
6641     exception=DestroyExceptionInfo(exception);
6642     SvREFCNT_dec(perl_exception);
6643   }
6644 \f
6645 #
6646 ###############################################################################
6647 #                                                                             #
6648 #                                                                             #
6649 #                                                                             #
6650 #   I m a g e T o B l o b                                                     #
6651 #                                                                             #
6652 #                                                                             #
6653 #                                                                             #
6654 ###############################################################################
6655 #
6656 #
6657 void
6658 ImageToBlob(ref,...)
6659   Image::Magick ref=NO_INIT
6660   ALIAS:
6661     ImageToBlob  = 1
6662     imagetoblob  = 2
6663     toblob       = 3
6664     blob         = 4
6665   PPCODE:
6666   {
6667     char
6668       filename[MaxTextExtent];
6669
6670     ExceptionInfo
6671       *exception;
6672
6673     Image
6674       *image,
6675       *next;
6676
6677     register ssize_t
6678       i;
6679
6680     struct PackageInfo
6681       *info,
6682       *package_info;
6683
6684     size_t
6685       length;
6686
6687     ssize_t
6688       scene;
6689
6690     SV
6691       *perl_exception,
6692       *reference;
6693
6694     void
6695       *blob;
6696
6697     PERL_UNUSED_VAR(ref);
6698     PERL_UNUSED_VAR(ix);
6699     exception=AcquireExceptionInfo();
6700     perl_exception=newSVpv("",0);
6701     package_info=(struct PackageInfo *) NULL;
6702     if (sv_isobject(ST(0)) == 0)
6703       {
6704         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6705           PackageName);
6706         goto PerlException;
6707       }
6708     reference=SvRV(ST(0));
6709     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6710     if (image == (Image *) NULL)
6711       {
6712         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6713           PackageName);
6714         goto PerlException;
6715       }
6716     package_info=ClonePackageInfo(info,exception);
6717     for (i=2; i < items; i+=2)
6718       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6719     (void) CopyMagickString(filename,package_info->image_info->filename,
6720       MaxTextExtent);
6721     scene=0;
6722     for (next=image; next; next=next->next)
6723     {
6724       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6725       next->scene=scene++;
6726     }
6727     SetImageInfo(package_info->image_info,(unsigned int)
6728       GetImageListLength(image),exception);
6729     EXTEND(sp,(ssize_t) GetImageListLength(image));
6730     for ( ; image; image=image->next)
6731     {
6732       length=0;
6733       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6734       if (blob != (char *) NULL)
6735         {
6736           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6737           blob=(unsigned char *) RelinquishMagickMemory(blob);
6738         }
6739       if (package_info->image_info->adjoin)
6740         break;
6741     }
6742
6743   PerlException:
6744     if (package_info != (struct PackageInfo *) NULL)
6745       DestroyPackageInfo(package_info);
6746     InheritPerlException(exception,perl_exception);
6747     exception=DestroyExceptionInfo(exception);
6748     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6749   }
6750 \f
6751 #
6752 ###############################################################################
6753 #                                                                             #
6754 #                                                                             #
6755 #                                                                             #
6756 #   L a y e r s                                                               #
6757 #                                                                             #
6758 #                                                                             #
6759 #                                                                             #
6760 ###############################################################################
6761 #
6762 #
6763 void
6764 Layers(ref,...)
6765   Image::Magick ref=NO_INIT
6766   ALIAS:
6767     Layers                = 1
6768     layers           = 2
6769     OptimizeImageLayers   = 3
6770     optimizelayers        = 4
6771     optimizeimagelayers   = 5
6772   PPCODE:
6773   {
6774     AV
6775       *av;
6776
6777     char
6778       *attribute;
6779
6780     CompositeOperator
6781       compose;
6782
6783     ExceptionInfo
6784       *exception;
6785
6786     HV
6787       *hv;
6788
6789     Image
6790       *image,
6791       *layers;
6792
6793     LayerMethod
6794       method;
6795
6796     register ssize_t
6797       i;
6798
6799     ssize_t
6800       option,
6801       sp;
6802
6803     struct PackageInfo
6804       *info;
6805
6806     SV
6807       *av_reference,
6808       *perl_exception,
6809       *reference,
6810       *rv,
6811       *sv;
6812
6813     PERL_UNUSED_VAR(ref);
6814     PERL_UNUSED_VAR(ix);
6815     exception=AcquireExceptionInfo();
6816     perl_exception=newSVpv("",0);
6817     sv=NULL;
6818     if (sv_isobject(ST(0)) == 0)
6819       {
6820         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6821           PackageName);
6822         goto PerlException;
6823       }
6824     reference=SvRV(ST(0));
6825     hv=SvSTASH(reference);
6826     av=newAV();
6827     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6828     SvREFCNT_dec(av);
6829     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6830     if (image == (Image *) NULL)
6831       {
6832         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6833           PackageName);
6834         goto PerlException;
6835       }
6836     compose=image->compose;
6837     method=OptimizeLayer;
6838     for (i=2; i < items; i+=2)
6839     {
6840       attribute=(char *) SvPV(ST(i-1),na);
6841       switch (*attribute)
6842       {
6843         case 'C':
6844         case 'c':
6845         {
6846           if (LocaleCompare(attribute,"compose") == 0)
6847             {
6848               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6849                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6850               if (sp < 0)
6851                 {
6852                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6853                     SvPV(ST(i),na));
6854                   break;
6855                 }
6856               compose=(CompositeOperator) sp;
6857               break;
6858             }
6859           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6860             attribute);
6861           break;
6862         }
6863         case 'M':
6864         case 'm':
6865         {
6866           if (LocaleCompare(attribute,"method") == 0)
6867             {
6868               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6869                 SvPV(ST(i),na));
6870               if (option < 0)
6871                 {
6872                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6873                     SvPV(ST(i),na));
6874                   break;
6875                 }
6876               method=(LayerMethod) option;
6877               break;
6878             }
6879           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6880             attribute);
6881           break;
6882         }
6883         default:
6884         {
6885           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6886             attribute);
6887           break;
6888         }
6889       }
6890     }
6891     layers=(Image *) NULL;
6892     switch (method)
6893     {
6894       case CompareAnyLayer:
6895       case CompareClearLayer:
6896       case CompareOverlayLayer:
6897       default:
6898       {
6899         layers=CompareImagesLayers(image,method,exception);
6900         break;
6901       }
6902       case MergeLayer:
6903       case FlattenLayer:
6904       case MosaicLayer:
6905       {
6906         layers=MergeImageLayers(image,method,exception);
6907         break;
6908       }
6909       case DisposeLayer:
6910       {
6911         layers=DisposeImages(image,exception);
6912         break;
6913       }
6914       case OptimizeImageLayer:
6915       {
6916         layers=OptimizeImageLayers(image,exception);
6917         break;
6918       }
6919       case OptimizePlusLayer:
6920       {
6921         layers=OptimizePlusImageLayers(image,exception);
6922         break;
6923       }
6924       case OptimizeTransLayer:
6925       {
6926         OptimizeImageTransparency(image,exception);
6927         break;
6928       }
6929       case RemoveDupsLayer:
6930       {
6931         RemoveDuplicateLayers(&image,exception);
6932         break;
6933       }
6934       case RemoveZeroLayer:
6935       {
6936         RemoveZeroDelayLayers(&image,exception);
6937         break;
6938       }
6939       case OptimizeLayer:
6940       {
6941         QuantizeInfo
6942           *quantize_info;
6943
6944         /*
6945           General Purpose, GIF Animation Optimizer.
6946         */
6947         layers=CoalesceImages(image,exception);
6948         if (layers == (Image *) NULL)
6949           break;
6950         image=layers;
6951         layers=OptimizeImageLayers(image,exception);
6952         if (layers == (Image *) NULL)
6953           break;
6954         image=DestroyImageList(image);
6955         image=layers;
6956         layers=(Image *) NULL;
6957         OptimizeImageTransparency(image,exception);
6958         quantize_info=AcquireQuantizeInfo(info->image_info);
6959         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6960         quantize_info=DestroyQuantizeInfo(quantize_info);
6961         break;
6962       }
6963       case CompositeLayer:
6964       {
6965         Image
6966           *source;
6967
6968         RectangleInfo
6969           geometry;
6970
6971         /*
6972           Split image sequence at the first 'NULL:' image.
6973         */
6974         source=image;
6975         while (source != (Image *) NULL)
6976         {
6977           source=GetNextImageInList(source);
6978           if ((source != (Image *) NULL) &&
6979               (LocaleCompare(source->magick,"NULL") == 0))
6980             break;
6981         }
6982         if (source != (Image *) NULL)
6983           {
6984             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6985                 (GetNextImageInList(source) == (Image *) NULL))
6986               source=(Image *) NULL;
6987             else
6988               {
6989                 /*
6990                   Separate the two lists, junk the null: image.
6991                 */
6992                 source=SplitImageList(source->previous);
6993                 DeleteImageFromList(&source);
6994               }
6995           }
6996         if (source == (Image *) NULL)
6997           {
6998             (void) ThrowMagickException(exception,GetMagickModule(),
6999               OptionError,"MissingNullSeparator","layers Composite");
7000             break;
7001           }
7002         /*
7003           Adjust offset with gravity and virtual canvas.
7004         */
7005         SetGeometry(image,&geometry);
7006         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7007         geometry.width=source->page.width != 0 ? source->page.width :
7008           source->columns;
7009         geometry.height=source->page.height != 0 ? source->page.height :
7010           source->rows;
7011         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7012           image->columns,image->page.height != 0 ? image->page.height :
7013           image->rows,image->gravity,&geometry);
7014         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7015         source=DestroyImageList(source);
7016         break;
7017       }
7018     }
7019     if (layers != (Image *) NULL)
7020       image=layers;
7021     if (image == (Image *) NULL)
7022       goto PerlException;
7023     for ( ; image; image=image->next)
7024     {
7025       AddImageToRegistry(sv,image);
7026       rv=newRV(sv);
7027       av_push(av,sv_bless(rv,hv));
7028       SvREFCNT_dec(sv);
7029     }
7030     exception=DestroyExceptionInfo(exception);
7031     ST(0)=av_reference;
7032     SvREFCNT_dec(perl_exception);
7033     XSRETURN(1);
7034
7035   PerlException:
7036     InheritPerlException(exception,perl_exception);
7037     exception=DestroyExceptionInfo(exception);
7038     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7039     SvPOK_on(perl_exception);
7040     ST(0)=sv_2mortal(perl_exception);
7041     XSRETURN(1);
7042   }
7043 \f
7044 #
7045 ###############################################################################
7046 #                                                                             #
7047 #                                                                             #
7048 #                                                                             #
7049 #   M a g i c k T o M i m e                                                   #
7050 #                                                                             #
7051 #                                                                             #
7052 #                                                                             #
7053 ###############################################################################
7054 #
7055 #
7056 SV *
7057 MagickToMime(ref,name)
7058   Image::Magick ref=NO_INIT
7059   char *name
7060   ALIAS:
7061     magicktomime = 1
7062   CODE:
7063   {
7064     char
7065       *mime;
7066
7067     PERL_UNUSED_VAR(ref);
7068     PERL_UNUSED_VAR(ix);
7069     mime=MagickToMime(name);
7070     RETVAL=newSVpv(mime,0);
7071     mime=(char *) RelinquishMagickMemory(mime);
7072   }
7073   OUTPUT:
7074     RETVAL
7075 \f
7076 #
7077 ###############################################################################
7078 #                                                                             #
7079 #                                                                             #
7080 #                                                                             #
7081 #   M o g r i f y                                                             #
7082 #                                                                             #
7083 #                                                                             #
7084 #                                                                             #
7085 ###############################################################################
7086 #
7087 #
7088 void
7089 Mogrify(ref,...)
7090   Image::Magick ref=NO_INIT
7091   ALIAS:
7092     Comment            =   1
7093     CommentImage       =   2
7094     Label              =   3
7095     LabelImage         =   4
7096     AddNoise           =   5
7097     AddNoiseImage      =   6
7098     Colorize           =   7
7099     ColorizeImage      =   8
7100     Border             =   9
7101     BorderImage        =  10
7102     Blur               =  11
7103     BlurImage          =  12
7104     Chop               =  13
7105     ChopImage          =  14
7106     Crop               =  15
7107     CropImage          =  16
7108     Despeckle          =  17
7109     DespeckleImage     =  18
7110     Edge               =  19
7111     EdgeImage          =  20
7112     Emboss             =  21
7113     EmbossImage        =  22
7114     Enhance            =  23
7115     EnhanceImage       =  24
7116     Flip               =  25
7117     FlipImage          =  26
7118     Flop               =  27
7119     FlopImage          =  28
7120     Frame              =  29
7121     FrameImage         =  30
7122     Implode            =  31
7123     ImplodeImage       =  32
7124     Magnify            =  33
7125     MagnifyImage       =  34
7126     MedianFilter       =  35
7127     MedianConvolveImage  =  36
7128     Minify             =  37
7129     MinifyImage        =  38
7130     OilPaint           =  39
7131     OilPaintImage      =  40
7132     ReduceNoise        =  41
7133     ReduceNoiseImage   =  42
7134     Roll               =  43
7135     RollImage          =  44
7136     Rotate             =  45
7137     RotateImage        =  46
7138     Sample             =  47
7139     SampleImage        =  48
7140     Scale              =  49
7141     ScaleImage         =  50
7142     Shade              =  51
7143     ShadeImage         =  52
7144     Sharpen            =  53
7145     SharpenImage       =  54
7146     Shear              =  55
7147     ShearImage         =  56
7148     Spread             =  57
7149     SpreadImage        =  58
7150     Swirl              =  59
7151     SwirlImage         =  60
7152     Resize             =  61
7153     ResizeImage        =  62
7154     Zoom               =  63
7155     ZoomImage          =  64
7156     Annotate           =  65
7157     AnnotateImage      =  66
7158     ColorFloodfill     =  67
7159     ColorFloodfillImage=  68
7160     Composite          =  69
7161     CompositeImage     =  70
7162     Contrast           =  71
7163     ContrastImage      =  72
7164     CycleColormap      =  73
7165     CycleColormapImage =  74
7166     Draw               =  75
7167     DrawImage          =  76
7168     Equalize           =  77
7169     EqualizeImage      =  78
7170     Gamma              =  79
7171     GammaImage         =  80
7172     Map                =  81
7173     MapImage           =  82
7174     MatteFloodfill     =  83
7175     MatteFloodfillImage=  84
7176     Modulate           =  85
7177     ModulateImage      =  86
7178     Negate             =  87
7179     NegateImage        =  88
7180     Normalize          =  89
7181     NormalizeImage     =  90
7182     NumberColors       =  91
7183     NumberColorsImage  =  92
7184     Opaque             =  93
7185     OpaqueImage        =  94
7186     Quantize           =  95
7187     QuantizeImage      =  96
7188     Raise              =  97
7189     RaiseImage         =  98
7190     Segment            =  99
7191     SegmentImage       = 100
7192     Signature          = 101
7193     SignatureImage     = 102
7194     Solarize           = 103
7195     SolarizeImage      = 104
7196     Sync               = 105
7197     SyncImage          = 106
7198     Texture            = 107
7199     TextureImage       = 108
7200     Evaluate           = 109
7201     EvaluateImage      = 110
7202     Transparent        = 111
7203     TransparentImage   = 112
7204     Threshold          = 113
7205     ThresholdImage     = 114
7206     Charcoal           = 115
7207     CharcoalImage      = 116
7208     Trim               = 117
7209     TrimImage          = 118
7210     Wave               = 119
7211     WaveImage          = 120
7212     Separate           = 121
7213     SeparateImage      = 122
7214     Stereo             = 125
7215     StereoImage        = 126
7216     Stegano            = 127
7217     SteganoImage       = 128
7218     Deconstruct        = 129
7219     DeconstructImage   = 130
7220     GaussianBlur       = 131
7221     GaussianBlurImage  = 132
7222     Convolve           = 133
7223     ConvolveImage      = 134
7224     Profile            = 135
7225     ProfileImage       = 136
7226     UnsharpMask        = 137
7227     UnsharpMaskImage   = 138
7228     MotionBlur         = 139
7229     MotionBlurImage    = 140
7230     OrderedDither      = 141
7231     OrderedDitherImage = 142
7232     Shave              = 143
7233     ShaveImage         = 144
7234     Level              = 145
7235     LevelImage         = 146
7236     Clip               = 147
7237     ClipImage          = 148
7238     AffineTransform    = 149
7239     AffineTransformImage = 150
7240     Difference         = 151
7241     DifferenceImage    = 152
7242     AdaptiveThreshold  = 153
7243     AdaptiveThresholdImage = 154
7244     Resample           = 155
7245     ResampleImage      = 156
7246     Describe           = 157
7247     DescribeImage      = 158
7248     BlackThreshold     = 159
7249     BlackThresholdImage= 160
7250     WhiteThreshold     = 161
7251     WhiteThresholdImage= 162
7252     RadialBlur         = 163
7253     RadialBlurImage    = 164
7254     Thumbnail          = 165
7255     ThumbnailImage     = 166
7256     Strip              = 167
7257     StripImage         = 168
7258     Tint               = 169
7259     TintImage          = 170
7260     Channel            = 171
7261     ChannelImage       = 172
7262     Splice             = 173
7263     SpliceImage        = 174
7264     Posterize          = 175
7265     PosterizeImage     = 176
7266     Shadow             = 177
7267     ShadowImage        = 178
7268     Identify           = 179
7269     IdentifyImage      = 180
7270     SepiaTone          = 181
7271     SepiaToneImage     = 182
7272     SigmoidalContrast  = 183
7273     SigmoidalContrastImage = 184
7274     Extent             = 185
7275     ExtentImage        = 186
7276     Vignette           = 187
7277     VignetteImage      = 188
7278     ContrastStretch    = 189
7279     ContrastStretchImage = 190
7280     Sans0              = 191
7281     Sans0Image         = 192
7282     Sans1              = 193
7283     Sans1Image         = 194
7284     AdaptiveSharpen    = 195
7285     AdaptiveSharpenImage = 196
7286     Transpose          = 197
7287     TransposeImage     = 198
7288     Transverse         = 199
7289     TransverseImage    = 200
7290     AutoOrient         = 201
7291     AutoOrientImage    = 202
7292     AdaptiveBlur       = 203
7293     AdaptiveBlurImage  = 204
7294     Sketch             = 205
7295     SketchImage        = 206
7296     UniqueColors       = 207
7297     UniqueColorsImage  = 208
7298     AdaptiveResize     = 209
7299     AdaptiveResizeImage= 210
7300     ClipMask           = 211
7301     ClipMaskImage      = 212
7302     LinearStretch      = 213
7303     LinearStretchImage = 214
7304     ColorMatrix        = 215
7305     ColorMatrixImage   = 216
7306     Mask               = 217
7307     MaskImage          = 218
7308     Polaroid           = 219
7309     PolaroidImage      = 220
7310     FloodfillPaint     = 221
7311     FloodfillPaintImage= 222
7312     Distort            = 223
7313     DistortImage       = 224
7314     Clut               = 225
7315     ClutImage          = 226
7316     LiquidRescale      = 227
7317     LiquidRescaleImage = 228
7318     Encipher           = 229
7319     EncipherImage      = 230
7320     Decipher           = 231
7321     DecipherImage      = 232
7322     Deskew             = 233
7323     DeskewImage        = 234
7324     Remap              = 235
7325     RemapImage         = 236
7326     SparseColor        = 237
7327     SparseColorImage   = 238
7328     Function           = 239
7329     FunctionImage      = 240
7330     SelectiveBlur      = 241
7331     SelectiveBlurImage = 242
7332     HaldClut           = 243
7333     HaldClutImage      = 244
7334     BlueShift          = 245
7335     BlueShiftImage     = 246
7336     ForwardFourierTransform  = 247
7337     ForwardFourierTransformImage = 248
7338     InverseFourierTransform = 249
7339     InverseFourierTransformImage = 250
7340     ColorDecisionList  = 251
7341     ColorDecisionListImage = 252
7342     AutoGamma          = 253
7343     AutoGammaImage     = 254
7344     AutoLevel          = 255
7345     AutoLevelImage     = 256
7346     LevelColors        = 257
7347     LevelImageColors   = 258
7348     Clamp              = 259
7349     ClampImage         = 260
7350     BrightnessContrast = 261
7351     BrightnessContrastImage = 262
7352     Morphology         = 263
7353     MorphologyImage    = 264
7354     Color              = 265
7355     ColorImage         = 266
7356     Mode               = 267
7357     ModeImage          = 268
7358     Statistic          = 269
7359     StatisticImage     = 270
7360     Perceptible        = 271
7361     PerceptibleImage   = 272
7362     Poly               = 273
7363     PolyImage          = 274
7364     MogrifyRegion      = 666
7365   PPCODE:
7366   {
7367     AffineMatrix
7368       affine,
7369       current;
7370
7371     char
7372       attribute_flag[MaxArguments],
7373       message[MaxTextExtent];
7374
7375     ChannelType
7376       channel,
7377       channel_mask;
7378
7379     CompositeOperator
7380       compose;
7381
7382     const char
7383       *attribute,
7384       *value;
7385
7386     double
7387       angle;
7388
7389     ExceptionInfo
7390       *exception;
7391
7392     GeometryInfo
7393       geometry_info;
7394
7395     Image
7396       *image,
7397       *next,
7398       *region_image;
7399
7400     MagickBooleanType
7401       status;
7402
7403     MagickStatusType
7404       flags;
7405
7406     PixelInfo
7407       fill_color;
7408
7409     RectangleInfo
7410       geometry,
7411       region_info;
7412
7413     register ssize_t
7414       i;
7415
7416     ssize_t
7417       base,
7418       j,
7419       number_images;
7420
7421     struct Methods
7422       *rp;
7423
7424     struct PackageInfo
7425       *info;
7426
7427     SV
7428       *perl_exception,
7429       **pv,
7430       *reference,
7431       **reference_vector;
7432
7433     struct ArgumentList
7434       argument_list[MaxArguments];
7435
7436     PERL_UNUSED_VAR(ref);
7437     PERL_UNUSED_VAR(ix);
7438     exception=AcquireExceptionInfo();
7439     perl_exception=newSVpv("",0);
7440     reference_vector=NULL;
7441     region_image=NULL;
7442     number_images=0;
7443     base=2;
7444     if (sv_isobject(ST(0)) == 0)
7445       {
7446         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7447           PackageName);
7448         goto PerlException;
7449       }
7450     reference=SvRV(ST(0));
7451     region_info.width=0;
7452     region_info.height=0;
7453     region_info.x=0;
7454     region_info.y=0;
7455     region_image=(Image *) NULL;
7456     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7457     if (ix && (ix != 666))
7458       {
7459         /*
7460           Called as Method(...)
7461         */
7462         ix=(ix+1)/2;
7463         rp=(&Methods[ix-1]);
7464         attribute=rp->name;
7465       }
7466     else
7467       {
7468         /*
7469           Called as Mogrify("Method",...)
7470         */
7471         attribute=(char *) SvPV(ST(1),na);
7472         if (ix)
7473           {
7474             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7475             attribute=(char *) SvPV(ST(2),na);
7476             base++;
7477           }
7478         for (rp=Methods; ; rp++)
7479         {
7480           if (rp >= EndOf(Methods))
7481             {
7482               ThrowPerlException(exception,OptionError,
7483                 "UnrecognizedPerlMagickMethod",attribute);
7484               goto PerlException;
7485             }
7486           if (strEQcase(attribute,rp->name))
7487             break;
7488         }
7489         ix=rp-Methods+1;
7490         base++;
7491       }
7492     if (image == (Image *) NULL)
7493       {
7494         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7495         goto PerlException;
7496       }
7497     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7498     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7499     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7500     {
7501       Arguments
7502         *pp,
7503         *qq;
7504
7505       ssize_t
7506         ssize_test;
7507
7508       struct ArgumentList
7509         *al;
7510
7511       SV
7512         *sv;
7513
7514       sv=NULL;
7515       ssize_test=0;
7516       pp=(Arguments *) NULL;
7517       qq=rp->arguments;
7518       if (i == items)
7519         {
7520           pp=rp->arguments,
7521           sv=ST(i-1);
7522         }
7523       else
7524         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7525         {
7526           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7527             break;
7528           if (strEQcase(attribute,qq->method) > ssize_test)
7529             {
7530               pp=qq;
7531               ssize_test=strEQcase(attribute,qq->method);
7532             }
7533         }
7534       if (pp == (Arguments *) NULL)
7535         {
7536           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7537             attribute);
7538           goto continue_outer_loop;
7539         }
7540       al=(&argument_list[pp-rp->arguments]);
7541       switch (pp->type)
7542       {
7543         case ArrayReference:
7544         {
7545           if (SvTYPE(sv) != SVt_RV)
7546             {
7547               (void) FormatLocaleString(message,MaxTextExtent,
7548                 "invalid %.60s value",pp->method);
7549               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7550               goto continue_outer_loop;
7551             }
7552           al->array_reference=SvRV(sv);
7553           break;
7554         }
7555         case RealReference:
7556         {
7557           al->real_reference=SvNV(sv);
7558           break;
7559         }
7560         case FileReference:
7561         {
7562           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7563           break;
7564         }
7565         case ImageReference:
7566         {
7567           if (!sv_isobject(sv) ||
7568               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7569                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7570             {
7571               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7572                 PackageName);
7573               goto PerlException;
7574             }
7575           break;
7576         }
7577         case IntegerReference:
7578         {
7579           al->integer_reference=SvIV(sv);
7580           break;
7581         }
7582         case StringReference:
7583         {
7584           al->string_reference=(char *) SvPV(sv,al->length);
7585           if (sv_isobject(sv))
7586             al->image_reference=SetupList(aTHX_ SvRV(sv),
7587               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7588           break;
7589         }
7590         default:
7591         {
7592           /*
7593             Is a string; look up name.
7594           */
7595           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7596             {
7597               al->string_reference=(char *) SvPV(sv,al->length);
7598               al->integer_reference=(-1);
7599               break;
7600             }
7601           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7602             MagickFalse,SvPV(sv,na));
7603           if (pp->type == MagickChannelOptions)
7604             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7605           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7606             {
7607               (void) FormatLocaleString(message,MaxTextExtent,
7608                 "invalid %.60s value",pp->method);
7609               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7610               goto continue_outer_loop;
7611             }
7612           break;
7613         }
7614       }
7615       attribute_flag[pp-rp->arguments]++;
7616       continue_outer_loop: ;
7617     }
7618     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7619     pv=reference_vector;
7620     SetGeometryInfo(&geometry_info);
7621     channel=DefaultChannels;
7622     for (next=image; next; next=next->next)
7623     {
7624       image=next;
7625       SetGeometry(image,&geometry);
7626       if ((region_info.width*region_info.height) != 0)
7627         {
7628           region_image=image;
7629           image=CropImage(image,&region_info,exception);
7630         }
7631       switch (ix)
7632       {
7633         default:
7634         {
7635           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7636           ThrowPerlException(exception,OptionError,
7637             "UnrecognizedPerlMagickMethod",message);
7638           goto PerlException;
7639         }
7640         case 1:  /* Comment */
7641         {
7642           if (attribute_flag[0] == 0)
7643             argument_list[0].string_reference=(char *) NULL;
7644           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7645             info ? info->image_info : (ImageInfo *) NULL,image,
7646             argument_list[0].string_reference,exception),exception);
7647           break;
7648         }
7649         case 2:  /* Label */
7650         {
7651           if (attribute_flag[0] == 0)
7652             argument_list[0].string_reference=(char *) NULL;
7653           (void) SetImageProperty(image,"label",InterpretImageProperties(
7654             info ? info->image_info : (ImageInfo *) NULL,image,
7655             argument_list[0].string_reference,exception),exception);
7656           break;
7657         }
7658         case 3:  /* AddNoise */
7659         {
7660           double
7661             attenuate;
7662
7663           if (attribute_flag[0] == 0)
7664             argument_list[0].integer_reference=UniformNoise;
7665           attenuate=1.0;
7666           if (attribute_flag[1] != 0)
7667             attenuate=argument_list[1].real_reference;
7668           if (attribute_flag[2] != 0)
7669             channel=(ChannelType) argument_list[2].integer_reference;
7670           channel_mask=SetImageChannelMask(image,channel);
7671           image=AddNoiseImage(image,(NoiseType)
7672             argument_list[0].integer_reference,attenuate,exception);
7673           if (image != (Image *) NULL)
7674             (void) SetImageChannelMask(image,channel_mask);
7675           break;
7676         }
7677         case 4:  /* Colorize */
7678         {
7679           PixelInfo
7680             target;
7681
7682           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7683             0,0,&target,exception);
7684           if (attribute_flag[0] != 0)
7685             (void) QueryColorCompliance(argument_list[0].string_reference,
7686               AllCompliance,&target,exception);
7687           if (attribute_flag[1] == 0)
7688             argument_list[1].string_reference="100%";
7689           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7690             exception);
7691           break;
7692         }
7693         case 5:  /* Border */
7694         {
7695           CompositeOperator
7696             compose;
7697
7698           geometry.width=0;
7699           geometry.height=0;
7700           if (attribute_flag[0] != 0)
7701             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7702               &geometry,exception);
7703           if (attribute_flag[1] != 0)
7704             geometry.width=argument_list[1].integer_reference;
7705           if (attribute_flag[2] != 0)
7706             geometry.height=argument_list[2].integer_reference;
7707           if (attribute_flag[3] != 0)
7708             QueryColorCompliance(argument_list[3].string_reference,
7709               AllCompliance,&image->border_color,exception);
7710           if (attribute_flag[4] != 0)
7711             QueryColorCompliance(argument_list[4].string_reference,
7712               AllCompliance,&image->border_color,exception);
7713           if (attribute_flag[5] != 0)
7714             QueryColorCompliance(argument_list[5].string_reference,
7715               AllCompliance,&image->border_color,exception);
7716           compose=image->compose;
7717           if (attribute_flag[6] != 0)
7718             compose=(CompositeOperator) argument_list[6].integer_reference;
7719           image=BorderImage(image,&geometry,compose,exception);
7720           break;
7721         }
7722         case 6:  /* Blur */
7723         {
7724           if (attribute_flag[0] != 0)
7725             {
7726               flags=ParseGeometry(argument_list[0].string_reference,
7727                 &geometry_info);
7728               if ((flags & SigmaValue) == 0)
7729                 geometry_info.sigma=1.0;
7730             }
7731           if (attribute_flag[1] != 0)
7732             geometry_info.rho=argument_list[1].real_reference;
7733           if (attribute_flag[2] != 0)
7734             geometry_info.sigma=argument_list[2].real_reference;
7735           if (attribute_flag[3] != 0)
7736             channel=(ChannelType) argument_list[3].integer_reference;
7737           channel_mask=SetImageChannelMask(image,channel);
7738           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7739             exception);
7740           if (image != (Image *) NULL)
7741             (void) SetImageChannelMask(image,channel_mask);
7742           break;
7743         }
7744         case 7:  /* Chop */
7745         {
7746           if (attribute_flag[0] != 0)
7747             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7748               &geometry,exception);
7749           if (attribute_flag[1] != 0)
7750             geometry.width=argument_list[1].integer_reference;
7751           if (attribute_flag[2] != 0)
7752             geometry.height=argument_list[2].integer_reference;
7753           if (attribute_flag[3] != 0)
7754             geometry.x=argument_list[3].integer_reference;
7755           if (attribute_flag[4] != 0)
7756             geometry.y=argument_list[4].integer_reference;
7757           image=ChopImage(image,&geometry,exception);
7758           break;
7759         }
7760         case 8:  /* Crop */
7761         {
7762           if (attribute_flag[6] != 0)
7763             image->gravity=(GravityType) argument_list[6].integer_reference;
7764           if (attribute_flag[0] != 0)
7765             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7766               &geometry,exception);
7767           if (attribute_flag[1] != 0)
7768             geometry.width=argument_list[1].integer_reference;
7769           if (attribute_flag[2] != 0)
7770             geometry.height=argument_list[2].integer_reference;
7771           if (attribute_flag[3] != 0)
7772             geometry.x=argument_list[3].integer_reference;
7773           if (attribute_flag[4] != 0)
7774             geometry.y=argument_list[4].integer_reference;
7775           if (attribute_flag[5] != 0)
7776             image->fuzz=StringToDoubleInterval(
7777               argument_list[5].string_reference,(double) QuantumRange+1.0);
7778           image=CropImage(image,&geometry,exception);
7779           break;
7780         }
7781         case 9:  /* Despeckle */
7782         {
7783           image=DespeckleImage(image,exception);
7784           break;
7785         }
7786         case 10:  /* Edge */
7787         {
7788           if (attribute_flag[0] != 0)
7789             geometry_info.rho=argument_list[0].real_reference;
7790           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7791             exception);
7792           break;
7793         }
7794         case 11:  /* Emboss */
7795         {
7796           if (attribute_flag[0] != 0)
7797             {
7798               flags=ParseGeometry(argument_list[0].string_reference,
7799                 &geometry_info);
7800               if ((flags & SigmaValue) == 0)
7801                 geometry_info.sigma=1.0;
7802             }
7803           if (attribute_flag[1] != 0)
7804             geometry_info.rho=argument_list[1].real_reference;
7805           if (attribute_flag[2] != 0)
7806             geometry_info.sigma=argument_list[2].real_reference;
7807           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7808             exception);
7809           break;
7810         }
7811         case 12:  /* Enhance */
7812         {
7813           image=EnhanceImage(image,exception);
7814           break;
7815         }
7816         case 13:  /* Flip */
7817         {
7818           image=FlipImage(image,exception);
7819           break;
7820         }
7821         case 14:  /* Flop */
7822         {
7823           image=FlopImage(image,exception);
7824           break;
7825         }
7826         case 15:  /* Frame */
7827         {
7828           CompositeOperator
7829             compose;
7830
7831           FrameInfo
7832             frame_info;
7833
7834           if (attribute_flag[0] != 0)
7835             {
7836               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7837                 &geometry,exception);
7838               frame_info.width=geometry.width;
7839               frame_info.height=geometry.height;
7840               frame_info.outer_bevel=geometry.x;
7841               frame_info.inner_bevel=geometry.y;
7842             }
7843           if (attribute_flag[1] != 0)
7844             frame_info.width=argument_list[1].integer_reference;
7845           if (attribute_flag[2] != 0)
7846             frame_info.height=argument_list[2].integer_reference;
7847           if (attribute_flag[3] != 0)
7848             frame_info.inner_bevel=argument_list[3].integer_reference;
7849           if (attribute_flag[4] != 0)
7850             frame_info.outer_bevel=argument_list[4].integer_reference;
7851           if (attribute_flag[5] != 0)
7852             QueryColorCompliance(argument_list[5].string_reference,
7853               AllCompliance,&fill_color,exception);
7854           if (attribute_flag[6] != 0)
7855             QueryColorCompliance(argument_list[6].string_reference,
7856               AllCompliance,&fill_color,exception);
7857           frame_info.x=(ssize_t) frame_info.width;
7858           frame_info.y=(ssize_t) frame_info.height;
7859           frame_info.width=image->columns+2*frame_info.x;
7860           frame_info.height=image->rows+2*frame_info.y;
7861           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7862             image->matte_color=fill_color;
7863           compose=image->compose;
7864           if (attribute_flag[7] != 0)
7865             compose=(CompositeOperator) argument_list[7].integer_reference;
7866           image=FrameImage(image,&frame_info,compose,exception);
7867           break;
7868         }
7869         case 16:  /* Implode */
7870         {
7871           PixelInterpolateMethod
7872             method;
7873
7874           if (attribute_flag[0] == 0)
7875             argument_list[0].real_reference=0.5;
7876           method=UndefinedInterpolatePixel;
7877           if (attribute_flag[1] != 0)
7878             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7879           image=ImplodeImage(image,argument_list[0].real_reference,
7880             method,exception);
7881           break;
7882         }
7883         case 17:  /* Magnify */
7884         {
7885           image=MagnifyImage(image,exception);
7886           break;
7887         }
7888         case 18:  /* MedianFilter */
7889         {
7890           if (attribute_flag[0] != 0)
7891             {
7892               flags=ParseGeometry(argument_list[0].string_reference,
7893                 &geometry_info);
7894               if ((flags & SigmaValue) == 0)
7895                 geometry_info.sigma=geometry_info.rho;
7896             }
7897           if (attribute_flag[1] != 0)
7898             geometry_info.rho=argument_list[1].real_reference;
7899           if (attribute_flag[2] != 0)
7900             geometry_info.sigma=argument_list[2].real_reference;
7901           if (attribute_flag[3] != 0)
7902             channel=(ChannelType) argument_list[3].integer_reference;
7903           channel_mask=SetImageChannelMask(image,channel);
7904           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7905             (size_t) geometry_info.sigma,exception);
7906           if (image != (Image *) NULL)
7907             (void) SetImageChannelMask(image,channel_mask);
7908           break;
7909         }
7910         case 19:  /* Minify */
7911         {
7912           image=MinifyImage(image,exception);
7913           break;
7914         }
7915         case 20:  /* OilPaint */
7916         {
7917           if (attribute_flag[0] == 0)
7918             argument_list[0].real_reference=0.0;
7919           if (attribute_flag[1] == 0)
7920             argument_list[1].real_reference=1.0;
7921           image=OilPaintImage(image,argument_list[0].real_reference,
7922             argument_list[1].real_reference,exception);
7923           break;
7924         }
7925         case 21:  /* ReduceNoise */
7926         {
7927           if (attribute_flag[0] != 0)
7928             {
7929               flags=ParseGeometry(argument_list[0].string_reference,
7930                 &geometry_info);
7931               if ((flags & SigmaValue) == 0)
7932                 geometry_info.sigma=1.0;
7933             }
7934           if (attribute_flag[1] != 0)
7935             geometry_info.rho=argument_list[1].real_reference;
7936           if (attribute_flag[2] != 0)
7937             geometry_info.sigma=argument_list[2].real_reference;
7938           if (attribute_flag[3] != 0)
7939             channel=(ChannelType) argument_list[3].integer_reference;
7940           channel_mask=SetImageChannelMask(image,channel);
7941           image=StatisticImage(image,NonpeakStatistic,(size_t)
7942             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7943           if (image != (Image *) NULL)
7944             (void) SetImageChannelMask(image,channel_mask);
7945           break;
7946         }
7947         case 22:  /* Roll */
7948         {
7949           if (attribute_flag[0] != 0)
7950             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7951               &geometry,exception);
7952           if (attribute_flag[1] != 0)
7953             geometry.x=argument_list[1].integer_reference;
7954           if (attribute_flag[2] != 0)
7955             geometry.y=argument_list[2].integer_reference;
7956           image=RollImage(image,geometry.x,geometry.y,exception);
7957           break;
7958         }
7959         case 23:  /* Rotate */
7960         {
7961           if (attribute_flag[0] == 0)
7962             argument_list[0].real_reference=90.0;
7963           if (attribute_flag[1] != 0)
7964             {
7965               QueryColorCompliance(argument_list[1].string_reference,
7966                 AllCompliance,&image->background_color,exception);
7967               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
7968                   (image->alpha_trait != BlendPixelTrait))
7969                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
7970             }
7971           image=RotateImage(image,argument_list[0].real_reference,exception);
7972           break;
7973         }
7974         case 24:  /* Sample */
7975         {
7976           if (attribute_flag[0] != 0)
7977             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7978               &geometry,exception);
7979           if (attribute_flag[1] != 0)
7980             geometry.width=argument_list[1].integer_reference;
7981           if (attribute_flag[2] != 0)
7982             geometry.height=argument_list[2].integer_reference;
7983           image=SampleImage(image,geometry.width,geometry.height,exception);
7984           break;
7985         }
7986         case 25:  /* Scale */
7987         {
7988           if (attribute_flag[0] != 0)
7989             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7990               &geometry,exception);
7991           if (attribute_flag[1] != 0)
7992             geometry.width=argument_list[1].integer_reference;
7993           if (attribute_flag[2] != 0)
7994             geometry.height=argument_list[2].integer_reference;
7995           image=ScaleImage(image,geometry.width,geometry.height,exception);
7996           break;
7997         }
7998         case 26:  /* Shade */
7999         {
8000           if (attribute_flag[0] != 0)
8001             {
8002               flags=ParseGeometry(argument_list[0].string_reference,
8003                 &geometry_info);
8004               if ((flags & SigmaValue) == 0)
8005                 geometry_info.sigma=0.0;
8006             }
8007           if (attribute_flag[1] != 0)
8008             geometry_info.rho=argument_list[1].real_reference;
8009           if (attribute_flag[2] != 0)
8010             geometry_info.sigma=argument_list[2].real_reference;
8011           image=ShadeImage(image,
8012             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8013             geometry_info.rho,geometry_info.sigma,exception);
8014           break;
8015         }
8016         case 27:  /* Sharpen */
8017         {
8018           if (attribute_flag[0] != 0)
8019             {
8020               flags=ParseGeometry(argument_list[0].string_reference,
8021                 &geometry_info);
8022               if ((flags & SigmaValue) == 0)
8023                 geometry_info.sigma=1.0;
8024             }
8025           if (attribute_flag[1] != 0)
8026             geometry_info.rho=argument_list[1].real_reference;
8027           if (attribute_flag[2] != 0)
8028             geometry_info.sigma=argument_list[2].real_reference;
8029           if (attribute_flag[3] != 0)
8030             channel=(ChannelType) argument_list[3].integer_reference;
8031           channel_mask=SetImageChannelMask(image,channel);
8032           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8033             exception);
8034           if (image != (Image *) NULL)
8035             (void) SetImageChannelMask(image,channel_mask);
8036           break;
8037         }
8038         case 28:  /* Shear */
8039         {
8040           if (attribute_flag[0] != 0)
8041             {
8042               flags=ParseGeometry(argument_list[0].string_reference,
8043                 &geometry_info);
8044               if ((flags & SigmaValue) == 0)
8045                 geometry_info.sigma=geometry_info.rho;
8046             }
8047           if (attribute_flag[1] != 0)
8048             geometry_info.rho=argument_list[1].real_reference;
8049           if (attribute_flag[2] != 0)
8050             geometry_info.sigma=argument_list[2].real_reference;
8051           if (attribute_flag[3] != 0)
8052             QueryColorCompliance(argument_list[3].string_reference,
8053               AllCompliance,&image->background_color,exception);
8054           if (attribute_flag[4] != 0)
8055             QueryColorCompliance(argument_list[4].string_reference,
8056               AllCompliance,&image->background_color,exception);
8057           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8058             exception);
8059           break;
8060         }
8061         case 29:  /* Spread */
8062         {
8063           PixelInterpolateMethod
8064             method;
8065
8066           if (attribute_flag[0] == 0)
8067             argument_list[0].real_reference=1.0;
8068           method=UndefinedInterpolatePixel;
8069           if (attribute_flag[1] != 0)
8070             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8071           image=SpreadImage(image,argument_list[0].real_reference,method,
8072             exception);
8073           break;
8074         }
8075         case 30:  /* Swirl */
8076         {
8077           PixelInterpolateMethod
8078             method;
8079
8080           if (attribute_flag[0] == 0)
8081             argument_list[0].real_reference=50.0;
8082           method=UndefinedInterpolatePixel;
8083           if (attribute_flag[1] != 0)
8084             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8085           image=SwirlImage(image,argument_list[0].real_reference,
8086             method,exception);
8087           break;
8088         }
8089         case 31:  /* Resize */
8090         case 32:  /* Zoom */
8091         {
8092           if (attribute_flag[0] != 0)
8093             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8094               &geometry,exception);
8095           if (attribute_flag[1] != 0)
8096             geometry.width=argument_list[1].integer_reference;
8097           if (attribute_flag[2] != 0)
8098             geometry.height=argument_list[2].integer_reference;
8099           if (attribute_flag[3] == 0)
8100             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8101           if (attribute_flag[4] != 0)
8102             SetImageArtifact(image,"filter:support",
8103               argument_list[4].string_reference);
8104           image=ResizeImage(image,geometry.width,geometry.height,
8105             (FilterTypes) argument_list[3].integer_reference,
8106             exception);
8107           break;
8108         }
8109         case 33:  /* Annotate */
8110         {
8111           DrawInfo
8112             *draw_info;
8113
8114           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8115             (DrawInfo *) NULL);
8116           if (attribute_flag[0] != 0)
8117             {
8118               char
8119                 *text;
8120
8121               text=InterpretImageProperties(info ? info->image_info :
8122                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8123                 exception);
8124               (void) CloneString(&draw_info->text,text);
8125               text=DestroyString(text);
8126             }
8127           if (attribute_flag[1] != 0)
8128             (void) CloneString(&draw_info->font,
8129               argument_list[1].string_reference);
8130           if (attribute_flag[2] != 0)
8131             draw_info->pointsize=argument_list[2].real_reference;
8132           if (attribute_flag[3] != 0)
8133             (void) CloneString(&draw_info->density,
8134               argument_list[3].string_reference);
8135           if (attribute_flag[4] != 0)
8136             (void) QueryColorCompliance(argument_list[4].string_reference,
8137               AllCompliance,&draw_info->undercolor,exception);
8138           if (attribute_flag[5] != 0)
8139             {
8140               (void) QueryColorCompliance(argument_list[5].string_reference,
8141                 AllCompliance,&draw_info->stroke,exception);
8142               if (argument_list[5].image_reference != (Image *) NULL)
8143                 draw_info->stroke_pattern=CloneImage(
8144                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8145             }
8146           if (attribute_flag[6] != 0)
8147             {
8148               (void) QueryColorCompliance(argument_list[6].string_reference,
8149                 AllCompliance,&draw_info->fill,exception);
8150               if (argument_list[6].image_reference != (Image *) NULL)
8151                 draw_info->fill_pattern=CloneImage(
8152                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8153             }
8154           if (attribute_flag[7] != 0)
8155             {
8156               (void) CloneString(&draw_info->geometry,
8157                 argument_list[7].string_reference);
8158               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8159                 &geometry,exception);
8160               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8161                 geometry_info.sigma=geometry_info.xi;
8162             }
8163           if (attribute_flag[8] != 0)
8164             (void) QueryColorCompliance(argument_list[8].string_reference,
8165               AllCompliance,&draw_info->fill,exception);
8166           if (attribute_flag[11] != 0)
8167             draw_info->gravity=(GravityType)
8168               argument_list[11].integer_reference;
8169           if (attribute_flag[25] != 0)
8170             {
8171               AV
8172                 *av;
8173
8174               av=(AV *) argument_list[25].array_reference;
8175               if ((av_len(av) != 3) && (av_len(av) != 5))
8176                 {
8177                   ThrowPerlException(exception,OptionError,
8178                     "affine matrix must have 4 or 6 elements",PackageName);
8179                   goto PerlException;
8180                 }
8181               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8182               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8183               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8184               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8185               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8186                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8187                 {
8188                   ThrowPerlException(exception,OptionError,
8189                     "affine matrix is singular",PackageName);
8190                    goto PerlException;
8191                 }
8192               if (av_len(av) == 5)
8193                 {
8194                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8195                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8196                 }
8197             }
8198           for (j=12; j < 17; j++)
8199           {
8200             if (attribute_flag[j] == 0)
8201               continue;
8202             value=argument_list[j].string_reference;
8203             angle=argument_list[j].real_reference;
8204             current=draw_info->affine;
8205             GetAffineMatrix(&affine);
8206             switch (j)
8207             {
8208               case 12:
8209               {
8210                 /*
8211                   Translate.
8212                 */
8213                 flags=ParseGeometry(value,&geometry_info);
8214                 affine.tx=geometry_info.xi;
8215                 affine.ty=geometry_info.psi;
8216                 if ((flags & PsiValue) == 0)
8217                   affine.ty=affine.tx;
8218                 break;
8219               }
8220               case 13:
8221               {
8222                 /*
8223                   Scale.
8224                 */
8225                 flags=ParseGeometry(value,&geometry_info);
8226                 affine.sx=geometry_info.rho;
8227                 affine.sy=geometry_info.sigma;
8228                 if ((flags & SigmaValue) == 0)
8229                   affine.sy=affine.sx;
8230                 break;
8231               }
8232               case 14:
8233               {
8234                 /*
8235                   Rotate.
8236                 */
8237                 if (angle == 0.0)
8238                   break;
8239                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8240                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8241                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8242                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8243                 break;
8244               }
8245               case 15:
8246               {
8247                 /*
8248                   SkewX.
8249                 */
8250                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8251                 break;
8252               }
8253               case 16:
8254               {
8255                 /*
8256                   SkewY.
8257                 */
8258                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8259                 break;
8260               }
8261             }
8262             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8263             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8264             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8265             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8266             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8267               current.tx;
8268             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8269               current.ty;
8270           }
8271           if (attribute_flag[9] == 0)
8272             argument_list[9].real_reference=0.0;
8273           if (attribute_flag[10] == 0)
8274             argument_list[10].real_reference=0.0;
8275           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8276             {
8277               char
8278                 geometry[MaxTextExtent];
8279
8280               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8281                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8282                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8283               (void) CloneString(&draw_info->geometry,geometry);
8284             }
8285           if (attribute_flag[17] != 0)
8286             draw_info->stroke_width=argument_list[17].real_reference;
8287           if (attribute_flag[18] != 0)
8288             {
8289               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8290                 MagickTrue : MagickFalse;
8291               draw_info->stroke_antialias=draw_info->text_antialias;
8292             }
8293           if (attribute_flag[19] != 0)
8294             (void) CloneString(&draw_info->family,
8295               argument_list[19].string_reference);
8296           if (attribute_flag[20] != 0)
8297             draw_info->style=(StyleType) argument_list[20].integer_reference;
8298           if (attribute_flag[21] != 0)
8299             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8300           if (attribute_flag[22] != 0)
8301             draw_info->weight=argument_list[22].integer_reference;
8302           if (attribute_flag[23] != 0)
8303             draw_info->align=(AlignType) argument_list[23].integer_reference;
8304           if (attribute_flag[24] != 0)
8305             (void) CloneString(&draw_info->encoding,
8306               argument_list[24].string_reference);
8307           if (attribute_flag[25] != 0)
8308             draw_info->fill_pattern=CloneImage(
8309               argument_list[25].image_reference,0,0,MagickTrue,exception);
8310           if (attribute_flag[26] != 0)
8311             draw_info->fill_pattern=CloneImage(
8312               argument_list[26].image_reference,0,0,MagickTrue,exception);
8313           if (attribute_flag[27] != 0)
8314             draw_info->stroke_pattern=CloneImage(
8315               argument_list[27].image_reference,0,0,MagickTrue,exception);
8316           if (attribute_flag[29] != 0)
8317             draw_info->kerning=argument_list[29].real_reference;
8318           if (attribute_flag[30] != 0)
8319             draw_info->interline_spacing=argument_list[30].real_reference;
8320           if (attribute_flag[31] != 0)
8321             draw_info->interword_spacing=argument_list[31].real_reference;
8322           if (attribute_flag[32] != 0)
8323             draw_info->direction=(DirectionType)
8324               argument_list[32].integer_reference;
8325           (void) AnnotateImage(image,draw_info,exception);
8326           draw_info=DestroyDrawInfo(draw_info);
8327           break;
8328         }
8329         case 34:  /* ColorFloodfill */
8330         {
8331           DrawInfo
8332             *draw_info;
8333
8334           MagickBooleanType
8335             invert;
8336
8337           PixelInfo
8338             target;
8339
8340           draw_info=CloneDrawInfo(info ? info->image_info :
8341             (ImageInfo *) NULL,(DrawInfo *) NULL);
8342           if (attribute_flag[0] != 0)
8343             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8344               &geometry,exception);
8345           if (attribute_flag[1] != 0)
8346             geometry.x=argument_list[1].integer_reference;
8347           if (attribute_flag[2] != 0)
8348             geometry.y=argument_list[2].integer_reference;
8349           if (attribute_flag[3] != 0)
8350             (void) QueryColorCompliance(argument_list[3].string_reference,
8351               AllCompliance,&draw_info->fill,exception);
8352           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8353             geometry.x,geometry.y,&target,exception);
8354           invert=MagickFalse;
8355           if (attribute_flag[4] != 0)
8356             {
8357               QueryColorCompliance(argument_list[4].string_reference,
8358                 AllCompliance,&target,exception);
8359               invert=MagickTrue;
8360             }
8361           if (attribute_flag[5] != 0)
8362             image->fuzz=StringToDoubleInterval(
8363               argument_list[5].string_reference,(double) QuantumRange+1.0);
8364           if (attribute_flag[6] != 0)
8365             invert=(MagickBooleanType) argument_list[6].integer_reference;
8366           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8367             geometry.y,invert,exception);
8368           draw_info=DestroyDrawInfo(draw_info);
8369           break;
8370         }
8371         case 35:  /* Composite */
8372         {
8373           char
8374             composite_geometry[MaxTextExtent];
8375
8376           Image
8377             *composite_image,
8378             *rotate_image;
8379
8380           MagickBooleanType
8381             clip_to_self;
8382
8383           compose=OverCompositeOp;
8384           if (attribute_flag[0] != 0)
8385             composite_image=argument_list[0].image_reference;
8386           else
8387             {
8388               ThrowPerlException(exception,OptionError,
8389                 "CompositeImageRequired",PackageName);
8390               goto PerlException;
8391             }
8392           /*
8393             Parameter Handling used for BOTH normal and tiled composition.
8394           */
8395           if (attribute_flag[1] != 0) /* compose */
8396             compose=(CompositeOperator) argument_list[1].integer_reference;
8397           if (attribute_flag[6] != 0) /* opacity  */
8398             {
8399               if (compose != DissolveCompositeOp)
8400                 (void) SetImageAlpha(composite_image,(Quantum)
8401                   StringToDoubleInterval(argument_list[6].string_reference,
8402                   (double) QuantumRange+1.0),exception);
8403               else
8404                 {
8405                   CacheView
8406                     *composite_view;
8407
8408                   double
8409                     opacity;
8410
8411                   MagickBooleanType
8412                     sync;
8413
8414                   register ssize_t
8415                     x;
8416
8417                   register Quantum
8418                     *q;
8419
8420                   ssize_t
8421                     y;
8422
8423                   /*
8424                     Handle dissolve composite operator (patch by
8425                     Kevin A. McGrail).
8426                   */
8427                   (void) CloneString(&image->geometry,
8428                     argument_list[6].string_reference);
8429                   opacity=(Quantum) StringToDoubleInterval(
8430                     argument_list[6].string_reference,(double) QuantumRange+
8431                     1.0);
8432                   if (composite_image->alpha_trait == BlendPixelTrait)
8433                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8434                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8435                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8436                   {
8437                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8438                       composite_image->columns,1,exception);
8439                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8440                     {
8441                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8442                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8443                           q);
8444                       q+=GetPixelChannels(composite_image);
8445                     }
8446                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8447                     if (sync == MagickFalse)
8448                       break;
8449                   }
8450                   composite_view=DestroyCacheView(composite_view);
8451                 }
8452             }
8453           if (attribute_flag[9] != 0)    /* "color=>" */
8454             QueryColorCompliance(argument_list[9].string_reference,
8455               AllCompliance,&composite_image->background_color,exception);
8456           if (attribute_flag[12] != 0) /* "interpolate=>" */
8457             image->interpolate=(PixelInterpolateMethod)
8458               argument_list[12].integer_reference;
8459           if (attribute_flag[13] != 0)   /* "args=>" */
8460             (void) SetImageArtifact(composite_image,"compose:args",
8461               argument_list[13].string_reference);
8462           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8463             (void) SetImageArtifact(composite_image,"compose:args",
8464               argument_list[14].string_reference);
8465           clip_to_self=MagickTrue;
8466           if (attribute_flag[15] != 0)
8467             clip_to_self=(MagickBooleanType)
8468               argument_list[15].integer_reference;
8469           /*
8470             Tiling Composition (with orthogonal rotate).
8471           */
8472           rotate_image=(Image *) NULL;
8473           if (attribute_flag[8] != 0)   /* "rotate=>" */
8474             {
8475                /*
8476                  Rotate image.
8477                */
8478                rotate_image=RotateImage(composite_image,
8479                  argument_list[8].real_reference,exception);
8480                if (rotate_image == (Image *) NULL)
8481                  break;
8482             }
8483           if ((attribute_flag[7] != 0) &&
8484               (argument_list[7].integer_reference != 0)) /* tile */
8485             {
8486               ssize_t
8487                 x,
8488                 y;
8489
8490               /*
8491                 Tile the composite image.
8492               */
8493              if (attribute_flag[8] != 0)   /* "tile=>" */
8494                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8495                  "false");
8496              else
8497                (void) SetImageArtifact(composite_image,
8498                  "compose:outside-overlay","false");
8499              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8500                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8501                 {
8502                   if (attribute_flag[8] != 0) /* rotate */
8503                     (void) CompositeImage(image,rotate_image,compose,
8504                       MagickTrue,x,y,exception);
8505                   else
8506                     (void) CompositeImage(image,composite_image,compose,
8507                       MagickTrue,x,y,exception);
8508                 }
8509               if (attribute_flag[8] != 0) /* rotate */
8510                 rotate_image=DestroyImage(rotate_image);
8511               break;
8512             }
8513           /*
8514             Parameter Handling used used ONLY for normal composition.
8515           */
8516           if (attribute_flag[5] != 0) /* gravity */
8517             image->gravity=(GravityType) argument_list[5].integer_reference;
8518           if (attribute_flag[2] != 0) /* geometry offset */
8519             {
8520               SetGeometry(image,&geometry);
8521               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8522                 &geometry);
8523               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8524                 &geometry);
8525             }
8526           if (attribute_flag[3] != 0) /* x offset */
8527             geometry.x=argument_list[3].integer_reference;
8528           if (attribute_flag[4] != 0) /* y offset */
8529             geometry.y=argument_list[4].integer_reference;
8530           if (attribute_flag[10] != 0) /* mask */
8531             {
8532               if ((image->compose == DisplaceCompositeOp) ||
8533                   (image->compose == DistortCompositeOp))
8534                 {
8535                   /*
8536                     Merge Y displacement into X displacement image.
8537                   */
8538                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8539                     exception);
8540                   (void) CompositeImage(composite_image,
8541                     argument_list[10].image_reference,CopyGreenCompositeOp,
8542                     MagickTrue,0,0,exception);
8543                 }
8544               else
8545                 {
8546                   Image
8547                     *mask_image;
8548
8549                   /*
8550                     Set a blending mask for the composition.
8551                   */
8552                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8553                     MagickTrue,exception);
8554                   (void) NegateImage(mask_image,MagickFalse,exception);
8555                   (void) SetImageMask(composite_image,mask_image,exception);
8556                   mask_image=DestroyImage(mask_image);
8557                 }
8558             }
8559           if (attribute_flag[11] != 0) /* channel */
8560             channel=(ChannelType) argument_list[11].integer_reference;
8561           /*
8562             Composite two images (normal composition).
8563           */
8564           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8565             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8566             (double) composite_image->rows,(double) geometry.x,(double)
8567             geometry.y);
8568           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8569             exception);
8570           channel_mask=SetImageChannelMask(image,channel);
8571           if (attribute_flag[8] == 0) /* no rotate */
8572             CompositeImage(image,composite_image,compose,clip_to_self,
8573               geometry.x,geometry.y,exception);
8574           else
8575             {
8576               /*
8577                 Position adjust rotated image then composite.
8578               */
8579               geometry.x-=(ssize_t) (rotate_image->columns-
8580                 composite_image->columns)/2;
8581               geometry.y-=(ssize_t) (rotate_image->rows-
8582                 composite_image->rows)/2;
8583               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8584                 geometry.y,exception);
8585               rotate_image=DestroyImage(rotate_image);
8586             }
8587           if (attribute_flag[10] != 0) /* mask */
8588             {
8589               if ((image->compose == DisplaceCompositeOp) ||
8590                   (image->compose == DistortCompositeOp))
8591                 composite_image=DestroyImage(composite_image);
8592               else
8593                 (void) SetImageMask(image,(Image *) NULL,exception);
8594             }
8595           (void) SetImageChannelMask(image,channel_mask);
8596           break;
8597         }
8598         case 36:  /* Contrast */
8599         {
8600           if (attribute_flag[0] == 0)
8601             argument_list[0].integer_reference=0;
8602           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8603             MagickTrue : MagickFalse,exception);
8604           break;
8605         }
8606         case 37:  /* CycleColormap */
8607         {
8608           if (attribute_flag[0] == 0)
8609             argument_list[0].integer_reference=6;
8610           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8611             exception);
8612           break;
8613         }
8614         case 38:  /* Draw */
8615         {
8616           DrawInfo
8617             *draw_info;
8618
8619           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8620             (DrawInfo *) NULL);
8621           (void) CloneString(&draw_info->primitive,"point");
8622           if (attribute_flag[0] != 0)
8623             {
8624               if (argument_list[0].integer_reference < 0)
8625                 (void) CloneString(&draw_info->primitive,
8626                   argument_list[0].string_reference);
8627               else
8628                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8629                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8630             }
8631           if (attribute_flag[1] != 0)
8632             {
8633               if (LocaleCompare(draw_info->primitive,"path") == 0)
8634                 {
8635                   (void) ConcatenateString(&draw_info->primitive," '");
8636                   ConcatenateString(&draw_info->primitive,
8637                     argument_list[1].string_reference);
8638                   (void) ConcatenateString(&draw_info->primitive,"'");
8639                 }
8640               else
8641                 {
8642                   (void) ConcatenateString(&draw_info->primitive," ");
8643                   ConcatenateString(&draw_info->primitive,
8644                     argument_list[1].string_reference);
8645                 }
8646             }
8647           if (attribute_flag[2] != 0)
8648             {
8649               (void) ConcatenateString(&draw_info->primitive," ");
8650               (void) ConcatenateString(&draw_info->primitive,
8651                 CommandOptionToMnemonic(MagickMethodOptions,
8652                 argument_list[2].integer_reference));
8653             }
8654           if (attribute_flag[3] != 0)
8655             {
8656               (void) QueryColorCompliance(argument_list[3].string_reference,
8657                 AllCompliance,&draw_info->stroke,exception);
8658               if (argument_list[3].image_reference != (Image *) NULL)
8659                 draw_info->stroke_pattern=CloneImage(
8660                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8661             }
8662           if (attribute_flag[4] != 0)
8663             {
8664               (void) QueryColorCompliance(argument_list[4].string_reference,
8665                 AllCompliance,&draw_info->fill,exception);
8666               if (argument_list[4].image_reference != (Image *) NULL)
8667                 draw_info->fill_pattern=CloneImage(
8668                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8669             }
8670           if (attribute_flag[5] != 0)
8671             draw_info->stroke_width=argument_list[5].real_reference;
8672           if (attribute_flag[6] != 0)
8673             (void) CloneString(&draw_info->font,
8674               argument_list[6].string_reference);
8675           if (attribute_flag[7] != 0)
8676             (void) QueryColorCompliance(argument_list[7].string_reference,
8677               AllCompliance,&draw_info->border_color,exception);
8678           if (attribute_flag[8] != 0)
8679             draw_info->affine.tx=argument_list[8].real_reference;
8680           if (attribute_flag[9] != 0)
8681             draw_info->affine.ty=argument_list[9].real_reference;
8682           if (attribute_flag[20] != 0)
8683             {
8684               AV
8685                 *av;
8686
8687               av=(AV *) argument_list[20].array_reference;
8688               if ((av_len(av) != 3) && (av_len(av) != 5))
8689                 {
8690                   ThrowPerlException(exception,OptionError,
8691                     "affine matrix must have 4 or 6 elements",PackageName);
8692                   goto PerlException;
8693                 }
8694               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8695               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8696               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8697               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8698               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8699                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8700                 {
8701                   ThrowPerlException(exception,OptionError,
8702                     "affine matrix is singular",PackageName);
8703                    goto PerlException;
8704                 }
8705               if (av_len(av) == 5)
8706                 {
8707                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8708                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8709                 }
8710             }
8711           for (j=10; j < 15; j++)
8712           {
8713             if (attribute_flag[j] == 0)
8714               continue;
8715             value=argument_list[j].string_reference;
8716             angle=argument_list[j].real_reference;
8717             current=draw_info->affine;
8718             GetAffineMatrix(&affine);
8719             switch (j)
8720             {
8721               case 10:
8722               {
8723                 /*
8724                   Translate.
8725                 */
8726                 flags=ParseGeometry(value,&geometry_info);
8727                 affine.tx=geometry_info.xi;
8728                 affine.ty=geometry_info.psi;
8729                 if ((flags & PsiValue) == 0)
8730                   affine.ty=affine.tx;
8731                 break;
8732               }
8733               case 11:
8734               {
8735                 /*
8736                   Scale.
8737                 */
8738                 flags=ParseGeometry(value,&geometry_info);
8739                 affine.sx=geometry_info.rho;
8740                 affine.sy=geometry_info.sigma;
8741                 if ((flags & SigmaValue) == 0)
8742                   affine.sy=affine.sx;
8743                 break;
8744               }
8745               case 12:
8746               {
8747                 /*
8748                   Rotate.
8749                 */
8750                 if (angle == 0.0)
8751                   break;
8752                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8753                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8754                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8755                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8756                 break;
8757               }
8758               case 13:
8759               {
8760                 /*
8761                   SkewX.
8762                 */
8763                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8764                 break;
8765               }
8766               case 14:
8767               {
8768                 /*
8769                   SkewY.
8770                 */
8771                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8772                 break;
8773               }
8774             }
8775             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8776             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8777             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8778             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8779             draw_info->affine.tx=
8780               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8781             draw_info->affine.ty=
8782               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8783           }
8784           if (attribute_flag[15] != 0)
8785             draw_info->fill_pattern=CloneImage(
8786               argument_list[15].image_reference,0,0,MagickTrue,exception);
8787           if (attribute_flag[16] != 0)
8788             draw_info->pointsize=argument_list[16].real_reference;
8789           if (attribute_flag[17] != 0)
8790             {
8791               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8792                 ? MagickTrue : MagickFalse;
8793               draw_info->text_antialias=draw_info->stroke_antialias;
8794             }
8795           if (attribute_flag[18] != 0)
8796             (void) CloneString(&draw_info->density,
8797               argument_list[18].string_reference);
8798           if (attribute_flag[19] != 0)
8799             draw_info->stroke_width=argument_list[19].real_reference;
8800           if (attribute_flag[21] != 0)
8801             draw_info->dash_offset=argument_list[21].real_reference;
8802           if (attribute_flag[22] != 0)
8803             {
8804               AV
8805                 *av;
8806
8807               av=(AV *) argument_list[22].array_reference;
8808               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8809                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8810               if (draw_info->dash_pattern != (double *) NULL)
8811                 {
8812                   for (i=0; i <= av_len(av); i++)
8813                     draw_info->dash_pattern[i]=(double)
8814                       SvNV(*(av_fetch(av,i,0)));
8815                   draw_info->dash_pattern[i]=0.0;
8816                 }
8817             }
8818           if (attribute_flag[23] != 0)
8819             image->interpolate=(PixelInterpolateMethod)
8820               argument_list[23].integer_reference;
8821           if ((attribute_flag[24] != 0) &&
8822               (draw_info->fill_pattern != (Image *) NULL))
8823             flags=ParsePageGeometry(draw_info->fill_pattern,
8824               argument_list[24].string_reference,
8825               &draw_info->fill_pattern->tile_offset,exception);
8826           if (attribute_flag[25] != 0)
8827             {
8828               (void) ConcatenateString(&draw_info->primitive," '");
8829               (void) ConcatenateString(&draw_info->primitive,
8830                 argument_list[25].string_reference);
8831               (void) ConcatenateString(&draw_info->primitive,"'");
8832             }
8833           if (attribute_flag[26] != 0)
8834             draw_info->fill_pattern=CloneImage(
8835               argument_list[26].image_reference,0,0,MagickTrue,exception);
8836           if (attribute_flag[27] != 0)
8837             draw_info->stroke_pattern=CloneImage(
8838               argument_list[27].image_reference,0,0,MagickTrue,exception);
8839           if (attribute_flag[28] != 0)
8840             (void) CloneString(&draw_info->primitive,
8841               argument_list[28].string_reference);
8842           if (attribute_flag[29] != 0)
8843             draw_info->kerning=argument_list[29].real_reference;
8844           if (attribute_flag[30] != 0)
8845             draw_info->interline_spacing=argument_list[30].real_reference;
8846           if (attribute_flag[31] != 0)
8847             draw_info->interword_spacing=argument_list[31].real_reference;
8848           if (attribute_flag[32] != 0)
8849             draw_info->direction=(DirectionType)
8850               argument_list[32].integer_reference;
8851           DrawImage(image,draw_info,exception);
8852           draw_info=DestroyDrawInfo(draw_info);
8853           break;
8854         }
8855         case 39:  /* Equalize */
8856         {
8857           if (attribute_flag[0] != 0)
8858             channel=(ChannelType) argument_list[0].integer_reference;
8859           channel_mask=SetImageChannelMask(image,channel);
8860           EqualizeImage(image,exception);
8861           (void) SetImageChannelMask(image,channel_mask);
8862           break;
8863         }
8864         case 40:  /* Gamma */
8865         {
8866           if (attribute_flag[1] != 0)
8867             channel=(ChannelType) argument_list[1].integer_reference;
8868           if (attribute_flag[2] == 0)
8869             argument_list[2].real_reference=1.0;
8870           if (attribute_flag[3] == 0)
8871             argument_list[3].real_reference=1.0;
8872           if (attribute_flag[4] == 0)
8873             argument_list[4].real_reference=1.0;
8874           if (attribute_flag[0] == 0)
8875             {
8876               (void) FormatLocaleString(message,MaxTextExtent,
8877                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8878                 (double) argument_list[3].real_reference,
8879                 (double) argument_list[4].real_reference);
8880               argument_list[0].string_reference=message;
8881             }
8882           (void) GammaImage(image,StringToDouble(
8883             argument_list[0].string_reference,(char **) NULL),exception);
8884           break;
8885         }
8886         case 41:  /* Map */
8887         {
8888           QuantizeInfo
8889             *quantize_info;
8890
8891           if (attribute_flag[0] == 0)
8892             {
8893               ThrowPerlException(exception,OptionError,"MapImageRequired",
8894                 PackageName);
8895               goto PerlException;
8896             }
8897           quantize_info=AcquireQuantizeInfo(info->image_info);
8898           if (attribute_flag[1] != 0)
8899             quantize_info->dither_method=(DitherMethod)
8900               argument_list[1].integer_reference;
8901           (void) RemapImages(quantize_info,image,
8902             argument_list[0].image_reference,exception);
8903           quantize_info=DestroyQuantizeInfo(quantize_info);
8904           break;
8905         }
8906         case 42:  /* MatteFloodfill */
8907         {
8908           DrawInfo
8909             *draw_info;
8910
8911           MagickBooleanType
8912             invert;
8913
8914           PixelInfo
8915             target;
8916
8917           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8918             (DrawInfo *) NULL);
8919           if (attribute_flag[0] != 0)
8920             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8921               &geometry,exception);
8922           if (attribute_flag[1] != 0)
8923             geometry.x=argument_list[1].integer_reference;
8924           if (attribute_flag[2] != 0)
8925             geometry.y=argument_list[2].integer_reference;
8926           if (image->alpha_trait != BlendPixelTrait)
8927             (void) SetImageAlpha(image,OpaqueAlpha,exception);
8928           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8929             geometry.x,geometry.y,&target,exception);
8930           if (attribute_flag[4] != 0)
8931             QueryColorCompliance(argument_list[4].string_reference,
8932               AllCompliance,&target,exception);
8933           if (attribute_flag[3] != 0)
8934             target.alpha=StringToDoubleInterval(
8935               argument_list[3].string_reference,(double) (double) QuantumRange+
8936               1.0);
8937           if (attribute_flag[5] != 0)
8938             image->fuzz=StringToDoubleInterval(
8939               argument_list[5].string_reference,(double) QuantumRange+1.0);
8940           invert=MagickFalse;
8941           if (attribute_flag[6] != 0)
8942             invert=(MagickBooleanType) argument_list[6].integer_reference;
8943           channel_mask=SetImageChannelMask(image,AlphaChannel);
8944           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8945             geometry.y,invert,exception);
8946           (void) SetImageChannelMask(image,channel_mask);
8947           draw_info=DestroyDrawInfo(draw_info);
8948           break;
8949         }
8950         case 43:  /* Modulate */
8951         {
8952           char
8953             modulate[MaxTextExtent];
8954
8955           geometry_info.rho=100.0;
8956           geometry_info.sigma=100.0;
8957           geometry_info.xi=100.0;
8958           if (attribute_flag[0] != 0)
8959             (void)ParseGeometry(argument_list[0].string_reference,
8960               &geometry_info);
8961           if (attribute_flag[1] != 0)
8962             geometry_info.xi=argument_list[1].real_reference;
8963           if (attribute_flag[2] != 0)
8964             geometry_info.sigma=argument_list[2].real_reference;
8965           if (attribute_flag[3] != 0)
8966             {
8967               geometry_info.sigma=argument_list[3].real_reference;
8968               SetImageArtifact(image,"modulate:colorspace","HWB");
8969             }
8970           if (attribute_flag[4] != 0)
8971             {
8972               geometry_info.rho=argument_list[4].real_reference;
8973               SetImageArtifact(image,"modulate:colorspace","HSB");
8974             }
8975           if (attribute_flag[5] != 0)
8976             {
8977               geometry_info.sigma=argument_list[5].real_reference;
8978               SetImageArtifact(image,"modulate:colorspace","HSL");
8979             }
8980           if (attribute_flag[6] != 0)
8981             {
8982               geometry_info.rho=argument_list[6].real_reference;
8983               SetImageArtifact(image,"modulate:colorspace","HWB");
8984             }
8985           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8986             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8987           (void) ModulateImage(image,modulate,exception);
8988           break;
8989         }
8990         case 44:  /* Negate */
8991         {
8992           if (attribute_flag[0] == 0)
8993             argument_list[0].integer_reference=0;
8994           if (attribute_flag[1] != 0)
8995             channel=(ChannelType) argument_list[1].integer_reference;
8996           channel_mask=SetImageChannelMask(image,channel);
8997           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8998             MagickTrue : MagickFalse,exception);
8999           (void) SetImageChannelMask(image,channel_mask);
9000           break;
9001         }
9002         case 45:  /* Normalize */
9003         {
9004           if (attribute_flag[0] != 0)
9005             channel=(ChannelType) argument_list[0].integer_reference;
9006           channel_mask=SetImageChannelMask(image,channel);
9007           NormalizeImage(image,exception);
9008           (void) SetImageChannelMask(image,channel_mask);
9009           break;
9010         }
9011         case 46:  /* NumberColors */
9012           break;
9013         case 47:  /* Opaque */
9014         {
9015           MagickBooleanType
9016             invert;
9017
9018           PixelInfo
9019             fill_color,
9020             target;
9021
9022           (void) QueryColorCompliance("none",AllCompliance,&target,
9023              exception);
9024           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9025             exception);
9026           if (attribute_flag[0] != 0)
9027             (void) QueryColorCompliance(argument_list[0].string_reference,
9028               AllCompliance,&target,exception);
9029           if (attribute_flag[1] != 0)
9030             (void) QueryColorCompliance(argument_list[1].string_reference,
9031               AllCompliance,&fill_color,exception);
9032           if (attribute_flag[2] != 0)
9033             image->fuzz=StringToDoubleInterval(
9034               argument_list[2].string_reference,(double) QuantumRange+1.0);
9035           if (attribute_flag[3] != 0)
9036             channel=(ChannelType) argument_list[3].integer_reference;
9037           invert=MagickFalse;
9038           if (attribute_flag[4] != 0)
9039             invert=(MagickBooleanType) argument_list[4].integer_reference;
9040           channel_mask=SetImageChannelMask(image,channel);
9041           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9042           (void) SetImageChannelMask(image,channel_mask);
9043           break;
9044         }
9045         case 48:  /* Quantize */
9046         {
9047           QuantizeInfo
9048             *quantize_info;
9049
9050           quantize_info=AcquireQuantizeInfo(info->image_info);
9051           if (attribute_flag[0] != 0)
9052             quantize_info->number_colors=(size_t)
9053               argument_list[0].integer_reference;
9054           if (attribute_flag[1] != 0)
9055             quantize_info->tree_depth=(size_t)
9056               argument_list[1].integer_reference;
9057           if (attribute_flag[2] != 0)
9058             quantize_info->colorspace=(ColorspaceType)
9059               argument_list[2].integer_reference;
9060           if (attribute_flag[3] != 0)
9061             quantize_info->dither_method=(DitherMethod)
9062               argument_list[3].integer_reference;
9063           if (attribute_flag[4] != 0)
9064             quantize_info->measure_error=argument_list[4].integer_reference !=
9065               0 ? MagickTrue : MagickFalse;
9066           if (attribute_flag[5] != 0)
9067             (void) QueryColorCompliance(argument_list[5].string_reference,
9068               AllCompliance,&image->transparent_color,exception);
9069           if (attribute_flag[5] && argument_list[5].integer_reference)
9070             {
9071               (void) QuantizeImages(quantize_info,image,exception);
9072               goto PerlException;
9073             }
9074           if (attribute_flag[6] != 0)
9075             quantize_info->dither_method=(DitherMethod)
9076               argument_list[6].integer_reference;
9077           if ((image->storage_class == DirectClass) ||
9078               (image->colors > quantize_info->number_colors) ||
9079               (quantize_info->colorspace == GRAYColorspace))
9080             (void) QuantizeImage(quantize_info,image,exception);
9081           else
9082             CompressImageColormap(image,exception);
9083           quantize_info=DestroyQuantizeInfo(quantize_info);
9084           break;
9085         }
9086         case 49:  /* Raise */
9087         {
9088           if (attribute_flag[0] != 0)
9089             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9090               &geometry,exception);
9091           if (attribute_flag[1] != 0)
9092             geometry.width=argument_list[1].integer_reference;
9093           if (attribute_flag[2] != 0)
9094             geometry.height=argument_list[2].integer_reference;
9095           if (attribute_flag[3] == 0)
9096             argument_list[3].integer_reference=1;
9097           (void) RaiseImage(image,&geometry,
9098             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9099             exception);
9100           break;
9101         }
9102         case 50:  /* Segment */
9103         {
9104           ColorspaceType
9105             colorspace;
9106
9107           double
9108             cluster_threshold,
9109             smoothing_threshold;
9110
9111           MagickBooleanType
9112             verbose;
9113
9114           cluster_threshold=1.0;
9115           smoothing_threshold=1.5;
9116           colorspace=sRGBColorspace;
9117           verbose=MagickFalse;
9118           if (attribute_flag[0] != 0)
9119             {
9120               flags=ParseGeometry(argument_list[0].string_reference,
9121                 &geometry_info);
9122               cluster_threshold=geometry_info.rho;
9123               if (flags & SigmaValue)
9124                 smoothing_threshold=geometry_info.sigma;
9125             }
9126           if (attribute_flag[1] != 0)
9127             cluster_threshold=argument_list[1].real_reference;
9128           if (attribute_flag[2] != 0)
9129             smoothing_threshold=argument_list[2].real_reference;
9130           if (attribute_flag[3] != 0)
9131             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9132           if (attribute_flag[4] != 0)
9133             verbose=argument_list[4].integer_reference != 0 ?
9134               MagickTrue : MagickFalse;
9135           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9136             smoothing_threshold,exception);
9137           break;
9138         }
9139         case 51:  /* Signature */
9140         {
9141           (void) SignatureImage(image,exception);
9142           break;
9143         }
9144         case 52:  /* Solarize */
9145         {
9146           geometry_info.rho=QuantumRange/2.0;
9147           if (attribute_flag[0] != 0)
9148             flags=ParseGeometry(argument_list[0].string_reference,
9149               &geometry_info);
9150           if (attribute_flag[1] != 0)
9151             geometry_info.rho=StringToDoubleInterval(
9152               argument_list[1].string_reference,(double) QuantumRange+1.0);
9153           (void) SolarizeImage(image,geometry_info.rho,exception);
9154           break;
9155         }
9156         case 53:  /* Sync */
9157         {
9158           (void) SyncImage(image,exception);
9159           break;
9160         }
9161         case 54:  /* Texture */
9162         {
9163           if (attribute_flag[0] == 0)
9164             break;
9165           TextureImage(image,argument_list[0].image_reference,exception);
9166           break;
9167         }
9168         case 55:  /* Evalute */
9169         {
9170           MagickEvaluateOperator
9171             op;
9172
9173           op=SetEvaluateOperator;
9174           if (attribute_flag[0] == MagickFalse)
9175             argument_list[0].real_reference=0.0;
9176           if (attribute_flag[1] != MagickFalse)
9177             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9178           if (attribute_flag[2] != MagickFalse)
9179             channel=(ChannelType) argument_list[2].integer_reference;
9180           channel_mask=SetImageChannelMask(image,channel);
9181           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9182             exception);
9183           (void) SetImageChannelMask(image,channel_mask);
9184           break;
9185         }
9186         case 56:  /* Transparent */
9187         {
9188           double
9189             opacity;
9190
9191           MagickBooleanType
9192             invert;
9193
9194           PixelInfo
9195             target;
9196
9197           (void) QueryColorCompliance("none",AllCompliance,&target,
9198             exception);
9199           if (attribute_flag[0] != 0)
9200             (void) QueryColorCompliance(argument_list[0].string_reference,
9201               AllCompliance,&target,exception);
9202           opacity=TransparentAlpha;
9203           if (attribute_flag[1] != 0)
9204             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9205               (double) QuantumRange+1.0);
9206           if (attribute_flag[2] != 0)
9207             image->fuzz=StringToDoubleInterval(
9208               argument_list[2].string_reference,(double) QuantumRange+1.0);
9209           if (attribute_flag[3] == 0)
9210             argument_list[3].integer_reference=0;
9211           invert=MagickFalse;
9212           if (attribute_flag[3] != 0)
9213             invert=(MagickBooleanType) argument_list[3].integer_reference;
9214           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9215             invert,exception);
9216           break;
9217         }
9218         case 57:  /* Threshold */
9219         {
9220           double
9221             threshold;
9222
9223           if (attribute_flag[0] == 0)
9224             argument_list[0].string_reference="50%";
9225           if (attribute_flag[1] != 0)
9226             channel=(ChannelType) argument_list[1].integer_reference;
9227           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9228             (double) QuantumRange+1.0);
9229           channel_mask=SetImageChannelMask(image,channel);
9230           (void) BilevelImage(image,threshold,exception);
9231           (void) SetImageChannelMask(image,channel_mask);
9232           break;
9233         }
9234         case 58:  /* Charcoal */
9235         {
9236           if (attribute_flag[0] != 0)
9237             {
9238               flags=ParseGeometry(argument_list[0].string_reference,
9239                 &geometry_info);
9240               if ((flags & SigmaValue) == 0)
9241                 geometry_info.sigma=1.0;
9242             }
9243           if (attribute_flag[1] != 0)
9244             geometry_info.rho=argument_list[1].real_reference;
9245           if (attribute_flag[2] != 0)
9246             geometry_info.sigma=argument_list[2].real_reference;
9247           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9248             exception);
9249           break;
9250         }
9251         case 59:  /* Trim */
9252         {
9253           if (attribute_flag[0] != 0)
9254             image->fuzz=StringToDoubleInterval(
9255               argument_list[0].string_reference,(double) QuantumRange+1.0);
9256           image=TrimImage(image,exception);
9257           break;
9258         }
9259         case 60:  /* Wave */
9260         {
9261           PixelInterpolateMethod
9262             method;
9263
9264           if (attribute_flag[0] != 0)
9265             {
9266               flags=ParseGeometry(argument_list[0].string_reference,
9267                 &geometry_info);
9268               if ((flags & SigmaValue) == 0)
9269                 geometry_info.sigma=1.0;
9270             }
9271           if (attribute_flag[1] != 0)
9272             geometry_info.rho=argument_list[1].real_reference;
9273           if (attribute_flag[2] != 0)
9274             geometry_info.sigma=argument_list[2].real_reference;
9275           method=UndefinedInterpolatePixel;
9276           if (attribute_flag[3] != 0)
9277             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9278           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9279             method,exception);
9280           break;
9281         }
9282         case 61:  /* Separate */
9283         {
9284           if (attribute_flag[0] != 0)
9285             channel=(ChannelType) argument_list[0].integer_reference;
9286           image=SeparateImage(image,channel,exception);
9287           break;
9288         }
9289         case 63:  /* Stereo */
9290         {
9291           if (attribute_flag[0] == 0)
9292             {
9293               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9294                 PackageName);
9295               goto PerlException;
9296             }
9297           if (attribute_flag[1] != 0)
9298             geometry.x=argument_list[1].integer_reference;
9299           if (attribute_flag[2] != 0)
9300             geometry.y=argument_list[2].integer_reference;
9301           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9302             geometry.x,geometry.y,exception);
9303           break;
9304         }
9305         case 64:  /* Stegano */
9306         {
9307           if (attribute_flag[0] == 0)
9308             {
9309               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9310                 PackageName);
9311               goto PerlException;
9312             }
9313           if (attribute_flag[1] == 0)
9314             argument_list[1].integer_reference=0;
9315           image->offset=argument_list[1].integer_reference;
9316           image=SteganoImage(image,argument_list[0].image_reference,exception);
9317           break;
9318         }
9319         case 65:  /* Deconstruct */
9320         {
9321           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9322           break;
9323         }
9324         case 66:  /* GaussianBlur */
9325         {
9326           if (attribute_flag[0] != 0)
9327             {
9328               flags=ParseGeometry(argument_list[0].string_reference,
9329                 &geometry_info);
9330               if ((flags & SigmaValue) == 0)
9331                 geometry_info.sigma=1.0;
9332             }
9333           if (attribute_flag[1] != 0)
9334             geometry_info.rho=argument_list[1].real_reference;
9335           if (attribute_flag[2] != 0)
9336             geometry_info.sigma=argument_list[2].real_reference;
9337           if (attribute_flag[3] != 0)
9338             channel=(ChannelType) argument_list[3].integer_reference;
9339           channel_mask=SetImageChannelMask(image,channel);
9340           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9341             exception);
9342           if (image != (Image *) NULL)
9343             (void) SetImageChannelMask(image,channel_mask);
9344           break;
9345         }
9346         case 67:  /* Convolve */
9347         {
9348           KernelInfo
9349             *kernel;
9350
9351           kernel=(KernelInfo *) NULL;
9352           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9353             break;
9354           if (attribute_flag[0] != 0)
9355             {
9356               AV
9357                 *av;
9358
9359               size_t
9360                 order;
9361
9362               kernel=AcquireKernelInfo((const char *) NULL);
9363               if (kernel == (KernelInfo *) NULL)
9364                 break;
9365               av=(AV *) argument_list[0].array_reference;
9366               order=(size_t) sqrt(av_len(av)+1);
9367               kernel->width=order;
9368               kernel->height=order;
9369               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9370                 order*sizeof(*kernel->values));
9371               if (kernel->values == (MagickRealType *) NULL)
9372                 {
9373                   kernel=DestroyKernelInfo(kernel);
9374                   ThrowPerlException(exception,ResourceLimitFatalError,
9375                     "MemoryAllocationFailed",PackageName);
9376                   goto PerlException;
9377                 }
9378               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9379                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9380               for ( ; j < (ssize_t) (order*order); j++)
9381                 kernel->values[j]=0.0;
9382             }
9383           if (attribute_flag[1] != 0)
9384             channel=(ChannelType) argument_list[1].integer_reference;
9385           if (attribute_flag[2] != 0)
9386             SetImageArtifact(image,"filter:blur",
9387               argument_list[2].string_reference);
9388           if (attribute_flag[3] != 0)
9389             {
9390               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9391               if (kernel == (KernelInfo *) NULL)
9392                 break;
9393             }
9394           channel_mask=SetImageChannelMask(image,channel);
9395           image=ConvolveImage(image,kernel,exception);
9396           if (image != (Image *) NULL)
9397             (void) SetImageChannelMask(image,channel_mask);
9398           kernel=DestroyKernelInfo(kernel);
9399           break;
9400         }
9401         case 68:  /* Profile */
9402         {
9403           const char
9404             *name;
9405
9406           Image
9407             *profile_image;
9408
9409           ImageInfo
9410             *profile_info;
9411
9412           StringInfo
9413             *profile;
9414
9415           name="*";
9416           if (attribute_flag[0] != 0)
9417             name=argument_list[0].string_reference;
9418           if (attribute_flag[2] != 0)
9419             image->rendering_intent=(RenderingIntent)
9420               argument_list[2].integer_reference;
9421           if (attribute_flag[3] != 0)
9422             image->black_point_compensation=
9423               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9424           if (attribute_flag[1] != 0)
9425             {
9426               if (argument_list[1].length == 0)
9427                 {
9428                   /*
9429                     Remove a profile from the image.
9430                   */
9431                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9432                     exception);
9433                   break;
9434                 }
9435               /*
9436                 Associate user supplied profile with the image.
9437               */
9438               profile=AcquireStringInfo(argument_list[1].length);
9439               SetStringInfoDatum(profile,(const unsigned char *)
9440                 argument_list[1].string_reference);
9441               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9442                 (size_t) GetStringInfoLength(profile),exception);
9443               profile=DestroyStringInfo(profile);
9444               break;
9445             }
9446           /*
9447             Associate a profile with the image.
9448           */
9449           profile_info=CloneImageInfo(info ? info->image_info :
9450             (ImageInfo *) NULL);
9451           profile_image=ReadImages(profile_info,name,exception);
9452           if (profile_image == (Image *) NULL)
9453             break;
9454           ResetImageProfileIterator(profile_image);
9455           name=GetNextImageProfile(profile_image);
9456           while (name != (const char *) NULL)
9457           {
9458             const StringInfo
9459               *profile;
9460
9461             profile=GetImageProfile(profile_image,name);
9462             if (profile != (const StringInfo *) NULL)
9463               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9464                 (size_t) GetStringInfoLength(profile),exception);
9465             name=GetNextImageProfile(profile_image);
9466           }
9467           profile_image=DestroyImage(profile_image);
9468           profile_info=DestroyImageInfo(profile_info);
9469           break;
9470         }
9471         case 69:  /* UnsharpMask */
9472         {
9473           if (attribute_flag[0] != 0)
9474             {
9475               flags=ParseGeometry(argument_list[0].string_reference,
9476                 &geometry_info);
9477               if ((flags & SigmaValue) == 0)
9478                 geometry_info.sigma=1.0;
9479               if ((flags & XiValue) == 0)
9480                 geometry_info.xi=1.0;
9481               if ((flags & PsiValue) == 0)
9482                 geometry_info.psi=0.5;
9483             }
9484           if (attribute_flag[1] != 0)
9485             geometry_info.rho=argument_list[1].real_reference;
9486           if (attribute_flag[2] != 0)
9487             geometry_info.sigma=argument_list[2].real_reference;
9488           if (attribute_flag[3] != 0)
9489             geometry_info.xi=argument_list[3].real_reference;
9490           if (attribute_flag[4] != 0)
9491             geometry_info.psi=argument_list[4].real_reference;
9492           if (attribute_flag[5] != 0)
9493             channel=(ChannelType) argument_list[5].integer_reference;
9494           channel_mask=SetImageChannelMask(image,channel);
9495           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9496             geometry_info.xi,geometry_info.psi,exception);
9497           if (image != (Image *) NULL)
9498             (void) SetImageChannelMask(image,channel_mask);
9499           break;
9500         }
9501         case 70:  /* MotionBlur */
9502         {
9503           if (attribute_flag[0] != 0)
9504             {
9505               flags=ParseGeometry(argument_list[0].string_reference,
9506                 &geometry_info);
9507               if ((flags & SigmaValue) == 0)
9508                 geometry_info.sigma=1.0;
9509               if ((flags & XiValue) == 0)
9510                 geometry_info.xi=1.0;
9511             }
9512           if (attribute_flag[1] != 0)
9513             geometry_info.rho=argument_list[1].real_reference;
9514           if (attribute_flag[2] != 0)
9515             geometry_info.sigma=argument_list[2].real_reference;
9516           if (attribute_flag[3] != 0)
9517             geometry_info.xi=argument_list[3].real_reference;
9518           if (attribute_flag[4] != 0)
9519             channel=(ChannelType) argument_list[4].integer_reference;
9520           channel_mask=SetImageChannelMask(image,channel);
9521           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9522             geometry_info.xi,exception);
9523           if (image != (Image *) NULL)
9524             (void) SetImageChannelMask(image,channel_mask);
9525           break;
9526         }
9527         case 71:  /* OrderedDither */
9528         {
9529           if (attribute_flag[0] == 0)
9530             argument_list[0].string_reference="o8x8";
9531           if (attribute_flag[1] != 0)
9532             channel=(ChannelType) argument_list[1].integer_reference;
9533           channel_mask=SetImageChannelMask(image,channel);
9534           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9535             exception);
9536           (void) SetImageChannelMask(image,channel_mask);
9537           break;
9538         }
9539         case 72:  /* Shave */
9540         {
9541           if (attribute_flag[0] != 0)
9542             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9543               &geometry,exception);
9544           if (attribute_flag[1] != 0)
9545             geometry.width=argument_list[1].integer_reference;
9546           if (attribute_flag[2] != 0)
9547             geometry.height=argument_list[2].integer_reference;
9548           image=ShaveImage(image,&geometry,exception);
9549           break;
9550         }
9551         case 73:  /* Level */
9552         {
9553           double
9554             black_point,
9555             gamma,
9556             white_point;
9557
9558           black_point=0.0;
9559           white_point=(double) image->columns*image->rows;
9560           gamma=1.0;
9561           if (attribute_flag[0] != 0)
9562             {
9563               flags=ParseGeometry(argument_list[0].string_reference,
9564                 &geometry_info);
9565               black_point=geometry_info.rho;
9566               if ((flags & SigmaValue) != 0)
9567                 white_point=geometry_info.sigma;
9568               if ((flags & XiValue) != 0)
9569                 gamma=geometry_info.xi;
9570               if ((flags & PercentValue) != 0)
9571                 {
9572                   black_point*=(double) (QuantumRange/100.0);
9573                   white_point*=(double) (QuantumRange/100.0);
9574                 }
9575               if ((flags & SigmaValue) == 0)
9576                 white_point=(double) QuantumRange-black_point;
9577             }
9578           if (attribute_flag[1] != 0)
9579             black_point=argument_list[1].real_reference;
9580           if (attribute_flag[2] != 0)
9581             white_point=argument_list[2].real_reference;
9582           if (attribute_flag[3] != 0)
9583             gamma=argument_list[3].real_reference;
9584           if (attribute_flag[4] != 0)
9585             channel=(ChannelType) argument_list[4].integer_reference;
9586           if (attribute_flag[5] != 0)
9587             {
9588               argument_list[0].real_reference=argument_list[5].real_reference;
9589               attribute_flag[0]=attribute_flag[5];
9590             }
9591           channel_mask=SetImageChannelMask(image,channel);
9592           (void) LevelImage(image,black_point,white_point,gamma,exception);
9593           (void) SetImageChannelMask(image,channel_mask);
9594           break;
9595         }
9596         case 74:  /* Clip */
9597         {
9598           if (attribute_flag[0] == 0)
9599             argument_list[0].string_reference="#1";
9600           if (attribute_flag[1] == 0)
9601             argument_list[1].integer_reference=MagickTrue;
9602           (void) ClipImagePath(image,argument_list[0].string_reference,
9603             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9604             exception);
9605           break;
9606         }
9607         case 75:  /* AffineTransform */
9608         {
9609           DrawInfo
9610             *draw_info;
9611
9612           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9613             (DrawInfo *) NULL);
9614           if (attribute_flag[0] != 0)
9615             {
9616               AV
9617                 *av;
9618
9619               av=(AV *) argument_list[0].array_reference;
9620               if ((av_len(av) != 3) && (av_len(av) != 5))
9621                 {
9622                   ThrowPerlException(exception,OptionError,
9623                     "affine matrix must have 4 or 6 elements",PackageName);
9624                   goto PerlException;
9625                 }
9626               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9627               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9628               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9629               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9630               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9631                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9632                 {
9633                   ThrowPerlException(exception,OptionError,
9634                     "affine matrix is singular",PackageName);
9635                    goto PerlException;
9636                 }
9637               if (av_len(av) == 5)
9638                 {
9639                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9640                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9641                 }
9642             }
9643           for (j=1; j < 6; j++)
9644           {
9645             if (attribute_flag[j] == 0)
9646               continue;
9647             value=argument_list[j].string_reference;
9648             angle=argument_list[j].real_reference;
9649             current=draw_info->affine;
9650             GetAffineMatrix(&affine);
9651             switch (j)
9652             {
9653               case 1:
9654               {
9655                 /*
9656                   Translate.
9657                 */
9658                 flags=ParseGeometry(value,&geometry_info);
9659                 affine.tx=geometry_info.xi;
9660                 affine.ty=geometry_info.psi;
9661                 if ((flags & PsiValue) == 0)
9662                   affine.ty=affine.tx;
9663                 break;
9664               }
9665               case 2:
9666               {
9667                 /*
9668                   Scale.
9669                 */
9670                 flags=ParseGeometry(value,&geometry_info);
9671                 affine.sx=geometry_info.rho;
9672                 affine.sy=geometry_info.sigma;
9673                 if ((flags & SigmaValue) == 0)
9674                   affine.sy=affine.sx;
9675                 break;
9676               }
9677               case 3:
9678               {
9679                 /*
9680                   Rotate.
9681                 */
9682                 if (angle == 0.0)
9683                   break;
9684                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9685                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9686                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9687                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9688                 break;
9689               }
9690               case 4:
9691               {
9692                 /*
9693                   SkewX.
9694                 */
9695                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9696                 break;
9697               }
9698               case 5:
9699               {
9700                 /*
9701                   SkewY.
9702                 */
9703                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9704                 break;
9705               }
9706             }
9707             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9708             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9709             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9710             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9711             draw_info->affine.tx=
9712               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9713             draw_info->affine.ty=
9714               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9715           }
9716           if (attribute_flag[6] != 0)
9717             image->interpolate=(PixelInterpolateMethod)
9718               argument_list[6].integer_reference;
9719           if (attribute_flag[7] != 0)
9720             QueryColorCompliance(argument_list[7].string_reference,
9721               AllCompliance,&image->background_color,exception);
9722           image=AffineTransformImage(image,&draw_info->affine,exception);
9723           draw_info=DestroyDrawInfo(draw_info);
9724           break;
9725         }
9726         case 76:  /* Difference */
9727         {
9728           if (attribute_flag[0] == 0)
9729             {
9730               ThrowPerlException(exception,OptionError,
9731                 "ReferenceImageRequired",PackageName);
9732               goto PerlException;
9733             }
9734           if (attribute_flag[1] != 0)
9735             image->fuzz=StringToDoubleInterval(
9736               argument_list[1].string_reference,(double) QuantumRange+1.0);
9737           (void) IsImagesEqual(image,argument_list[0].image_reference,
9738             exception);
9739           break;
9740         }
9741         case 77:  /* AdaptiveThreshold */
9742         {
9743           if (attribute_flag[0] != 0)
9744             {
9745               flags=ParseGeometry(argument_list[0].string_reference,
9746                 &geometry_info);
9747               if ((flags & PercentValue) != 0)
9748                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9749             }
9750           if (attribute_flag[1] != 0)
9751             geometry_info.rho=argument_list[1].integer_reference;
9752           if (attribute_flag[2] != 0)
9753             geometry_info.sigma=argument_list[2].integer_reference;
9754           if (attribute_flag[3] != 0)
9755             geometry_info.xi=argument_list[3].integer_reference;;
9756           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9757             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9758           break;
9759         }
9760         case 78:  /* Resample */
9761         {
9762           size_t
9763             height,
9764             width;
9765
9766           if (attribute_flag[0] != 0)
9767             {
9768               flags=ParseGeometry(argument_list[0].string_reference,
9769                 &geometry_info);
9770               if ((flags & SigmaValue) == 0)
9771                 geometry_info.sigma=geometry_info.rho;
9772             }
9773           if (attribute_flag[1] != 0)
9774             geometry_info.rho=argument_list[1].real_reference;
9775           if (attribute_flag[2] != 0)
9776             geometry_info.sigma=argument_list[2].real_reference;
9777           if (attribute_flag[3] == 0)
9778             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9779           if (attribute_flag[4] == 0)
9780             SetImageArtifact(image,"filter:support",
9781               argument_list[4].string_reference);
9782           width=(size_t) (geometry_info.rho*image->columns/
9783             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9784           height=(size_t) (geometry_info.sigma*image->rows/
9785             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9786           image=ResizeImage(image,width,height,(FilterTypes)
9787             argument_list[3].integer_reference,exception);
9788           if (image != (Image *) NULL)
9789             {
9790               image->resolution.x=geometry_info.rho;
9791               image->resolution.y=geometry_info.sigma;
9792             }
9793           break;
9794         }
9795         case 79:  /* Describe */
9796         {
9797           if (attribute_flag[0] == 0)
9798             argument_list[0].file_reference=(FILE *) NULL;
9799           if (attribute_flag[1] != 0)
9800             (void) SetImageArtifact(image,"identify:features",
9801               argument_list[1].string_reference);
9802           (void) IdentifyImage(image,argument_list[0].file_reference,
9803             MagickTrue,exception);
9804           break;
9805         }
9806         case 80:  /* BlackThreshold */
9807         {
9808           if (attribute_flag[0] == 0)
9809             argument_list[0].string_reference="50%";
9810           if (attribute_flag[2] != 0)
9811             channel=(ChannelType) argument_list[2].integer_reference;
9812           channel_mask=SetImageChannelMask(image,channel);
9813           BlackThresholdImage(image,argument_list[0].string_reference,
9814             exception);
9815           (void) SetImageChannelMask(image,channel_mask);
9816           break;
9817         }
9818         case 81:  /* WhiteThreshold */
9819         {
9820           if (attribute_flag[0] == 0)
9821             argument_list[0].string_reference="50%";
9822           if (attribute_flag[2] != 0)
9823             channel=(ChannelType) argument_list[2].integer_reference;
9824           channel_mask=SetImageChannelMask(image,channel);
9825           WhiteThresholdImage(image,argument_list[0].string_reference,
9826             exception);
9827           (void) SetImageChannelMask(image,channel_mask);
9828           break;
9829         }
9830         case 82:  /* RadialBlur */
9831         {
9832           if (attribute_flag[0] != 0)
9833             {
9834               flags=ParseGeometry(argument_list[0].string_reference,
9835                 &geometry_info);
9836             }
9837           if (attribute_flag[1] != 0)
9838             geometry_info.rho=argument_list[1].real_reference;
9839           if (attribute_flag[2] != 0)
9840             channel=(ChannelType) argument_list[2].integer_reference;
9841           channel_mask=SetImageChannelMask(image,channel);
9842           image=RadialBlurImage(image,geometry_info.rho,exception);
9843           if (image != (Image *) NULL)
9844             (void) SetImageChannelMask(image,channel_mask);
9845           break;
9846         }
9847         case 83:  /* Thumbnail */
9848         {
9849           if (attribute_flag[0] != 0)
9850             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9851               &geometry,exception);
9852           if (attribute_flag[1] != 0)
9853             geometry.width=argument_list[1].integer_reference;
9854           if (attribute_flag[2] != 0)
9855             geometry.height=argument_list[2].integer_reference;
9856           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9857           break;
9858         }
9859         case 84:  /* Strip */
9860         {
9861           (void) StripImage(image,exception);
9862           break;
9863         }
9864         case 85:  /* Tint */
9865         {
9866           PixelInfo
9867             tint;
9868
9869           GetPixelInfo(image,&tint);
9870           if (attribute_flag[0] != 0)
9871             (void) QueryColorCompliance(argument_list[0].string_reference,
9872               AllCompliance,&tint,exception);
9873           if (attribute_flag[1] == 0)
9874             argument_list[1].string_reference="100";
9875           image=TintImage(image,argument_list[1].string_reference,&tint,
9876             exception);
9877           break;
9878         }
9879         case 86:  /* Channel */
9880         {
9881           if (attribute_flag[0] != 0)
9882             channel=(ChannelType) argument_list[0].integer_reference;
9883           image=SeparateImage(image,channel,exception);
9884           break;
9885         }
9886         case 87:  /* Splice */
9887         {
9888           if (attribute_flag[0] != 0)
9889             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9890               &geometry,exception);
9891           if (attribute_flag[1] != 0)
9892             geometry.width=argument_list[1].integer_reference;
9893           if (attribute_flag[2] != 0)
9894             geometry.height=argument_list[2].integer_reference;
9895           if (attribute_flag[3] != 0)
9896             geometry.x=argument_list[3].integer_reference;
9897           if (attribute_flag[4] != 0)
9898             geometry.y=argument_list[4].integer_reference;
9899           if (attribute_flag[5] != 0)
9900             image->fuzz=StringToDoubleInterval(
9901               argument_list[5].string_reference,(double) QuantumRange+1.0);
9902           if (attribute_flag[6] != 0)
9903             (void) QueryColorCompliance(argument_list[6].string_reference,
9904               AllCompliance,&image->background_color,exception);
9905           if (attribute_flag[7] != 0)
9906             image->gravity=(GravityType) argument_list[7].integer_reference;
9907           image=SpliceImage(image,&geometry,exception);
9908           break;
9909         }
9910         case 88:  /* Posterize */
9911         {
9912           if (attribute_flag[0] == 0)
9913             argument_list[0].integer_reference=3;
9914           if (attribute_flag[1] == 0)
9915             argument_list[1].integer_reference=0;
9916           (void) PosterizeImage(image,argument_list[0].integer_reference,
9917             argument_list[1].integer_reference ? RiemersmaDitherMethod :
9918             NoDitherMethod,exception);
9919           break;
9920         }
9921         case 89:  /* Shadow */
9922         {
9923           if (attribute_flag[0] != 0)
9924             {
9925               flags=ParseGeometry(argument_list[0].string_reference,
9926                 &geometry_info);
9927               if ((flags & SigmaValue) == 0)
9928                 geometry_info.sigma=1.0;
9929               if ((flags & XiValue) == 0)
9930                 geometry_info.xi=4.0;
9931               if ((flags & PsiValue) == 0)
9932                 geometry_info.psi=4.0;
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             geometry_info.xi=argument_list[3].integer_reference;
9940           if (attribute_flag[4] != 0)
9941             geometry_info.psi=argument_list[4].integer_reference;
9942           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9943             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
9944             ceil(geometry_info.psi-0.5),exception);
9945           break;
9946         }
9947         case 90:  /* Identify */
9948         {
9949           if (attribute_flag[0] == 0)
9950             argument_list[0].file_reference=(FILE *) NULL;
9951           if (attribute_flag[1] != 0)
9952             (void) SetImageArtifact(image,"identify:features",
9953               argument_list[1].string_reference);
9954           if ((attribute_flag[2] != 0) &&
9955               (argument_list[2].integer_reference != 0))
9956             (void) SetImageArtifact(image,"identify:unique","true");
9957           (void) IdentifyImage(image,argument_list[0].file_reference,
9958             MagickTrue,exception);
9959           break;
9960         }
9961         case 91:  /* SepiaTone */
9962         {
9963           if (attribute_flag[0] == 0)
9964             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9965           image=SepiaToneImage(image,argument_list[0].real_reference,
9966             exception);
9967           break;
9968         }
9969         case 92:  /* SigmoidalContrast */
9970         {
9971           MagickBooleanType
9972             sharpen;
9973
9974           if (attribute_flag[0] != 0)
9975             {
9976               flags=ParseGeometry(argument_list[0].string_reference,
9977                 &geometry_info);
9978               if ((flags & SigmaValue) == 0)
9979                 geometry_info.sigma=QuantumRange/2.0;
9980               if ((flags & PercentValue) != 0)
9981                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9982             }
9983           if (attribute_flag[1] != 0)
9984             geometry_info.rho=argument_list[1].real_reference;
9985           if (attribute_flag[2] != 0)
9986             geometry_info.sigma=argument_list[2].real_reference;
9987           if (attribute_flag[3] != 0)
9988             channel=(ChannelType) argument_list[3].integer_reference;
9989           sharpen=MagickTrue;
9990           if (attribute_flag[4] != 0)
9991             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9992               MagickFalse;
9993           channel_mask=SetImageChannelMask(image,channel);
9994           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9995             geometry_info.sigma,exception);
9996           (void) SetImageChannelMask(image,channel_mask);
9997           break;
9998         }
9999         case 93:  /* Extent */
10000         {
10001           if (attribute_flag[7] != 0)
10002             image->gravity=(GravityType) argument_list[7].integer_reference;
10003           if (attribute_flag[0] != 0)
10004             {
10005               int
10006                 flags;
10007
10008               flags=ParseGravityGeometry(image,
10009                 argument_list[0].string_reference,&geometry,exception);
10010               (void) flags;
10011               if (geometry.width == 0)
10012                 geometry.width=image->columns;
10013               if (geometry.height == 0)
10014                 geometry.height=image->rows;
10015             }
10016           if (attribute_flag[1] != 0)
10017             geometry.width=argument_list[1].integer_reference;
10018           if (attribute_flag[2] != 0)
10019             geometry.height=argument_list[2].integer_reference;
10020           if (attribute_flag[3] != 0)
10021             geometry.x=argument_list[3].integer_reference;
10022           if (attribute_flag[4] != 0)
10023             geometry.y=argument_list[4].integer_reference;
10024           if (attribute_flag[5] != 0)
10025             image->fuzz=StringToDoubleInterval(
10026               argument_list[5].string_reference,(double) QuantumRange+1.0);
10027           if (attribute_flag[6] != 0)
10028             (void) QueryColorCompliance(argument_list[6].string_reference,
10029               AllCompliance,&image->background_color,exception);
10030           image=ExtentImage(image,&geometry,exception);
10031           break;
10032         }
10033         case 94:  /* Vignette */
10034         {
10035           if (attribute_flag[0] != 0)
10036             {
10037               flags=ParseGeometry(argument_list[0].string_reference,
10038                 &geometry_info);
10039               if ((flags & SigmaValue) == 0)
10040                 geometry_info.sigma=1.0;
10041               if ((flags & XiValue) == 0)
10042                 geometry_info.xi=0.1*image->columns;
10043               if ((flags & PsiValue) == 0)
10044                 geometry_info.psi=0.1*image->rows;
10045             }
10046           if (attribute_flag[1] != 0)
10047             geometry_info.rho=argument_list[1].real_reference;
10048           if (attribute_flag[2] != 0)
10049             geometry_info.sigma=argument_list[2].real_reference;
10050           if (attribute_flag[3] != 0)
10051             geometry_info.xi=argument_list[3].integer_reference;
10052           if (attribute_flag[4] != 0)
10053             geometry_info.psi=argument_list[4].integer_reference;
10054           if (attribute_flag[5] != 0)
10055             (void) QueryColorCompliance(argument_list[5].string_reference,
10056               AllCompliance,&image->background_color,exception);
10057           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10058             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10059             ceil(geometry_info.psi-0.5),exception);
10060           break;
10061         }
10062         case 95:  /* ContrastStretch */
10063         {
10064           double
10065             black_point,
10066             white_point;
10067
10068           black_point=0.0;
10069           white_point=(double) image->columns*image->rows;
10070           if (attribute_flag[0] != 0)
10071             {
10072               flags=ParseGeometry(argument_list[0].string_reference,
10073                 &geometry_info);
10074               black_point=geometry_info.rho;
10075               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10076                 black_point;
10077               if ((flags & PercentValue) != 0)
10078                 {
10079                   black_point*=(double) image->columns*image->rows/100.0;
10080                   white_point*=(double) image->columns*image->rows/100.0;
10081                 }
10082               white_point=(double) image->columns*image->rows-
10083                 white_point;
10084             }
10085           if (attribute_flag[1] != 0)
10086             black_point=argument_list[1].real_reference;
10087           if (attribute_flag[2] != 0)
10088             white_point=argument_list[2].real_reference;
10089           if (attribute_flag[4] != 0)
10090             channel=(ChannelType) argument_list[4].integer_reference;
10091           channel_mask=SetImageChannelMask(image,channel);
10092           (void) ContrastStretchImage(image,black_point,white_point,exception);
10093           (void) SetImageChannelMask(image,channel_mask);
10094           break;
10095         }
10096         case 96:  /* Sans0 */
10097         {
10098           break;
10099         }
10100         case 97:  /* Sans1 */
10101         {
10102           break;
10103         }
10104         case 98:  /* AdaptiveSharpen */
10105         {
10106           if (attribute_flag[0] != 0)
10107             {
10108               flags=ParseGeometry(argument_list[0].string_reference,
10109                 &geometry_info);
10110               if ((flags & SigmaValue) == 0)
10111                 geometry_info.sigma=1.0;
10112               if ((flags & XiValue) == 0)
10113                 geometry_info.xi=0.0;
10114             }
10115           if (attribute_flag[1] != 0)
10116             geometry_info.rho=argument_list[1].real_reference;
10117           if (attribute_flag[2] != 0)
10118             geometry_info.sigma=argument_list[2].real_reference;
10119           if (attribute_flag[3] != 0)
10120             geometry_info.xi=argument_list[3].real_reference;
10121           if (attribute_flag[4] != 0)
10122             channel=(ChannelType) argument_list[4].integer_reference;
10123           channel_mask=SetImageChannelMask(image,channel);
10124           image=AdaptiveSharpenImage(image,geometry_info.rho,
10125             geometry_info.sigma,exception);
10126           if (image != (Image *) NULL)
10127             (void) SetImageChannelMask(image,channel_mask);
10128           break;
10129         }
10130         case 99:  /* Transpose */
10131         {
10132           image=TransposeImage(image,exception);
10133           break;
10134         }
10135         case 100:  /* Tranverse */
10136         {
10137           image=TransverseImage(image,exception);
10138           break;
10139         }
10140         case 101:  /* AutoOrient */
10141         {
10142           switch (image->orientation)
10143           {
10144             case TopRightOrientation:
10145             {
10146               image=FlopImage(image,exception);
10147               break;
10148             }
10149             case BottomRightOrientation:
10150             {
10151               image=RotateImage(image,180.0,exception);
10152               break;
10153             }
10154             case BottomLeftOrientation:
10155             {
10156               image=FlipImage(image,exception);
10157               break;
10158             }
10159             case LeftTopOrientation:
10160             {
10161               image=TransposeImage(image,exception);
10162               break;
10163             }
10164             case RightTopOrientation:
10165             {
10166               image=RotateImage(image,90.0,exception);
10167               break;
10168             }
10169             case RightBottomOrientation:
10170             {
10171               image=TransverseImage(image,exception);
10172               break;
10173             }
10174             case LeftBottomOrientation:
10175             {
10176               image=RotateImage(image,270.0,exception);
10177               break;
10178             }
10179             default:
10180               break;
10181           }
10182           break;
10183         }
10184         case 102:  /* AdaptiveBlur */
10185         {
10186           if (attribute_flag[0] != 0)
10187             {
10188               flags=ParseGeometry(argument_list[0].string_reference,
10189                 &geometry_info);
10190               if ((flags & SigmaValue) == 0)
10191                 geometry_info.sigma=1.0;
10192               if ((flags & XiValue) == 0)
10193                 geometry_info.xi=0.0;
10194             }
10195           if (attribute_flag[1] != 0)
10196             geometry_info.rho=argument_list[1].real_reference;
10197           if (attribute_flag[2] != 0)
10198             geometry_info.sigma=argument_list[2].real_reference;
10199           if (attribute_flag[3] != 0)
10200             channel=(ChannelType) argument_list[3].integer_reference;
10201           channel_mask=SetImageChannelMask(image,channel);
10202           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10203             exception);
10204           if (image != (Image *) NULL)
10205             (void) SetImageChannelMask(image,channel_mask);
10206           break;
10207         }
10208         case 103:  /* Sketch */
10209         {
10210           if (attribute_flag[0] != 0)
10211             {
10212               flags=ParseGeometry(argument_list[0].string_reference,
10213                 &geometry_info);
10214               if ((flags & SigmaValue) == 0)
10215                 geometry_info.sigma=1.0;
10216               if ((flags & XiValue) == 0)
10217                 geometry_info.xi=1.0;
10218             }
10219           if (attribute_flag[1] != 0)
10220             geometry_info.rho=argument_list[1].real_reference;
10221           if (attribute_flag[2] != 0)
10222             geometry_info.sigma=argument_list[2].real_reference;
10223           if (attribute_flag[3] != 0)
10224             geometry_info.xi=argument_list[3].real_reference;
10225           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10226             geometry_info.xi,exception);
10227           break;
10228         }
10229         case 104:  /* UniqueColors */
10230         {
10231           image=UniqueImageColors(image,exception);
10232           break;
10233         }
10234         case 105:  /* AdaptiveResize */
10235         {
10236           if (attribute_flag[0] != 0)
10237             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10238               &geometry,exception);
10239           if (attribute_flag[1] != 0)
10240             geometry.width=argument_list[1].integer_reference;
10241           if (attribute_flag[2] != 0)
10242             geometry.height=argument_list[2].integer_reference;
10243           if (attribute_flag[3] != 0)
10244             image->filter=(FilterTypes) argument_list[4].integer_reference;
10245           if (attribute_flag[4] != 0)
10246             SetImageArtifact(image,"filter:support",
10247               argument_list[4].string_reference);
10248           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10249             exception);
10250           break;
10251         }
10252         case 106:  /* ClipMask */
10253         {
10254           Image
10255             *mask_image;
10256
10257           if (attribute_flag[0] == 0)
10258             {
10259               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10260                 PackageName);
10261               goto PerlException;
10262             }
10263           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10264             exception);
10265           (void) NegateImage(mask_image,MagickFalse,exception);
10266           (void) SetImageMask(image,mask_image,exception);
10267           mask_image=DestroyImage(mask_image);
10268           break;
10269         }
10270         case 107:  /* LinearStretch */
10271         {
10272            double
10273              black_point,
10274              white_point;
10275
10276            black_point=0.0;
10277            white_point=(double) image->columns*image->rows;
10278            if (attribute_flag[0] != 0)
10279              {
10280                flags=ParseGeometry(argument_list[0].string_reference,
10281                  &geometry_info);
10282                if ((flags & SigmaValue) != 0)
10283                   white_point=geometry_info.sigma;
10284                if ((flags & PercentValue) != 0)
10285                  {
10286                    black_point*=(double) image->columns*image->rows/100.0;
10287                    white_point*=(double) image->columns*image->rows/100.0;
10288                  }
10289                if ((flags & SigmaValue) == 0)
10290                  white_point=(double) image->columns*image->rows-black_point;
10291              }
10292           if (attribute_flag[1] != 0)
10293             black_point=argument_list[1].real_reference;
10294           if (attribute_flag[2] != 0)
10295             white_point=argument_list[2].real_reference;
10296           (void) LinearStretchImage(image,black_point,white_point,exception);
10297           break;
10298         }
10299         case 108:  /* ColorMatrix */
10300         {
10301           AV
10302             *av;
10303
10304           double
10305             *color_matrix;
10306
10307           KernelInfo
10308             *kernel_info;
10309
10310           size_t
10311             order;
10312
10313           if (attribute_flag[0] == 0)
10314             break;
10315           av=(AV *) argument_list[0].array_reference;
10316           order=(size_t) sqrt(av_len(av)+1);
10317           color_matrix=(double *) AcquireQuantumMemory(order,order*
10318             sizeof(*color_matrix));
10319           if (color_matrix == (double *) NULL)
10320             {
10321               ThrowPerlException(exception,ResourceLimitFatalError,
10322                 "MemoryAllocationFailed",PackageName);
10323               goto PerlException;
10324            }
10325           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10326             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10327           for ( ; j < (ssize_t) (order*order); j++)
10328             color_matrix[j]=0.0;
10329           kernel_info=AcquireKernelInfo((const char *) NULL);
10330           if (kernel_info == (KernelInfo *) NULL)
10331             break;
10332           kernel_info->width=order;
10333           kernel_info->height=order;
10334           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10335             order*sizeof(*kernel_info->values));
10336           if (kernel_info->values != (MagickRealType *) NULL)
10337             {
10338               for (i=0; i < (ssize_t) (order*order); i++)
10339                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10340               image=ColorMatrixImage(image,kernel_info,exception);
10341             }
10342           kernel_info=DestroyKernelInfo(kernel_info);
10343           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10344           break;
10345         }
10346         case 109:  /* Mask */
10347         {
10348           Image
10349             *mask_image;
10350
10351           if (attribute_flag[0] == 0)
10352             {
10353               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10354                 PackageName);
10355               goto PerlException;
10356             }
10357           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10358             MagickTrue,exception);
10359           (void) NegateImage(mask_image,MagickFalse,exception);
10360           (void) SetImageMask(image,mask_image,exception);
10361           mask_image=DestroyImage(mask_image);
10362           break;
10363         }
10364         case 110:  /* Polaroid */
10365         {
10366           char
10367             *caption;
10368
10369           DrawInfo
10370             *draw_info;
10371
10372           double
10373             angle;
10374
10375           PixelInterpolateMethod
10376             method;
10377
10378           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10379             (DrawInfo *) NULL);
10380           caption=(char *) NULL;
10381           if (attribute_flag[0] != 0)
10382             caption=InterpretImageProperties(info ? info->image_info :
10383               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10384               exception);
10385           angle=0.0;
10386           if (attribute_flag[1] != 0)
10387             angle=argument_list[1].real_reference;
10388           if (attribute_flag[2] != 0)
10389             (void) CloneString(&draw_info->font,
10390               argument_list[2].string_reference);
10391           if (attribute_flag[3] != 0)
10392             (void) QueryColorCompliance(argument_list[3].string_reference,
10393               AllCompliance,&draw_info->stroke,exception);
10394           if (attribute_flag[4] != 0)
10395             (void) QueryColorCompliance(argument_list[4].string_reference,
10396               AllCompliance,&draw_info->fill,exception);
10397           if (attribute_flag[5] != 0)
10398             draw_info->stroke_width=argument_list[5].real_reference;
10399           if (attribute_flag[6] != 0)
10400             draw_info->pointsize=argument_list[6].real_reference;
10401           if (attribute_flag[7] != 0)
10402             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10403           if (attribute_flag[8] != 0)
10404             (void) QueryColorCompliance(argument_list[8].string_reference,
10405               AllCompliance,&image->background_color,exception);
10406           method=UndefinedInterpolatePixel;
10407           if (attribute_flag[9] != 0)
10408             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10409           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10410           draw_info=DestroyDrawInfo(draw_info);
10411           if (caption != (char *) NULL)
10412             caption=DestroyString(caption);
10413           break;
10414         }
10415         case 111:  /* FloodfillPaint */
10416         {
10417           DrawInfo
10418             *draw_info;
10419
10420           MagickBooleanType
10421             invert;
10422
10423           PixelInfo
10424             target;
10425
10426           draw_info=CloneDrawInfo(info ? info->image_info :
10427             (ImageInfo *) NULL,(DrawInfo *) NULL);
10428           if (attribute_flag[0] != 0)
10429             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10430               &geometry,exception);
10431           if (attribute_flag[1] != 0)
10432             geometry.x=argument_list[1].integer_reference;
10433           if (attribute_flag[2] != 0)
10434             geometry.y=argument_list[2].integer_reference;
10435           if (attribute_flag[3] != 0)
10436             (void) QueryColorCompliance(argument_list[3].string_reference,
10437               AllCompliance,&draw_info->fill,exception);
10438           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10439             geometry.x,geometry.y,&target,exception);
10440           if (attribute_flag[4] != 0)
10441             QueryColorCompliance(argument_list[4].string_reference,
10442               AllCompliance,&target,exception);
10443           if (attribute_flag[5] != 0)
10444             image->fuzz=StringToDoubleInterval(
10445               argument_list[5].string_reference,(double) QuantumRange+1.0);
10446           if (attribute_flag[6] != 0)
10447             channel=(ChannelType) argument_list[6].integer_reference;
10448           invert=MagickFalse;
10449           if (attribute_flag[7] != 0)
10450             invert=(MagickBooleanType) argument_list[7].integer_reference;
10451           channel_mask=SetImageChannelMask(image,channel);
10452           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10453             geometry.y,invert,exception);
10454           (void) SetImageChannelMask(image,channel_mask);
10455           draw_info=DestroyDrawInfo(draw_info);
10456           break;
10457         }
10458         case 112:  /* Distort */
10459         {
10460           AV
10461             *av;
10462
10463           double
10464             *coordinates;
10465
10466           DistortImageMethod
10467             method;
10468
10469           size_t
10470             number_coordinates;
10471
10472           VirtualPixelMethod
10473             virtual_pixel;
10474
10475           if (attribute_flag[0] == 0)
10476             break;
10477           method=UndefinedDistortion;
10478           if (attribute_flag[1] != 0)
10479             method=(DistortImageMethod) argument_list[1].integer_reference;
10480           av=(AV *) argument_list[0].array_reference;
10481           number_coordinates=(size_t) av_len(av)+1;
10482           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10483             sizeof(*coordinates));
10484           if (coordinates == (double *) NULL)
10485             {
10486               ThrowPerlException(exception,ResourceLimitFatalError,
10487                 "MemoryAllocationFailed",PackageName);
10488               goto PerlException;
10489             }
10490           for (j=0; j < (ssize_t) number_coordinates; j++)
10491             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10492           virtual_pixel=UndefinedVirtualPixelMethod;
10493           if (attribute_flag[2] != 0)
10494             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10495               argument_list[2].integer_reference,exception);
10496           image=DistortImage(image,method,number_coordinates,coordinates,
10497             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10498             exception);
10499           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10500             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10501               exception);
10502           coordinates=(double *) RelinquishMagickMemory(coordinates);
10503           break;
10504         }
10505         case 113:  /* Clut */
10506         {
10507           PixelInterpolateMethod
10508             method;
10509
10510           if (attribute_flag[0] == 0)
10511             {
10512               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10513                 PackageName);
10514               goto PerlException;
10515             }
10516           method=UndefinedInterpolatePixel;
10517           if (attribute_flag[1] != 0)
10518             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10519           if (attribute_flag[2] != 0)
10520             channel=(ChannelType) argument_list[2].integer_reference;
10521           channel_mask=SetImageChannelMask(image,channel);
10522           (void) ClutImage(image,argument_list[0].image_reference,method,
10523             exception);
10524           (void) SetImageChannelMask(image,channel_mask);
10525           break;
10526         }
10527         case 114:  /* LiquidRescale */
10528         {
10529           if (attribute_flag[0] != 0)
10530             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10531               &geometry,exception);
10532           if (attribute_flag[1] != 0)
10533             geometry.width=argument_list[1].integer_reference;
10534           if (attribute_flag[2] != 0)
10535             geometry.height=argument_list[2].integer_reference;
10536           if (attribute_flag[3] == 0)
10537             argument_list[3].real_reference=1.0;
10538           if (attribute_flag[4] == 0)
10539             argument_list[4].real_reference=0.0;
10540           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10541             argument_list[3].real_reference,argument_list[4].real_reference,
10542             exception);
10543           break;
10544         }
10545         case 115:  /* EncipherImage */
10546         {
10547           (void) EncipherImage(image,argument_list[0].string_reference,
10548             exception);
10549           break;
10550         }
10551         case 116:  /* DecipherImage */
10552         {
10553           (void) DecipherImage(image,argument_list[0].string_reference,
10554             exception);
10555           break;
10556         }
10557         case 117:  /* Deskew */
10558         {
10559           geometry_info.rho=QuantumRange/2.0;
10560           if (attribute_flag[0] != 0)
10561             flags=ParseGeometry(argument_list[0].string_reference,
10562               &geometry_info);
10563           if (attribute_flag[1] != 0)
10564             geometry_info.rho=StringToDoubleInterval(
10565               argument_list[1].string_reference,(double) QuantumRange+1.0);
10566           image=DeskewImage(image,geometry_info.rho,exception);
10567           break;
10568         }
10569         case 118:  /* Remap */
10570         {
10571           QuantizeInfo
10572             *quantize_info;
10573
10574           if (attribute_flag[0] == 0)
10575             {
10576               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10577                 PackageName);
10578               goto PerlException;
10579             }
10580           quantize_info=AcquireQuantizeInfo(info->image_info);
10581           if (attribute_flag[1] != 0)
10582             quantize_info->dither_method=(DitherMethod)
10583               argument_list[1].integer_reference;
10584           (void) RemapImages(quantize_info,image,
10585             argument_list[0].image_reference,exception);
10586           quantize_info=DestroyQuantizeInfo(quantize_info);
10587           break;
10588         }
10589         case 119:  /* SparseColor */
10590         {
10591           AV
10592             *av;
10593
10594           double
10595             *coordinates;
10596
10597           SparseColorMethod
10598             method;
10599
10600           size_t
10601             number_coordinates;
10602
10603           VirtualPixelMethod
10604             virtual_pixel;
10605
10606           if (attribute_flag[0] == 0)
10607             break;
10608           method=UndefinedColorInterpolate;
10609           if (attribute_flag[1] != 0)
10610             method=(SparseColorMethod) argument_list[1].integer_reference;
10611           av=(AV *) argument_list[0].array_reference;
10612           number_coordinates=(size_t) av_len(av)+1;
10613           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10614             sizeof(*coordinates));
10615           if (coordinates == (double *) NULL)
10616             {
10617               ThrowPerlException(exception,ResourceLimitFatalError,
10618                 "MemoryAllocationFailed",PackageName);
10619               goto PerlException;
10620             }
10621           for (j=0; j < (ssize_t) number_coordinates; j++)
10622             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10623           virtual_pixel=UndefinedVirtualPixelMethod;
10624           if (attribute_flag[2] != 0)
10625             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10626               argument_list[2].integer_reference,exception);
10627           if (attribute_flag[3] != 0)
10628             channel=(ChannelType) argument_list[3].integer_reference;
10629           channel_mask=SetImageChannelMask(image,channel);
10630           image=SparseColorImage(image,method,number_coordinates,coordinates,
10631             exception);
10632           if (image != (Image *) NULL)
10633             (void) SetImageChannelMask(image,channel_mask);
10634           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10635             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10636               exception);
10637           coordinates=(double *) RelinquishMagickMemory(coordinates);
10638           break;
10639         }
10640         case 120:  /* Function */
10641         {
10642           AV
10643             *av;
10644
10645           double
10646             *parameters;
10647
10648           MagickFunction
10649             function;
10650
10651           size_t
10652             number_parameters;
10653
10654           VirtualPixelMethod
10655             virtual_pixel;
10656
10657           if (attribute_flag[0] == 0)
10658             break;
10659           function=UndefinedFunction;
10660           if (attribute_flag[1] != 0)
10661             function=(MagickFunction) argument_list[1].integer_reference;
10662           av=(AV *) argument_list[0].array_reference;
10663           number_parameters=(size_t) av_len(av)+1;
10664           parameters=(double *) AcquireQuantumMemory(number_parameters,
10665             sizeof(*parameters));
10666           if (parameters == (double *) NULL)
10667             {
10668               ThrowPerlException(exception,ResourceLimitFatalError,
10669                 "MemoryAllocationFailed",PackageName);
10670               goto PerlException;
10671             }
10672           for (j=0; j < (ssize_t) number_parameters; j++)
10673             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10674           virtual_pixel=UndefinedVirtualPixelMethod;
10675           if (attribute_flag[2] != 0)
10676             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10677               argument_list[2].integer_reference,exception);
10678           (void) FunctionImage(image,function,number_parameters,parameters,
10679             exception);
10680           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10681             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10682               exception);
10683           parameters=(double *) RelinquishMagickMemory(parameters);
10684           break;
10685         }
10686         case 121:  /* SelectiveBlur */
10687         {
10688           if (attribute_flag[0] != 0)
10689             {
10690               flags=ParseGeometry(argument_list[0].string_reference,
10691                 &geometry_info);
10692               if ((flags & SigmaValue) == 0)
10693                 geometry_info.sigma=1.0;
10694               if ((flags & PercentValue) != 0)
10695                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10696             }
10697           if (attribute_flag[1] != 0)
10698             geometry_info.rho=argument_list[1].real_reference;
10699           if (attribute_flag[2] != 0)
10700             geometry_info.sigma=argument_list[2].real_reference;
10701           if (attribute_flag[3] != 0)
10702             geometry_info.xi=argument_list[3].integer_reference;;
10703           if (attribute_flag[5] != 0)
10704             channel=(ChannelType) argument_list[5].integer_reference;
10705           channel_mask=SetImageChannelMask(image,channel);
10706           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10707             geometry_info.xi,exception);
10708           if (image != (Image *) NULL)
10709             (void) SetImageChannelMask(image,channel_mask);
10710           break;
10711         }
10712         case 122:  /* HaldClut */
10713         {
10714           if (attribute_flag[0] == 0)
10715             {
10716               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10717                 PackageName);
10718               goto PerlException;
10719             }
10720           if (attribute_flag[1] != 0)
10721             channel=(ChannelType) argument_list[1].integer_reference;
10722           channel_mask=SetImageChannelMask(image,channel);
10723           (void) HaldClutImage(image,argument_list[0].image_reference,
10724             exception);
10725           (void) SetImageChannelMask(image,channel_mask);
10726           break;
10727         }
10728         case 123:  /* BlueShift */
10729         {
10730           if (attribute_flag[0] != 0)
10731             (void) ParseGeometry(argument_list[0].string_reference,
10732               &geometry_info);
10733           image=BlueShiftImage(image,geometry_info.rho,exception);
10734           break;
10735         }
10736         case 124:  /* ForwardFourierTransformImage */
10737         {
10738           image=ForwardFourierTransformImage(image,
10739             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10740             exception);
10741           break;
10742         }
10743         case 125:  /* InverseFourierTransformImage */
10744         {
10745           image=InverseFourierTransformImage(image,image->next,
10746             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10747             exception);
10748           break;
10749         }
10750         case 126:  /* ColorDecisionList */
10751         {
10752           if (attribute_flag[0] == 0)
10753             argument_list[0].string_reference=(char *) NULL;
10754           (void) ColorDecisionListImage(image,
10755             argument_list[0].string_reference,exception);
10756           break;
10757         }
10758         case 127:  /* AutoGamma */
10759         {
10760           if (attribute_flag[0] != 0)
10761             channel=(ChannelType) argument_list[0].integer_reference;
10762           channel_mask=SetImageChannelMask(image,channel);
10763           (void) AutoGammaImage(image,exception);
10764           (void) SetImageChannelMask(image,channel_mask);
10765           break;
10766         }
10767         case 128:  /* AutoLevel */
10768         {
10769           if (attribute_flag[0] != 0)
10770             channel=(ChannelType) argument_list[0].integer_reference;
10771           channel_mask=SetImageChannelMask(image,channel);
10772           (void) AutoLevelImage(image,exception);
10773           (void) SetImageChannelMask(image,channel_mask);
10774           break;
10775         }
10776         case 129:  /* LevelColors */
10777         {
10778           PixelInfo
10779             black_point,
10780             white_point;
10781
10782           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10783             exception);
10784           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10785             exception);
10786           if (attribute_flag[1] != 0)
10787              (void) QueryColorCompliance(
10788                argument_list[1].string_reference,AllCompliance,&black_point,
10789                exception);
10790           if (attribute_flag[2] != 0)
10791              (void) QueryColorCompliance(
10792                argument_list[2].string_reference,AllCompliance,&white_point,
10793                exception);
10794           if (attribute_flag[3] != 0)
10795             channel=(ChannelType) argument_list[3].integer_reference;
10796           channel_mask=SetImageChannelMask(image,channel);
10797           (void) LevelImageColors(image,&black_point,&white_point,
10798             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10799             exception);
10800           (void) SetImageChannelMask(image,channel_mask);
10801           break;
10802         }
10803         case 130:  /* Clamp */
10804         {
10805           if (attribute_flag[0] != 0)
10806             channel=(ChannelType) argument_list[0].integer_reference;
10807           channel_mask=SetImageChannelMask(image,channel);
10808           (void) ClampImage(image,exception);
10809           (void) SetImageChannelMask(image,channel_mask);
10810           break;
10811         }
10812         case 131:  /* BrightnessContrast */
10813         {
10814           double
10815             brightness,
10816             contrast;
10817
10818           brightness=0.0;
10819           contrast=0.0;
10820           if (attribute_flag[0] != 0)
10821             {
10822               flags=ParseGeometry(argument_list[0].string_reference,
10823                 &geometry_info);
10824               brightness=geometry_info.rho;
10825               if ((flags & SigmaValue) == 0)
10826                 contrast=geometry_info.sigma;
10827             }
10828           if (attribute_flag[1] != 0)
10829             brightness=argument_list[1].real_reference;
10830           if (attribute_flag[2] != 0)
10831             contrast=argument_list[2].real_reference;
10832           if (attribute_flag[4] != 0)
10833             channel=(ChannelType) argument_list[4].integer_reference;
10834           channel_mask=SetImageChannelMask(image,channel);
10835           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10836           (void) SetImageChannelMask(image,channel_mask);
10837           break;
10838         }
10839         case 132:  /* Morphology */
10840         {
10841           KernelInfo
10842             *kernel;
10843
10844           MorphologyMethod
10845             method;
10846
10847           ssize_t
10848             iterations;
10849
10850           if (attribute_flag[0] == 0)
10851             break;
10852           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10853           if (kernel == (KernelInfo *) NULL)
10854             break;
10855           if (attribute_flag[1] != 0)
10856             channel=(ChannelType) argument_list[1].integer_reference;
10857           method=UndefinedMorphology;
10858           if (attribute_flag[2] != 0)
10859             method=argument_list[2].integer_reference;
10860           iterations=1;
10861           if (attribute_flag[3] != 0)
10862             iterations=argument_list[3].integer_reference;
10863           channel_mask=SetImageChannelMask(image,channel);
10864           image=MorphologyImage(image,method,iterations,kernel,exception);
10865           if (image != (Image *) NULL)
10866             (void) SetImageChannelMask(image,channel_mask);
10867           kernel=DestroyKernelInfo(kernel);
10868           break;
10869         }
10870         case 133:  /* Mode */
10871         {
10872           if (attribute_flag[0] != 0)
10873             {
10874               flags=ParseGeometry(argument_list[0].string_reference,
10875                 &geometry_info);
10876               if ((flags & SigmaValue) == 0)
10877                 geometry_info.sigma=1.0;
10878             }
10879           if (attribute_flag[1] != 0)
10880             geometry_info.rho=argument_list[1].real_reference;
10881           if (attribute_flag[2] != 0)
10882             geometry_info.sigma=argument_list[2].real_reference;
10883           if (attribute_flag[3] != 0)
10884             channel=(ChannelType) argument_list[3].integer_reference;
10885           channel_mask=SetImageChannelMask(image,channel);
10886           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10887             (size_t) geometry_info.sigma,exception);
10888           if (image != (Image *) NULL)
10889             (void) SetImageChannelMask(image,channel_mask);
10890           break;
10891         }
10892         case 134:  /* Statistic */
10893         {
10894           StatisticType
10895             statistic;
10896
10897           statistic=UndefinedStatistic;
10898           if (attribute_flag[0] != 0)
10899             {
10900               flags=ParseGeometry(argument_list[0].string_reference,
10901                 &geometry_info);
10902               if ((flags & SigmaValue) == 0)
10903                 geometry_info.sigma=1.0;
10904             }
10905           if (attribute_flag[1] != 0)
10906             geometry_info.rho=argument_list[1].real_reference;
10907           if (attribute_flag[2] != 0)
10908             geometry_info.sigma=argument_list[2].real_reference;
10909           if (attribute_flag[3] != 0)
10910             channel=(ChannelType) argument_list[3].integer_reference;
10911           if (attribute_flag[4] != 0)
10912             statistic=(StatisticType) argument_list[4].integer_reference;
10913           channel_mask=SetImageChannelMask(image,channel);
10914           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10915             (size_t) geometry_info.sigma,exception);
10916           if (image != (Image *) NULL)
10917             (void) SetImageChannelMask(image,channel_mask);
10918           break;
10919         }
10920         case 135:  /* Perceptible */
10921         {
10922           double
10923             epsilon;
10924
10925           epsilon=MagickEpsilon;
10926           if (attribute_flag[0] != 0)
10927             epsilon=argument_list[0].real_reference;
10928           if (attribute_flag[1] != 0)
10929             channel=(ChannelType) argument_list[1].integer_reference;
10930           channel_mask=SetImageChannelMask(image,channel);
10931           (void) PerceptibleImage(image,epsilon,exception);
10932           (void) SetImageChannelMask(image,channel_mask);
10933           break;
10934         }
10935         case 136:  /* Poly */
10936         {
10937           AV
10938             *av;
10939
10940           double
10941             *terms;
10942
10943           size_t
10944             number_terms;
10945
10946           if (attribute_flag[0] == 0)
10947             break;
10948           if (attribute_flag[1] != 0)
10949             channel=(ChannelType) argument_list[1].integer_reference;
10950           av=(AV *) argument_list[0].array_reference;
10951           number_terms=(size_t) av_len(av);
10952           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
10953           if (terms == (double *) NULL)
10954             {
10955               ThrowPerlException(exception,ResourceLimitFatalError,
10956                 "MemoryAllocationFailed",PackageName);
10957               goto PerlException;
10958             }
10959           for (j=0; j < av_len(av); j++)
10960             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
10961           image=PolynomialImage(image,number_terms >> 1,terms,exception);
10962           terms=(double *) RelinquishMagickMemory(terms);
10963           break;
10964         }
10965       }
10966       if (next != (Image *) NULL)
10967         (void) CatchImageException(next);
10968       if (region_image != (Image *) NULL)
10969         {
10970           /*
10971             Composite region.
10972           */ 
10973           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
10974             region_info.x,region_info.y,exception);
10975           (void) status;
10976           (void) CatchImageException(region_image);
10977           image=DestroyImage(image);
10978           image=region_image;
10979         }
10980       if (image != (Image *) NULL)
10981         {
10982           number_images++;
10983           if (next && (next != image))
10984             {
10985               image->next=next->next;
10986               if (image->next != (Image *) NULL)
10987                 image->next->previous=image;
10988               DeleteImageFromRegistry(*pv,next);
10989             }
10990           sv_setiv(*pv,PTR2IV(image));
10991           next=image;
10992         }
10993       if (*pv)
10994         pv++;
10995     }
10996
10997   PerlException:
10998     if (reference_vector)
10999       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11000     InheritPerlException(exception,perl_exception);
11001     exception=DestroyExceptionInfo(exception);
11002     sv_setiv(perl_exception,(IV) number_images);
11003     SvPOK_on(perl_exception);
11004     ST(0)=sv_2mortal(perl_exception);
11005     XSRETURN(1);
11006   }
11007 \f
11008 #
11009 ###############################################################################
11010 #                                                                             #
11011 #                                                                             #
11012 #                                                                             #
11013 #   M o n t a g e                                                             #
11014 #                                                                             #
11015 #                                                                             #
11016 #                                                                             #
11017 ###############################################################################
11018 #
11019 #
11020 void
11021 Montage(ref,...)
11022   Image::Magick ref=NO_INIT
11023   ALIAS:
11024     MontageImage  = 1
11025     montage       = 2
11026     montageimage  = 3
11027   PPCODE:
11028   {
11029     AV
11030       *av;
11031
11032     char
11033       *attribute;
11034
11035     ExceptionInfo
11036       *exception;
11037
11038     HV
11039       *hv;
11040
11041     Image
11042       *image,
11043       *next;
11044
11045     PixelInfo
11046       transparent_color;
11047
11048     MontageInfo
11049       *montage_info;
11050
11051     register ssize_t
11052       i;
11053
11054     ssize_t
11055       sp;
11056
11057     struct PackageInfo
11058       *info;
11059
11060     SV
11061       *av_reference,
11062       *perl_exception,
11063       *reference,
11064       *rv,
11065       *sv;
11066
11067     PERL_UNUSED_VAR(ref);
11068     PERL_UNUSED_VAR(ix);
11069     exception=AcquireExceptionInfo();
11070     perl_exception=newSVpv("",0);
11071     sv=NULL;
11072     attribute=NULL;
11073     if (sv_isobject(ST(0)) == 0)
11074       {
11075         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11076           PackageName);
11077         goto PerlException;
11078       }
11079     reference=SvRV(ST(0));
11080     hv=SvSTASH(reference);
11081     av=newAV();
11082     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11083     SvREFCNT_dec(av);
11084     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11085     if (image == (Image *) NULL)
11086       {
11087         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11088           PackageName);
11089         goto PerlException;
11090       }
11091     /*
11092       Get options.
11093     */
11094     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11095     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11096     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11097       exception);
11098     for (i=2; i < items; i+=2)
11099     {
11100       attribute=(char *) SvPV(ST(i-1),na);
11101       switch (*attribute)
11102       {
11103         case 'B':
11104         case 'b':
11105         {
11106           if (LocaleCompare(attribute,"background") == 0)
11107             {
11108               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11109                 &montage_info->background_color,exception);
11110               for (next=image; next; next=next->next)
11111                 next->background_color=montage_info->background_color;
11112               break;
11113             }
11114           if (LocaleCompare(attribute,"border") == 0)
11115             {
11116               montage_info->border_width=SvIV(ST(i));
11117               break;
11118             }
11119           if (LocaleCompare(attribute,"bordercolor") == 0)
11120             {
11121               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11122                 &montage_info->border_color,exception);
11123               for (next=image; next; next=next->next)
11124                 next->border_color=montage_info->border_color;
11125               break;
11126             }
11127           if (LocaleCompare(attribute,"borderwidth") == 0)
11128             {
11129               montage_info->border_width=SvIV(ST(i));
11130               break;
11131             }
11132           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11133             attribute);
11134           break;
11135         }
11136         case 'C':
11137         case 'c':
11138         {
11139           if (LocaleCompare(attribute,"compose") == 0)
11140             {
11141               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11142                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11143               if (sp < 0)
11144                 {
11145                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11146                     SvPV(ST(i),na));
11147                   break;
11148                 }
11149               for (next=image; next; next=next->next)
11150                 next->compose=(CompositeOperator) sp;
11151               break;
11152             }
11153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11154             attribute);
11155           break;
11156         }
11157         case 'F':
11158         case 'f':
11159         {
11160           if (LocaleCompare(attribute,"fill") == 0)
11161             {
11162               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11163                 &montage_info->fill,exception);
11164               break;
11165             }
11166           if (LocaleCompare(attribute,"font") == 0)
11167             {
11168               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11169               break;
11170             }
11171           if (LocaleCompare(attribute,"frame") == 0)
11172             {
11173               char
11174                 *p;
11175
11176               p=SvPV(ST(i),na);
11177               if (IsGeometry(p) == MagickFalse)
11178                 {
11179                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11180                     p);
11181                   break;
11182                 }
11183               (void) CloneString(&montage_info->frame,p);
11184               if (*p == '\0')
11185                 montage_info->frame=(char *) NULL;
11186               break;
11187             }
11188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11189             attribute);
11190           break;
11191         }
11192         case 'G':
11193         case 'g':
11194         {
11195           if (LocaleCompare(attribute,"geometry") == 0)
11196             {
11197               char
11198                 *p;
11199
11200               p=SvPV(ST(i),na);
11201               if (IsGeometry(p) == MagickFalse)
11202                 {
11203                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11204                     p);
11205                   break;
11206                 }
11207              (void) CloneString(&montage_info->geometry,p);
11208              if (*p == '\0')
11209                montage_info->geometry=(char *) NULL;
11210              break;
11211            }
11212          if (LocaleCompare(attribute,"gravity") == 0)
11213            {
11214              ssize_t
11215                in;
11216
11217              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11218                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11219              if (in < 0)
11220                {
11221                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11222                    SvPV(ST(i),na));
11223                  return;
11224                }
11225              montage_info->gravity=(GravityType) in;
11226              for (next=image; next; next=next->next)
11227                next->gravity=(GravityType) in;
11228              break;
11229            }
11230           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11231             attribute);
11232           break;
11233         }
11234         case 'L':
11235         case 'l':
11236         {
11237           if (LocaleCompare(attribute,"label") == 0)
11238             {
11239               for (next=image; next; next=next->next)
11240                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11241                   info ? info->image_info : (ImageInfo *) NULL,next,
11242                   SvPV(ST(i),na),exception),exception);
11243               break;
11244             }
11245           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11246             attribute);
11247           break;
11248         }
11249         case 'M':
11250         case 'm':
11251         {
11252           if (LocaleCompare(attribute,"mattecolor") == 0)
11253             {
11254               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11255                 &montage_info->matte_color,exception);
11256               for (next=image; next; next=next->next)
11257                 next->matte_color=montage_info->matte_color;
11258               break;
11259             }
11260           if (LocaleCompare(attribute,"mode") == 0)
11261             {
11262               ssize_t
11263                 in;
11264
11265               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11266                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11267               switch (in)
11268               {
11269                 default:
11270                 {
11271                   ThrowPerlException(exception,OptionError,
11272                     "UnrecognizedModeType",SvPV(ST(i),na));
11273                   break;
11274                 }
11275                 case FrameMode:
11276                 {
11277                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11278                   montage_info->shadow=MagickTrue;
11279                   break;
11280                 }
11281                 case UnframeMode:
11282                 {
11283                   montage_info->frame=(char *) NULL;
11284                   montage_info->shadow=MagickFalse;
11285                   montage_info->border_width=0;
11286                   break;
11287                 }
11288                 case ConcatenateMode:
11289                 {
11290                   montage_info->frame=(char *) NULL;
11291                   montage_info->shadow=MagickFalse;
11292                   (void) CloneString(&montage_info->geometry,"+0+0");
11293                   montage_info->border_width=0;
11294                 }
11295               }
11296               break;
11297             }
11298           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11299             attribute);
11300           break;
11301         }
11302         case 'P':
11303         case 'p':
11304         {
11305           if (LocaleCompare(attribute,"pointsize") == 0)
11306             {
11307               montage_info->pointsize=SvIV(ST(i));
11308               break;
11309             }
11310           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11311             attribute);
11312           break;
11313         }
11314         case 'S':
11315         case 's':
11316         {
11317           if (LocaleCompare(attribute,"shadow") == 0)
11318             {
11319               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11320                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11321               if (sp < 0)
11322                 {
11323                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11324                     SvPV(ST(i),na));
11325                   break;
11326                 }
11327              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11328              break;
11329             }
11330           if (LocaleCompare(attribute,"stroke") == 0)
11331             {
11332               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11333                 &montage_info->stroke,exception);
11334               break;
11335             }
11336           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11337             attribute);
11338           break;
11339         }
11340         case 'T':
11341         case 't':
11342         {
11343           if (LocaleCompare(attribute,"texture") == 0)
11344             {
11345               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11346               break;
11347             }
11348           if (LocaleCompare(attribute,"tile") == 0)
11349             {
11350               char *p=SvPV(ST(i),na);
11351               if (IsGeometry(p) == MagickFalse)
11352                 {
11353                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11354                     p);
11355                   break;
11356                 }
11357               (void) CloneString(&montage_info->tile,p);
11358               if (*p == '\0')
11359                 montage_info->tile=(char *) NULL;
11360               break;
11361             }
11362           if (LocaleCompare(attribute,"title") == 0)
11363             {
11364               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11365               break;
11366             }
11367           if (LocaleCompare(attribute,"transparent") == 0)
11368             {
11369               PixelInfo
11370                 transparent_color;
11371
11372               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11373                 &transparent_color,exception);
11374               for (next=image; next; next=next->next)
11375                 (void) TransparentPaintImage(next,&transparent_color,
11376                   TransparentAlpha,MagickFalse,exception);
11377               break;
11378             }
11379           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11380             attribute);
11381           break;
11382         }
11383         default:
11384         {
11385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11386             attribute);
11387           break;
11388         }
11389       }
11390     }
11391     image=MontageImageList(info->image_info,montage_info,image,exception);
11392     montage_info=DestroyMontageInfo(montage_info);
11393     if (image == (Image *) NULL)
11394       goto PerlException;
11395     if (transparent_color.alpha != TransparentAlpha)
11396       for (next=image; next; next=next->next)
11397         (void) TransparentPaintImage(next,&transparent_color,
11398           TransparentAlpha,MagickFalse,exception);
11399     for (  ; image; image=image->next)
11400     {
11401       AddImageToRegistry(sv,image);
11402       rv=newRV(sv);
11403       av_push(av,sv_bless(rv,hv));
11404       SvREFCNT_dec(sv);
11405     }
11406     exception=DestroyExceptionInfo(exception);
11407     ST(0)=av_reference;
11408     SvREFCNT_dec(perl_exception);
11409     XSRETURN(1);
11410
11411   PerlException:
11412     InheritPerlException(exception,perl_exception);
11413     exception=DestroyExceptionInfo(exception);
11414     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11415     SvPOK_on(perl_exception);
11416     ST(0)=sv_2mortal(perl_exception);
11417     XSRETURN(1);
11418   }
11419 \f
11420 #
11421 ###############################################################################
11422 #                                                                             #
11423 #                                                                             #
11424 #                                                                             #
11425 #   M o r p h                                                                 #
11426 #                                                                             #
11427 #                                                                             #
11428 #                                                                             #
11429 ###############################################################################
11430 #
11431 #
11432 void
11433 Morph(ref,...)
11434   Image::Magick ref=NO_INIT
11435   ALIAS:
11436     MorphImage  = 1
11437     morph       = 2
11438     morphimage  = 3
11439   PPCODE:
11440   {
11441     AV
11442       *av;
11443
11444     char
11445       *attribute;
11446
11447     ExceptionInfo
11448       *exception;
11449
11450     HV
11451       *hv;
11452
11453     Image
11454       *image;
11455
11456     register ssize_t
11457       i;
11458
11459     ssize_t
11460       number_frames;
11461
11462     struct PackageInfo
11463       *info;
11464
11465     SV
11466       *av_reference,
11467       *perl_exception,
11468       *reference,
11469       *rv,
11470       *sv;
11471
11472     PERL_UNUSED_VAR(ref);
11473     PERL_UNUSED_VAR(ix);
11474     exception=AcquireExceptionInfo();
11475     perl_exception=newSVpv("",0);
11476     sv=NULL;
11477     av=NULL;
11478     attribute=NULL;
11479     if (sv_isobject(ST(0)) == 0)
11480       {
11481         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11482           PackageName);
11483         goto PerlException;
11484       }
11485     reference=SvRV(ST(0));
11486     hv=SvSTASH(reference);
11487     av=newAV();
11488     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11489     SvREFCNT_dec(av);
11490     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11491     if (image == (Image *) NULL)
11492       {
11493         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11494           PackageName);
11495         goto PerlException;
11496       }
11497     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11498     /*
11499       Get attribute.
11500     */
11501     number_frames=30;
11502     for (i=2; i < items; i+=2)
11503     {
11504       attribute=(char *) SvPV(ST(i-1),na);
11505       switch (*attribute)
11506       {
11507         case 'F':
11508         case 'f':
11509         {
11510           if (LocaleCompare(attribute,"frames") == 0)
11511             {
11512               number_frames=SvIV(ST(i));
11513               break;
11514             }
11515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11516             attribute);
11517           break;
11518         }
11519         default:
11520         {
11521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11522             attribute);
11523           break;
11524         }
11525       }
11526     }
11527     image=MorphImages(image,number_frames,exception);
11528     if (image == (Image *) NULL)
11529       goto PerlException;
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);  /* can't return warning messages */
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 s a i c                                                               #
11557 #                                                                             #
11558 #                                                                             #
11559 #                                                                             #
11560 ###############################################################################
11561 #
11562 #
11563 void
11564 Mosaic(ref)
11565   Image::Magick ref=NO_INIT
11566   ALIAS:
11567     MosaicImage   = 1
11568     mosaic        = 2
11569     mosaicimage   = 3
11570   PPCODE:
11571   {
11572     AV
11573       *av;
11574
11575     ExceptionInfo
11576       *exception;
11577
11578     HV
11579       *hv;
11580
11581     Image
11582       *image;
11583
11584     struct PackageInfo
11585       *info;
11586
11587     SV
11588       *perl_exception,
11589       *reference,
11590       *rv,
11591       *sv;
11592
11593     PERL_UNUSED_VAR(ref);
11594     PERL_UNUSED_VAR(ix);
11595     exception=AcquireExceptionInfo();
11596     perl_exception=newSVpv("",0);
11597     sv=NULL;
11598     if (sv_isobject(ST(0)) == 0)
11599       {
11600         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11601           PackageName);
11602         goto PerlException;
11603       }
11604     reference=SvRV(ST(0));
11605     hv=SvSTASH(reference);
11606     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11607     if (image == (Image *) NULL)
11608       {
11609         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11610           PackageName);
11611         goto PerlException;
11612       }
11613     image=MergeImageLayers(image,MosaicLayer,exception);
11614     /*
11615       Create blessed Perl array for the returned image.
11616     */
11617     av=newAV();
11618     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11619     SvREFCNT_dec(av);
11620     AddImageToRegistry(sv,image);
11621     rv=newRV(sv);
11622     av_push(av,sv_bless(rv,hv));
11623     SvREFCNT_dec(sv);
11624     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11625     (void) CopyMagickString(info->image_info->filename,image->filename,
11626       MaxTextExtent);
11627     SetImageInfo(info->image_info,0,exception);
11628     exception=DestroyExceptionInfo(exception);
11629     SvREFCNT_dec(perl_exception);
11630     XSRETURN(1);
11631
11632   PerlException:
11633     InheritPerlException(exception,perl_exception);
11634     exception=DestroyExceptionInfo(exception);
11635     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11636     SvPOK_on(perl_exception);  /* return messages in string context */
11637     ST(0)=sv_2mortal(perl_exception);
11638     XSRETURN(1);
11639   }
11640 \f
11641 #
11642 ###############################################################################
11643 #                                                                             #
11644 #                                                                             #
11645 #                                                                             #
11646 #   P i n g                                                                   #
11647 #                                                                             #
11648 #                                                                             #
11649 #                                                                             #
11650 ###############################################################################
11651 #
11652 #
11653 void
11654 Ping(ref,...)
11655   Image::Magick ref=NO_INIT
11656   ALIAS:
11657     PingImage  = 1
11658     ping       = 2
11659     pingimage  = 3
11660   PPCODE:
11661   {
11662     AV
11663       *av;
11664
11665     char
11666       **keep,
11667       **list;
11668
11669     ExceptionInfo
11670       *exception;
11671
11672     Image
11673       *image,
11674       *next;
11675
11676     int
11677       n;
11678
11679     MagickBooleanType
11680       status;
11681
11682     register char
11683       **p;
11684
11685     register ssize_t
11686       i;
11687
11688     ssize_t
11689       ac;
11690
11691     STRLEN
11692       *length;
11693
11694     struct PackageInfo
11695       *info,
11696       *package_info;
11697
11698     SV
11699       *perl_exception,
11700       *reference;
11701
11702     size_t
11703       count;
11704
11705     PERL_UNUSED_VAR(ref);
11706     PERL_UNUSED_VAR(ix);
11707     exception=AcquireExceptionInfo();
11708     perl_exception=newSVpv("",0);
11709     package_info=(struct PackageInfo *) NULL;
11710     ac=(items < 2) ? 1 : items-1;
11711     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11712     keep=list;
11713     length=(STRLEN *) NULL;
11714     if (list == (char **) NULL)
11715       {
11716         ThrowPerlException(exception,ResourceLimitError,
11717           "MemoryAllocationFailed",PackageName);
11718         goto PerlException;
11719       }
11720     keep=list;
11721     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11722     if (length == (STRLEN *) NULL)
11723       {
11724         ThrowPerlException(exception,ResourceLimitError,
11725           "MemoryAllocationFailed",PackageName);
11726         goto PerlException;
11727       }
11728     if (sv_isobject(ST(0)) == 0)
11729       {
11730         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11731           PackageName);
11732         goto PerlException;
11733       }
11734     reference=SvRV(ST(0));
11735     if (SvTYPE(reference) != SVt_PVAV)
11736       {
11737         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11738           PackageName);
11739         goto PerlException;
11740       }
11741     av=(AV *) reference;
11742     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11743       exception);
11744     package_info=ClonePackageInfo(info,exception);
11745     n=1;
11746     if (items <= 1)
11747       *list=(char *) (*package_info->image_info->filename ?
11748         package_info->image_info->filename : "XC:black");
11749     else
11750       for (n=0, i=0; i < ac; i++)
11751       {
11752         list[n]=(char *) SvPV(ST(i+1),length[n]);
11753         if ((items >= 3) && strEQcase(list[n],"blob"))
11754           {
11755             void
11756               *blob;
11757
11758             i++;
11759             blob=(void *) (SvPV(ST(i+1),length[n]));
11760             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11761           }
11762         if ((items >= 3) && strEQcase(list[n],"filename"))
11763           continue;
11764         if ((items >= 3) && strEQcase(list[n],"file"))
11765           {
11766             FILE
11767               *file;
11768
11769             PerlIO
11770               *io_info;
11771
11772             i++;
11773             io_info=IoIFP(sv_2io(ST(i+1)));
11774             if (io_info == (PerlIO *) NULL)
11775               {
11776                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11777                   PackageName);
11778                 continue;
11779               }
11780             file=PerlIO_findFILE(io_info);
11781             if (file == (FILE *) NULL)
11782               {
11783                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11784                   PackageName);
11785                 continue;
11786               }
11787             SetImageInfoFile(package_info->image_info,file);
11788           }
11789         if ((items >= 3) && strEQcase(list[n],"magick"))
11790           continue;
11791         n++;
11792       }
11793     list[n]=(char *) NULL;
11794     keep=list;
11795     status=ExpandFilenames(&n,&list);
11796     if (status == MagickFalse)
11797       {
11798         ThrowPerlException(exception,ResourceLimitError,
11799           "MemoryAllocationFailed",PackageName);
11800         goto PerlException;
11801       }
11802     count=0;
11803     for (i=0; i < n; i++)
11804     {
11805       (void) CopyMagickString(package_info->image_info->filename,list[i],
11806         MaxTextExtent);
11807       image=PingImage(package_info->image_info,exception);
11808       if (image == (Image *) NULL)
11809         break;
11810       if ((package_info->image_info->file != (FILE *) NULL) ||
11811           (package_info->image_info->blob != (void *) NULL))
11812         DisassociateImageStream(image);
11813       count+=GetImageListLength(image);
11814       EXTEND(sp,4*count);
11815       for (next=image; next; next=next->next)
11816       {
11817         PUSHs(sv_2mortal(newSViv(next->columns)));
11818         PUSHs(sv_2mortal(newSViv(next->rows)));
11819         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11820         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11821       }
11822       image=DestroyImageList(image);
11823     }
11824     /*
11825       Free resources.
11826     */
11827     for (i=0; i < n; i++)
11828       if (list[i] != (char *) NULL)
11829         for (p=keep; list[i] != *p++; )
11830           if (*p == NULL)
11831             {
11832               list[i]=(char *) RelinquishMagickMemory(list[i]);
11833               break;
11834             }
11835
11836   PerlException:
11837     if (package_info != (struct PackageInfo *) NULL)
11838       DestroyPackageInfo(package_info);
11839     if (list && (list != keep))
11840       list=(char **) RelinquishMagickMemory(list);
11841     if (keep)
11842       keep=(char **) RelinquishMagickMemory(keep);
11843     if (length)
11844       length=(STRLEN *) RelinquishMagickMemory(length);
11845     InheritPerlException(exception,perl_exception);
11846     exception=DestroyExceptionInfo(exception);
11847     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11848   }
11849 \f
11850 #
11851 ###############################################################################
11852 #                                                                             #
11853 #                                                                             #
11854 #                                                                             #
11855 #   P r e v i e w                                                             #
11856 #                                                                             #
11857 #                                                                             #
11858 #                                                                             #
11859 ###############################################################################
11860 #
11861 #
11862 void
11863 Preview(ref,...)
11864   Image::Magick ref=NO_INIT
11865   ALIAS:
11866     PreviewImage = 1
11867     preview      = 2
11868     previewimage = 3
11869   PPCODE:
11870   {
11871     AV
11872       *av;
11873
11874     ExceptionInfo
11875       *exception;
11876
11877     HV
11878       *hv;
11879
11880     Image
11881       *image,
11882       *preview_image;
11883
11884     PreviewType
11885       preview_type;
11886
11887     struct PackageInfo
11888       *info;
11889
11890     SV
11891       *av_reference,
11892       *perl_exception,
11893       *reference,
11894       *rv,
11895       *sv;
11896
11897     PERL_UNUSED_VAR(ref);
11898     PERL_UNUSED_VAR(ix);
11899     exception=AcquireExceptionInfo();
11900     perl_exception=newSVpv("",0);
11901     sv=NULL;
11902     av=NULL;
11903     if (sv_isobject(ST(0)) == 0)
11904       {
11905         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11906           PackageName);
11907         goto PerlException;
11908       }
11909     reference=SvRV(ST(0));
11910     hv=SvSTASH(reference);
11911     av=newAV();
11912     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11913     SvREFCNT_dec(av);
11914     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11915     if (image == (Image *) NULL)
11916       {
11917         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11918           PackageName);
11919         goto PerlException;
11920       }
11921     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11922     preview_type=GammaPreview;
11923     if (items > 1)
11924       preview_type=(PreviewType)
11925         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11926     for ( ; image; image=image->next)
11927     {
11928       preview_image=PreviewImage(image,preview_type,exception);
11929       if (preview_image == (Image *) NULL)
11930         goto PerlException;
11931       AddImageToRegistry(sv,preview_image);
11932       rv=newRV(sv);
11933       av_push(av,sv_bless(rv,hv));
11934       SvREFCNT_dec(sv);
11935     }
11936     exception=DestroyExceptionInfo(exception);
11937     ST(0)=av_reference;
11938     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11939     XSRETURN(1);
11940
11941   PerlException:
11942     InheritPerlException(exception,perl_exception);
11943     exception=DestroyExceptionInfo(exception);
11944     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11945     SvPOK_on(perl_exception);
11946     ST(0)=sv_2mortal(perl_exception);
11947     XSRETURN(1);
11948   }
11949 \f
11950 #
11951 ###############################################################################
11952 #                                                                             #
11953 #                                                                             #
11954 #                                                                             #
11955 #   Q u e r y C o l o r                                                       #
11956 #                                                                             #
11957 #                                                                             #
11958 #                                                                             #
11959 ###############################################################################
11960 #
11961 #
11962 void
11963 QueryColor(ref,...)
11964   Image::Magick ref=NO_INIT
11965   ALIAS:
11966     querycolor = 1
11967   PPCODE:
11968   {
11969     char
11970       *name;
11971
11972     ExceptionInfo
11973       *exception;
11974
11975     PixelInfo
11976       color;
11977
11978     register ssize_t
11979       i;
11980
11981     SV
11982       *perl_exception;
11983
11984     PERL_UNUSED_VAR(ref);
11985     PERL_UNUSED_VAR(ix);
11986     exception=AcquireExceptionInfo();
11987     perl_exception=newSVpv("",0);
11988     if (items == 1)
11989       {
11990         const ColorInfo
11991           **colorlist;
11992
11993         size_t
11994           colors;
11995
11996         colorlist=GetColorInfoList("*",&colors,exception);
11997         EXTEND(sp,colors);
11998         for (i=0; i < (ssize_t) colors; i++)
11999         {
12000           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12001         }
12002         colorlist=(const ColorInfo **)
12003           RelinquishMagickMemory((ColorInfo **) colorlist);
12004         goto PerlException;
12005       }
12006     EXTEND(sp,5*items);
12007     for (i=1; i < items; i++)
12008     {
12009       name=(char *) SvPV(ST(i),na);
12010       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12011         {
12012           PUSHs(&sv_undef);
12013           continue;
12014         }
12015       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12016       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12017       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12018       if (color.colorspace == CMYKColorspace)
12019         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12020       if (color.alpha_trait == BlendPixelTrait)
12021         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12022     }
12023
12024   PerlException:
12025     InheritPerlException(exception,perl_exception);
12026     exception=DestroyExceptionInfo(exception);
12027     SvREFCNT_dec(perl_exception);
12028   }
12029 \f
12030 #
12031 ###############################################################################
12032 #                                                                             #
12033 #                                                                             #
12034 #                                                                             #
12035 #   Q u e r y C o l o r N a m e                                               #
12036 #                                                                             #
12037 #                                                                             #
12038 #                                                                             #
12039 ###############################################################################
12040 #
12041 #
12042 void
12043 QueryColorname(ref,...)
12044   Image::Magick ref=NO_INIT
12045   ALIAS:
12046     querycolorname = 1
12047   PPCODE:
12048   {
12049     AV
12050       *av;
12051
12052     char
12053       message[MaxTextExtent];
12054
12055     ExceptionInfo
12056       *exception;
12057
12058     Image
12059       *image;
12060
12061     PixelInfo
12062       target_color;
12063
12064     register ssize_t
12065       i;
12066
12067     struct PackageInfo
12068       *info;
12069
12070     SV
12071       *perl_exception,
12072       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12073
12074     PERL_UNUSED_VAR(ref);
12075     PERL_UNUSED_VAR(ix);
12076     exception=AcquireExceptionInfo();
12077     perl_exception=newSVpv("",0);
12078     reference=SvRV(ST(0));
12079     av=(AV *) reference;
12080     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12081       exception);
12082     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12083     if (image == (Image *) NULL)
12084       {
12085         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12086           PackageName);
12087         goto PerlException;
12088       }
12089     EXTEND(sp,items);
12090     for (i=1; i < items; i++)
12091     {
12092       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12093         exception);
12094       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12095         exception);
12096       PUSHs(sv_2mortal(newSVpv(message,0)));
12097     }
12098
12099   PerlException:
12100     InheritPerlException(exception,perl_exception);
12101     exception=DestroyExceptionInfo(exception);
12102     SvREFCNT_dec(perl_exception);
12103   }
12104 \f
12105 #
12106 ###############################################################################
12107 #                                                                             #
12108 #                                                                             #
12109 #                                                                             #
12110 #   Q u e r y F o n t                                                         #
12111 #                                                                             #
12112 #                                                                             #
12113 #                                                                             #
12114 ###############################################################################
12115 #
12116 #
12117 void
12118 QueryFont(ref,...)
12119   Image::Magick ref=NO_INIT
12120   ALIAS:
12121     queryfont = 1
12122   PPCODE:
12123   {
12124     char
12125       *name,
12126       message[MaxTextExtent];
12127
12128     ExceptionInfo
12129       *exception;
12130
12131     register ssize_t
12132       i;
12133
12134     SV
12135       *perl_exception;
12136
12137     volatile const TypeInfo
12138       *type_info;
12139
12140     PERL_UNUSED_VAR(ref);
12141     PERL_UNUSED_VAR(ix);
12142     exception=AcquireExceptionInfo();
12143     perl_exception=newSVpv("",0);
12144     if (items == 1)
12145       {
12146         const TypeInfo
12147           **typelist;
12148
12149         size_t
12150           types;
12151
12152         typelist=GetTypeInfoList("*",&types,exception);
12153         EXTEND(sp,types);
12154         for (i=0; i < (ssize_t) types; i++)
12155         {
12156           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12157         }
12158         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12159           typelist);
12160         goto PerlException;
12161       }
12162     EXTEND(sp,10*items);
12163     for (i=1; i < items; i++)
12164     {
12165       name=(char *) SvPV(ST(i),na);
12166       type_info=GetTypeInfo(name,exception);
12167       if (type_info == (TypeInfo *) NULL)
12168         {
12169           PUSHs(&sv_undef);
12170           continue;
12171         }
12172       if (type_info->name == (char *) NULL)
12173         PUSHs(&sv_undef);
12174       else
12175         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12176       if (type_info->description == (char *) NULL)
12177         PUSHs(&sv_undef);
12178       else
12179         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12180       if (type_info->family == (char *) NULL)
12181         PUSHs(&sv_undef);
12182       else
12183         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12184       if (type_info->style == UndefinedStyle)
12185         PUSHs(&sv_undef);
12186       else
12187         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12188           type_info->style),0)));
12189       if (type_info->stretch == UndefinedStretch)
12190         PUSHs(&sv_undef);
12191       else
12192         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12193           type_info->stretch),0)));
12194       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12195         type_info->weight);
12196       PUSHs(sv_2mortal(newSVpv(message,0)));
12197       if (type_info->encoding == (char *) NULL)
12198         PUSHs(&sv_undef);
12199       else
12200         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12201       if (type_info->foundry == (char *) NULL)
12202         PUSHs(&sv_undef);
12203       else
12204         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12205       if (type_info->format == (char *) NULL)
12206         PUSHs(&sv_undef);
12207       else
12208         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12209       if (type_info->metrics == (char *) NULL)
12210         PUSHs(&sv_undef);
12211       else
12212         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12213       if (type_info->glyphs == (char *) NULL)
12214         PUSHs(&sv_undef);
12215       else
12216         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12217     }
12218
12219   PerlException:
12220     InheritPerlException(exception,perl_exception);
12221     exception=DestroyExceptionInfo(exception);
12222     SvREFCNT_dec(perl_exception);
12223   }
12224 \f
12225 #
12226 ###############################################################################
12227 #                                                                             #
12228 #                                                                             #
12229 #                                                                             #
12230 #   Q u e r y F o n t M e t r i c s                                           #
12231 #                                                                             #
12232 #                                                                             #
12233 #                                                                             #
12234 ###############################################################################
12235 #
12236 #
12237 void
12238 QueryFontMetrics(ref,...)
12239   Image::Magick ref=NO_INIT
12240   ALIAS:
12241     queryfontmetrics = 1
12242   PPCODE:
12243   {
12244     AffineMatrix
12245       affine,
12246       current;
12247
12248     AV
12249       *av;
12250
12251     char
12252       *attribute;
12253
12254     double
12255       x,
12256       y;
12257
12258     DrawInfo
12259       *draw_info;
12260
12261     ExceptionInfo
12262       *exception;
12263
12264     GeometryInfo
12265       geometry_info;
12266
12267     Image
12268       *image;
12269
12270     MagickBooleanType
12271       status;
12272
12273     MagickStatusType
12274       flags;
12275
12276     register ssize_t
12277       i;
12278
12279     ssize_t
12280       type;
12281
12282     struct PackageInfo
12283       *info,
12284       *package_info;
12285
12286     SV
12287       *perl_exception,
12288       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12289
12290     TypeMetric
12291       metrics;
12292
12293     PERL_UNUSED_VAR(ref);
12294     PERL_UNUSED_VAR(ix);
12295     exception=AcquireExceptionInfo();
12296     package_info=(struct PackageInfo *) NULL;
12297     perl_exception=newSVpv("",0);
12298     reference=SvRV(ST(0));
12299     av=(AV *) reference;
12300     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12301       exception);
12302     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12303     if (image == (Image *) NULL)
12304       {
12305         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12306           PackageName);
12307         goto PerlException;
12308       }
12309     package_info=ClonePackageInfo(info,exception);
12310     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12311     CloneString(&draw_info->text,"");
12312     current=draw_info->affine;
12313     GetAffineMatrix(&affine);
12314     x=0.0;
12315     y=0.0;
12316     EXTEND(sp,7*items);
12317     for (i=2; i < items; i+=2)
12318     {
12319       attribute=(char *) SvPV(ST(i-1),na);
12320       switch (*attribute)
12321       {
12322         case 'A':
12323         case 'a':
12324         {
12325           if (LocaleCompare(attribute,"antialias") == 0)
12326             {
12327               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12328                 SvPV(ST(i),na));
12329               if (type < 0)
12330                 {
12331                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12332                     SvPV(ST(i),na));
12333                   break;
12334                 }
12335               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12336               break;
12337             }
12338           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12339             attribute);
12340           break;
12341         }
12342         case 'd':
12343         case 'D':
12344         {
12345           if (LocaleCompare(attribute,"density") == 0)
12346             {
12347               CloneString(&draw_info->density,SvPV(ST(i),na));
12348               break;
12349             }
12350           if (LocaleCompare(attribute,"direction") == 0)
12351             {
12352               draw_info->direction=(DirectionType) ParseCommandOption(
12353                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12354               break;
12355             }
12356           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12357             attribute);
12358           break;
12359         }
12360         case 'e':
12361         case 'E':
12362         {
12363           if (LocaleCompare(attribute,"encoding") == 0)
12364             {
12365               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12366               break;
12367             }
12368           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12369             attribute);
12370           break;
12371         }
12372         case 'f':
12373         case 'F':
12374         {
12375           if (LocaleCompare(attribute,"family") == 0)
12376             {
12377               CloneString(&draw_info->family,SvPV(ST(i),na));
12378               break;
12379             }
12380           if (LocaleCompare(attribute,"fill") == 0)
12381             {
12382               if (info)
12383                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12384                   &draw_info->fill,exception);
12385               break;
12386             }
12387           if (LocaleCompare(attribute,"font") == 0)
12388             {
12389               CloneString(&draw_info->font,SvPV(ST(i),na));
12390               break;
12391             }
12392           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12393             attribute);
12394           break;
12395         }
12396         case 'g':
12397         case 'G':
12398         {
12399           if (LocaleCompare(attribute,"geometry") == 0)
12400             {
12401               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12402               break;
12403             }
12404           if (LocaleCompare(attribute,"gravity") == 0)
12405             {
12406               draw_info->gravity=(GravityType) ParseCommandOption(
12407                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12408               break;
12409             }
12410           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12411             attribute);
12412           break;
12413         }
12414         case 'i':
12415         case 'I':
12416         {
12417           if (LocaleCompare(attribute,"interline-spacing") == 0)
12418             {
12419               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12420               draw_info->interline_spacing=geometry_info.rho;
12421               break;
12422             }
12423           if (LocaleCompare(attribute,"interword-spacing") == 0)
12424             {
12425               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12426               draw_info->interword_spacing=geometry_info.rho;
12427               break;
12428             }
12429           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12430             attribute);
12431           break;
12432         }
12433         case 'k':
12434         case 'K':
12435         {
12436           if (LocaleCompare(attribute,"kerning") == 0)
12437             {
12438               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12439               draw_info->kerning=geometry_info.rho;
12440               break;
12441             }
12442           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12443             attribute);
12444           break;
12445         }
12446         case 'p':
12447         case 'P':
12448         {
12449           if (LocaleCompare(attribute,"pointsize") == 0)
12450             {
12451               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12452               draw_info->pointsize=geometry_info.rho;
12453               break;
12454             }
12455           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12456             attribute);
12457           break;
12458         }
12459         case 'r':
12460         case 'R':
12461         {
12462           if (LocaleCompare(attribute,"rotate") == 0)
12463             {
12464               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12465               affine.rx=geometry_info.rho;
12466               affine.ry=geometry_info.sigma;
12467               if ((flags & SigmaValue) == 0)
12468                 affine.ry=affine.rx;
12469               break;
12470             }
12471           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12472             attribute);
12473           break;
12474         }
12475         case 's':
12476         case 'S':
12477         {
12478           if (LocaleCompare(attribute,"scale") == 0)
12479             {
12480               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12481               affine.sx=geometry_info.rho;
12482               affine.sy=geometry_info.sigma;
12483               if ((flags & SigmaValue) == 0)
12484                 affine.sy=affine.sx;
12485               break;
12486             }
12487           if (LocaleCompare(attribute,"skew") == 0)
12488             {
12489               double
12490                 x_angle,
12491                 y_angle;
12492
12493               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12494               x_angle=geometry_info.rho;
12495               y_angle=geometry_info.sigma;
12496               if ((flags & SigmaValue) == 0)
12497                 y_angle=x_angle;
12498               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12499               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12500               break;
12501             }
12502           if (LocaleCompare(attribute,"stroke") == 0)
12503             {
12504               if (info)
12505                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12506                   &draw_info->stroke,exception);
12507               break;
12508             }
12509           if (LocaleCompare(attribute,"style") == 0)
12510             {
12511               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12512                 SvPV(ST(i),na));
12513               if (type < 0)
12514                 {
12515                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12516                     SvPV(ST(i),na));
12517                   break;
12518                 }
12519               draw_info->style=(StyleType) type;
12520               break;
12521             }
12522           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12523             attribute);
12524           break;
12525         }
12526         case 't':
12527         case 'T':
12528         {
12529           if (LocaleCompare(attribute,"text") == 0)
12530             {
12531               CloneString(&draw_info->text,SvPV(ST(i),na));
12532               break;
12533             }
12534           if (LocaleCompare(attribute,"translate") == 0)
12535             {
12536               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12537               affine.tx=geometry_info.rho;
12538               affine.ty=geometry_info.sigma;
12539               if ((flags & SigmaValue) == 0)
12540                 affine.ty=affine.tx;
12541               break;
12542             }
12543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12544             attribute);
12545           break;
12546         }
12547         case 'w':
12548         case 'W':
12549         {
12550           if (LocaleCompare(attribute,"weight") == 0)
12551             {
12552               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12553               draw_info->weight=(size_t) geometry_info.rho;
12554               break;
12555             }
12556           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12557             attribute);
12558           break;
12559         }
12560         case 'x':
12561         case 'X':
12562         {
12563           if (LocaleCompare(attribute,"x") == 0)
12564             {
12565               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12566               x=geometry_info.rho;
12567               break;
12568             }
12569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12570             attribute);
12571           break;
12572         }
12573         case 'y':
12574         case 'Y':
12575         {
12576           if (LocaleCompare(attribute,"y") == 0)
12577             {
12578               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12579               y=geometry_info.rho;
12580               break;
12581             }
12582           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12583             attribute);
12584           break;
12585         }
12586         default:
12587         {
12588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12589             attribute);
12590           break;
12591         }
12592       }
12593     }
12594     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12595     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12596     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12597     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12598     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12599     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12600     if (draw_info->geometry == (char *) NULL)
12601       {
12602         draw_info->geometry=AcquireString((char *) NULL);
12603         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12604           "%.15g,%.15g",x,y);
12605       }
12606     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12607     (void) CatchImageException(image);
12608     if (status == MagickFalse)
12609       PUSHs(&sv_undef);
12610     else
12611       {
12612         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12613         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12614         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12615         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12616         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12617         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12618         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12619         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12620         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12621         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12622         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12623         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12624         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12625       }
12626     draw_info=DestroyDrawInfo(draw_info);
12627
12628   PerlException:
12629     if (package_info != (struct PackageInfo *) NULL)
12630       DestroyPackageInfo(package_info);
12631     InheritPerlException(exception,perl_exception);
12632     exception=DestroyExceptionInfo(exception);
12633     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12634   }
12635 \f
12636 #
12637 ###############################################################################
12638 #                                                                             #
12639 #                                                                             #
12640 #                                                                             #
12641 #   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                         #
12642 #                                                                             #
12643 #                                                                             #
12644 #                                                                             #
12645 ###############################################################################
12646 #
12647 #
12648 void
12649 QueryMultilineFontMetrics(ref,...)
12650   Image::Magick ref=NO_INIT
12651   ALIAS:
12652     querymultilinefontmetrics = 1
12653   PPCODE:
12654   {
12655     AffineMatrix
12656       affine,
12657       current;
12658
12659     AV
12660       *av;
12661
12662     char
12663       *attribute;
12664
12665     double
12666       x,
12667       y;
12668
12669     DrawInfo
12670       *draw_info;
12671
12672     ExceptionInfo
12673       *exception;
12674
12675     GeometryInfo
12676       geometry_info;
12677
12678     Image
12679       *image;
12680
12681     MagickBooleanType
12682       status;
12683
12684     MagickStatusType
12685       flags;
12686
12687     register ssize_t
12688       i;
12689
12690     ssize_t
12691       type;
12692
12693     struct PackageInfo
12694       *info,
12695       *package_info;
12696
12697     SV
12698       *perl_exception,
12699       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12700
12701     TypeMetric
12702       metrics;
12703
12704     PERL_UNUSED_VAR(ref);
12705     PERL_UNUSED_VAR(ix);
12706     exception=AcquireExceptionInfo();
12707     package_info=(struct PackageInfo *) NULL;
12708     perl_exception=newSVpv("",0);
12709     reference=SvRV(ST(0));
12710     av=(AV *) reference;
12711     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12712       exception);
12713     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12714     if (image == (Image *) NULL)
12715       {
12716         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12717           PackageName);
12718         goto PerlException;
12719       }
12720     package_info=ClonePackageInfo(info,exception);
12721     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12722     CloneString(&draw_info->text,"");
12723     current=draw_info->affine;
12724     GetAffineMatrix(&affine);
12725     x=0.0;
12726     y=0.0;
12727     EXTEND(sp,7*items);
12728     for (i=2; i < items; i+=2)
12729     {
12730       attribute=(char *) SvPV(ST(i-1),na);
12731       switch (*attribute)
12732       {
12733         case 'A':
12734         case 'a':
12735         {
12736           if (LocaleCompare(attribute,"antialias") == 0)
12737             {
12738               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12739                 SvPV(ST(i),na));
12740               if (type < 0)
12741                 {
12742                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12743                     SvPV(ST(i),na));
12744                   break;
12745                 }
12746               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12747               break;
12748             }
12749           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12750             attribute);
12751           break;
12752         }
12753         case 'd':
12754         case 'D':
12755         {
12756           if (LocaleCompare(attribute,"density") == 0)
12757             {
12758               CloneString(&draw_info->density,SvPV(ST(i),na));
12759               break;
12760             }
12761           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12762             attribute);
12763           break;
12764         }
12765         case 'e':
12766         case 'E':
12767         {
12768           if (LocaleCompare(attribute,"encoding") == 0)
12769             {
12770               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12771               break;
12772             }
12773           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12774             attribute);
12775           break;
12776         }
12777         case 'f':
12778         case 'F':
12779         {
12780           if (LocaleCompare(attribute,"family") == 0)
12781             {
12782               CloneString(&draw_info->family,SvPV(ST(i),na));
12783               break;
12784             }
12785           if (LocaleCompare(attribute,"fill") == 0)
12786             {
12787               if (info)
12788                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12789                   &draw_info->fill,exception);
12790               break;
12791             }
12792           if (LocaleCompare(attribute,"font") == 0)
12793             {
12794               CloneString(&draw_info->font,SvPV(ST(i),na));
12795               break;
12796             }
12797           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12798             attribute);
12799           break;
12800         }
12801         case 'g':
12802         case 'G':
12803         {
12804           if (LocaleCompare(attribute,"geometry") == 0)
12805             {
12806               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12807               break;
12808             }
12809           if (LocaleCompare(attribute,"gravity") == 0)
12810             {
12811               draw_info->gravity=(GravityType) ParseCommandOption(
12812                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12813               break;
12814             }
12815           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12816             attribute);
12817           break;
12818         }
12819         case 'p':
12820         case 'P':
12821         {
12822           if (LocaleCompare(attribute,"pointsize") == 0)
12823             {
12824               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12825               draw_info->pointsize=geometry_info.rho;
12826               break;
12827             }
12828           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12829             attribute);
12830           break;
12831         }
12832         case 'r':
12833         case 'R':
12834         {
12835           if (LocaleCompare(attribute,"rotate") == 0)
12836             {
12837               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12838               affine.rx=geometry_info.rho;
12839               affine.ry=geometry_info.sigma;
12840               if ((flags & SigmaValue) == 0)
12841                 affine.ry=affine.rx;
12842               break;
12843             }
12844           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12845             attribute);
12846           break;
12847         }
12848         case 's':
12849         case 'S':
12850         {
12851           if (LocaleCompare(attribute,"scale") == 0)
12852             {
12853               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12854               affine.sx=geometry_info.rho;
12855               affine.sy=geometry_info.sigma;
12856               if ((flags & SigmaValue) == 0)
12857                 affine.sy=affine.sx;
12858               break;
12859             }
12860           if (LocaleCompare(attribute,"skew") == 0)
12861             {
12862               double
12863                 x_angle,
12864                 y_angle;
12865
12866               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12867               x_angle=geometry_info.rho;
12868               y_angle=geometry_info.sigma;
12869               if ((flags & SigmaValue) == 0)
12870                 y_angle=x_angle;
12871               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12872               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12873               break;
12874             }
12875           if (LocaleCompare(attribute,"stroke") == 0)
12876             {
12877               if (info)
12878                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12879                   &draw_info->stroke,exception);
12880               break;
12881             }
12882           if (LocaleCompare(attribute,"style") == 0)
12883             {
12884               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12885                 SvPV(ST(i),na));
12886               if (type < 0)
12887                 {
12888                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12889                     SvPV(ST(i),na));
12890                   break;
12891                 }
12892               draw_info->style=(StyleType) type;
12893               break;
12894             }
12895           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12896             attribute);
12897           break;
12898         }
12899         case 't':
12900         case 'T':
12901         {
12902           if (LocaleCompare(attribute,"text") == 0)
12903             {
12904               CloneString(&draw_info->text,SvPV(ST(i),na));
12905               break;
12906             }
12907           if (LocaleCompare(attribute,"translate") == 0)
12908             {
12909               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12910               affine.tx=geometry_info.rho;
12911               affine.ty=geometry_info.sigma;
12912               if ((flags & SigmaValue) == 0)
12913                 affine.ty=affine.tx;
12914               break;
12915             }
12916           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12917             attribute);
12918           break;
12919         }
12920         case 'w':
12921         case 'W':
12922         {
12923           if (LocaleCompare(attribute,"weight") == 0)
12924             {
12925               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12926               draw_info->weight=(size_t) geometry_info.rho;
12927               break;
12928             }
12929           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12930             attribute);
12931           break;
12932         }
12933         case 'x':
12934         case 'X':
12935         {
12936           if (LocaleCompare(attribute,"x") == 0)
12937             {
12938               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12939               x=geometry_info.rho;
12940               break;
12941             }
12942           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12943             attribute);
12944           break;
12945         }
12946         case 'y':
12947         case 'Y':
12948         {
12949           if (LocaleCompare(attribute,"y") == 0)
12950             {
12951               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12952               y=geometry_info.rho;
12953               break;
12954             }
12955           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12956             attribute);
12957           break;
12958         }
12959         default:
12960         {
12961           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12962             attribute);
12963           break;
12964         }
12965       }
12966     }
12967     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12968     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12969     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12970     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12971     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12972     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12973     if (draw_info->geometry == (char *) NULL)
12974       {
12975         draw_info->geometry=AcquireString((char *) NULL);
12976         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12977           "%.15g,%.15g",x,y);
12978       }
12979     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12980     (void) CatchException(exception);
12981     if (status == MagickFalse)
12982       PUSHs(&sv_undef);
12983     else
12984       {
12985         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12986         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12987         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12988         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12989         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12990         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12991         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12992         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12993         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12994         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12995         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12996         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12997         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12998       }
12999     draw_info=DestroyDrawInfo(draw_info);
13000
13001   PerlException:
13002     if (package_info != (struct PackageInfo *) NULL)
13003       DestroyPackageInfo(package_info);
13004     InheritPerlException(exception,perl_exception);
13005     exception=DestroyExceptionInfo(exception);
13006     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13007   }
13008 \f
13009 #
13010 ###############################################################################
13011 #                                                                             #
13012 #                                                                             #
13013 #                                                                             #
13014 #   Q u e r y F o r m a t                                                     #
13015 #                                                                             #
13016 #                                                                             #
13017 #                                                                             #
13018 ###############################################################################
13019 #
13020 #
13021 void
13022 QueryFormat(ref,...)
13023   Image::Magick ref=NO_INIT
13024   ALIAS:
13025     queryformat = 1
13026   PPCODE:
13027   {
13028     char
13029       *name;
13030
13031     ExceptionInfo
13032       *exception;
13033
13034     register ssize_t
13035       i;
13036
13037     SV
13038       *perl_exception;
13039
13040     volatile const MagickInfo
13041       *magick_info;
13042
13043     PERL_UNUSED_VAR(ref);
13044     PERL_UNUSED_VAR(ix);
13045     exception=AcquireExceptionInfo();
13046     perl_exception=newSVpv("",0);
13047     if (items == 1)
13048       {
13049         char
13050           format[MaxTextExtent];
13051
13052         const MagickInfo
13053           **format_list;
13054
13055         size_t
13056           types;
13057
13058         format_list=GetMagickInfoList("*",&types,exception);
13059         EXTEND(sp,types);
13060         for (i=0; i < (ssize_t) types; i++)
13061         {
13062           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13063           LocaleLower(format);
13064           PUSHs(sv_2mortal(newSVpv(format,0)));
13065         }
13066         format_list=(const MagickInfo **)
13067           RelinquishMagickMemory((MagickInfo *) format_list);
13068         goto PerlException;
13069       }
13070     EXTEND(sp,8*items);
13071     for (i=1; i < items; i++)
13072     {
13073       name=(char *) SvPV(ST(i),na);
13074       magick_info=GetMagickInfo(name,exception);
13075       if (magick_info == (const MagickInfo *) NULL)
13076         {
13077           PUSHs(&sv_undef);
13078           continue;
13079         }
13080       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13081       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13082       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13083       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13084       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13085       if (magick_info->description == (char *) NULL)
13086         PUSHs(&sv_undef);
13087       else
13088         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13089       if (magick_info->module == (char *) NULL)
13090         PUSHs(&sv_undef);
13091       else
13092         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13093     }
13094
13095   PerlException:
13096     InheritPerlException(exception,perl_exception);
13097     exception=DestroyExceptionInfo(exception);
13098     SvREFCNT_dec(perl_exception);
13099   }
13100 \f
13101 #
13102 ###############################################################################
13103 #                                                                             #
13104 #                                                                             #
13105 #                                                                             #
13106 #   Q u e r y O p t i o n                                                     #
13107 #                                                                             #
13108 #                                                                             #
13109 #                                                                             #
13110 ###############################################################################
13111 #
13112 #
13113 void
13114 QueryOption(ref,...)
13115   Image::Magick ref=NO_INIT
13116   ALIAS:
13117     queryoption = 1
13118   PPCODE:
13119   {
13120     char
13121       **options;
13122
13123     ExceptionInfo
13124       *exception;
13125
13126     register ssize_t
13127       i;
13128
13129     ssize_t
13130       j,
13131       option;
13132
13133     SV
13134       *perl_exception;
13135
13136     PERL_UNUSED_VAR(ref);
13137     PERL_UNUSED_VAR(ix);
13138     exception=AcquireExceptionInfo();
13139     perl_exception=newSVpv("",0);
13140     EXTEND(sp,8*items);
13141     for (i=1; i < items; i++)
13142     {
13143       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13144         SvPV(ST(i),na));
13145       options=GetCommandOptions((CommandOption) option);
13146       if (options == (char **) NULL)
13147         PUSHs(&sv_undef);
13148       else
13149         {
13150           for (j=0; options[j] != (char *) NULL; j++)
13151             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13152           options=DestroyStringList(options);
13153         }
13154     }
13155
13156     InheritPerlException(exception,perl_exception);
13157     exception=DestroyExceptionInfo(exception);
13158     SvREFCNT_dec(perl_exception);
13159   }
13160 \f
13161 #
13162 ###############################################################################
13163 #                                                                             #
13164 #                                                                             #
13165 #                                                                             #
13166 #   R e a d                                                                   #
13167 #                                                                             #
13168 #                                                                             #
13169 #                                                                             #
13170 ###############################################################################
13171 #
13172 #
13173 void
13174 Read(ref,...)
13175   Image::Magick ref=NO_INIT
13176   ALIAS:
13177     ReadImage  = 1
13178     read       = 2
13179     readimage  = 3
13180   PPCODE:
13181   {
13182     AV
13183       *av;
13184
13185     char
13186       **keep,
13187       **list;
13188
13189     ExceptionInfo
13190       *exception;
13191
13192     HV
13193       *hv;
13194
13195     Image
13196       *image;
13197
13198     int
13199       n;
13200
13201     MagickBooleanType
13202       status;
13203
13204     register char
13205       **p;
13206
13207     register ssize_t
13208       i;
13209
13210     ssize_t
13211       ac,
13212       number_images;
13213
13214     STRLEN
13215       *length;
13216
13217     struct PackageInfo
13218       *info,
13219       *package_info;
13220
13221     SV
13222       *perl_exception,  /* Perl variable for storing messages */
13223       *reference,
13224       *rv,
13225       *sv;
13226
13227     PERL_UNUSED_VAR(ref);
13228     PERL_UNUSED_VAR(ix);
13229     exception=AcquireExceptionInfo();
13230     perl_exception=newSVpv("",0);
13231     sv=NULL;
13232     package_info=(struct PackageInfo *) NULL;
13233     number_images=0;
13234     ac=(items < 2) ? 1 : items-1;
13235     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13236     keep=list;
13237     length=(STRLEN *) NULL;
13238     if (list == (char **) NULL)
13239       {
13240         ThrowPerlException(exception,ResourceLimitError,
13241           "MemoryAllocationFailed",PackageName);
13242         goto PerlException;
13243       }
13244     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13245     if (length == (STRLEN *) NULL)
13246       {
13247         ThrowPerlException(exception,ResourceLimitError,
13248           "MemoryAllocationFailed",PackageName);
13249         goto PerlException;
13250       }
13251     if (sv_isobject(ST(0)) == 0)
13252       {
13253         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13254           PackageName);
13255         goto PerlException;
13256       }
13257     reference=SvRV(ST(0));
13258     hv=SvSTASH(reference);
13259     if (SvTYPE(reference) != SVt_PVAV)
13260       {
13261         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13262           PackageName);
13263         goto PerlException;
13264       }
13265     av=(AV *) reference;
13266     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13267       exception);
13268     package_info=ClonePackageInfo(info,exception);
13269     n=1;
13270     if (items <= 1)
13271       *list=(char *) (*package_info->image_info->filename ?
13272         package_info->image_info->filename : "XC:black");
13273     else
13274       for (n=0, i=0; i < ac; i++)
13275       {
13276         list[n]=(char *) SvPV(ST(i+1),length[n]);
13277         if ((items >= 3) && strEQcase(list[n],"blob"))
13278           {
13279             void
13280               *blob;
13281
13282             i++;
13283             blob=(void *) (SvPV(ST(i+1),length[n]));
13284             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13285           }
13286         if ((items >= 3) && strEQcase(list[n],"filename"))
13287           continue;
13288         if ((items >= 3) && strEQcase(list[n],"file"))
13289           {
13290             FILE
13291               *file;
13292
13293             PerlIO
13294               *io_info;
13295
13296             i++;
13297             io_info=IoIFP(sv_2io(ST(i+1)));
13298             if (io_info == (PerlIO *) NULL)
13299               {
13300                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13301                   PackageName);
13302                 continue;
13303               }
13304             file=PerlIO_findFILE(io_info);
13305             if (file == (FILE *) NULL)
13306               {
13307                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13308                   PackageName);
13309                 continue;
13310               }
13311             SetImageInfoFile(package_info->image_info,file);
13312           }
13313         if ((items >= 3) && strEQcase(list[n],"magick"))
13314           continue;
13315         n++;
13316       }
13317     list[n]=(char *) NULL;
13318     keep=list;
13319     status=ExpandFilenames(&n,&list);
13320     if (status == MagickFalse)
13321       {
13322         ThrowPerlException(exception,ResourceLimitError,
13323           "MemoryAllocationFailed",PackageName);
13324         goto PerlException;
13325       }
13326     number_images=0;
13327     for (i=0; i < n; i++)
13328     {
13329       if ((package_info->image_info->file == (FILE *) NULL) &&
13330           (package_info->image_info->blob == (void *) NULL))
13331         image=ReadImages(package_info->image_info,list[i],exception);
13332       else
13333         {
13334           image=ReadImages(package_info->image_info,
13335             package_info->image_info->filename,exception);
13336           if (image != (Image *) NULL)
13337             DisassociateImageStream(image);
13338         }
13339       if (image == (Image *) NULL)
13340         break;
13341       for ( ; image; image=image->next)
13342       {
13343         AddImageToRegistry(sv,image);
13344         rv=newRV(sv);
13345         av_push(av,sv_bless(rv,hv));
13346         SvREFCNT_dec(sv);
13347         number_images++;
13348       }
13349     }
13350     /*
13351       Free resources.
13352     */
13353     for (i=0; i < n; i++)
13354       if (list[i] != (char *) NULL)
13355         for (p=keep; list[i] != *p++; )
13356           if (*p == (char *) NULL)
13357             {
13358               list[i]=(char *) RelinquishMagickMemory(list[i]);
13359               break;
13360             }
13361
13362   PerlException:
13363     if (package_info != (struct PackageInfo *) NULL)
13364       DestroyPackageInfo(package_info);
13365     if (list && (list != keep))
13366       list=(char **) RelinquishMagickMemory(list);
13367     if (keep)
13368       keep=(char **) RelinquishMagickMemory(keep);
13369     if (length)
13370       length=(STRLEN *) RelinquishMagickMemory(length);
13371     InheritPerlException(exception,perl_exception);
13372     exception=DestroyExceptionInfo(exception);
13373     sv_setiv(perl_exception,(IV) number_images);
13374     SvPOK_on(perl_exception);
13375     ST(0)=sv_2mortal(perl_exception);
13376     XSRETURN(1);
13377   }
13378 \f
13379 #
13380 ###############################################################################
13381 #                                                                             #
13382 #                                                                             #
13383 #                                                                             #
13384 #   R e m o t e                                                               #
13385 #                                                                             #
13386 #                                                                             #
13387 #                                                                             #
13388 ###############################################################################
13389 #
13390 #
13391 void
13392 Remote(ref,...)
13393   Image::Magick ref=NO_INIT
13394   ALIAS:
13395     RemoteCommand  = 1
13396     remote         = 2
13397     remoteCommand  = 3
13398   PPCODE:
13399   {
13400     AV
13401       *av;
13402
13403     ExceptionInfo
13404       *exception;
13405
13406     register ssize_t
13407       i;
13408
13409     SV
13410       *perl_exception,
13411       *reference;
13412
13413     struct PackageInfo
13414       *info;
13415
13416     PERL_UNUSED_VAR(ref);
13417     PERL_UNUSED_VAR(ix);
13418     exception=AcquireExceptionInfo();
13419     perl_exception=newSVpv("",0);
13420     reference=SvRV(ST(0));
13421     av=(AV *) reference;
13422     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13423       exception);
13424     for (i=1; i < items; i++)
13425       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13426         SvPV(ST(i),na),exception);
13427     InheritPerlException(exception,perl_exception);
13428     exception=DestroyExceptionInfo(exception);
13429     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13430   }
13431 \f
13432 #
13433 ###############################################################################
13434 #                                                                             #
13435 #                                                                             #
13436 #                                                                             #
13437 #   S e t                                                                     #
13438 #                                                                             #
13439 #                                                                             #
13440 #                                                                             #
13441 ###############################################################################
13442 #
13443 #
13444 void
13445 Set(ref,...)
13446   Image::Magick ref=NO_INIT
13447   ALIAS:
13448     SetAttributes  = 1
13449     SetAttribute   = 2
13450     set            = 3
13451     setattributes  = 4
13452     setattribute   = 5
13453   PPCODE:
13454   {
13455     ExceptionInfo
13456       *exception;
13457
13458     Image
13459       *image;
13460
13461     register ssize_t
13462       i;
13463
13464     struct PackageInfo
13465       *info;
13466
13467     SV
13468       *perl_exception,
13469       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13470
13471     PERL_UNUSED_VAR(ref);
13472     PERL_UNUSED_VAR(ix);
13473     exception=AcquireExceptionInfo();
13474     perl_exception=newSVpv("",0);
13475     if (sv_isobject(ST(0)) == 0)
13476       {
13477         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13478           PackageName);
13479         goto PerlException;
13480       }
13481     reference=SvRV(ST(0));
13482     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13483     if (items == 2)
13484       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13485     else
13486       for (i=2; i < items; i+=2)
13487         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13488
13489   PerlException:
13490     InheritPerlException(exception,perl_exception);
13491     exception=DestroyExceptionInfo(exception);
13492     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13493     SvPOK_on(perl_exception);
13494     ST(0)=sv_2mortal(perl_exception);
13495     XSRETURN(1);
13496   }
13497 \f
13498 #
13499 ###############################################################################
13500 #                                                                             #
13501 #                                                                             #
13502 #                                                                             #
13503 #   S e t P i x e l                                                           #
13504 #                                                                             #
13505 #                                                                             #
13506 #                                                                             #
13507 ###############################################################################
13508 #
13509 #
13510 void
13511 SetPixel(ref,...)
13512   Image::Magick ref=NO_INIT
13513   ALIAS:
13514     setpixel = 1
13515     setPixel = 2
13516   PPCODE:
13517   {
13518     AV
13519       *av;
13520
13521     char
13522       *attribute;
13523
13524     ChannelType
13525       channel,
13526       channel_mask;
13527
13528     ExceptionInfo
13529       *exception;
13530
13531     Image
13532       *image;
13533
13534     MagickBooleanType
13535       normalize;
13536
13537     RectangleInfo
13538       region;
13539
13540     register ssize_t
13541       i;
13542
13543     register Quantum
13544       *q;
13545
13546     ssize_t
13547       option;
13548
13549     struct PackageInfo
13550       *info;
13551
13552     SV
13553       *perl_exception,
13554       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13555
13556     PERL_UNUSED_VAR(ref);
13557     PERL_UNUSED_VAR(ix);
13558     exception=AcquireExceptionInfo();
13559     perl_exception=newSVpv("",0);
13560     reference=SvRV(ST(0));
13561     av=(AV *) reference;
13562     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13563       exception);
13564     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13565     if (image == (Image *) NULL)
13566       {
13567         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13568           PackageName);
13569         goto PerlException;
13570       }
13571     av=(AV *) NULL;
13572     normalize=MagickTrue;
13573     region.x=0;
13574     region.y=0;
13575     region.width=image->columns;
13576     region.height=1;
13577     if (items == 1)
13578       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13579     channel=DefaultChannels;
13580     for (i=2; i < items; i+=2)
13581     {
13582       attribute=(char *) SvPV(ST(i-1),na);
13583       switch (*attribute)
13584       {
13585         case 'C':
13586         case 'c':
13587         {
13588           if (LocaleCompare(attribute,"channel") == 0)
13589             {
13590               ssize_t
13591                 option;
13592
13593               option=ParseChannelOption(SvPV(ST(i),na));
13594               if (option < 0)
13595                 {
13596                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13597                     SvPV(ST(i),na));
13598                   return;
13599                 }
13600               channel=(ChannelType) option;
13601               break;
13602             }
13603           if (LocaleCompare(attribute,"color") == 0)
13604             {
13605               if (SvTYPE(ST(i)) != SVt_RV)
13606                 {
13607                   char
13608                     message[MaxTextExtent];
13609
13610                   (void) FormatLocaleString(message,MaxTextExtent,
13611                     "invalid %.60s value",attribute);
13612                   ThrowPerlException(exception,OptionError,message,
13613                     SvPV(ST(i),na));
13614                 }
13615               av=(AV *) SvRV(ST(i));
13616               break;
13617             }
13618           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13619             attribute);
13620           break;
13621         }
13622         case 'g':
13623         case 'G':
13624         {
13625           if (LocaleCompare(attribute,"geometry") == 0)
13626             {
13627               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13628               break;
13629             }
13630           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13631             attribute);
13632           break;
13633         }
13634         case 'N':
13635         case 'n':
13636         {
13637           if (LocaleCompare(attribute,"normalize") == 0)
13638             {
13639               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13640                 SvPV(ST(i),na));
13641               if (option < 0)
13642                 {
13643                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13644                     SvPV(ST(i),na));
13645                   break;
13646                 }
13647              normalize=option != 0 ? MagickTrue : MagickFalse;
13648              break;
13649             }
13650           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13651             attribute);
13652           break;
13653         }
13654         case 'x':
13655         case 'X':
13656         {
13657           if (LocaleCompare(attribute,"x") == 0)
13658             {
13659               region.x=SvIV(ST(i));
13660               break;
13661             }
13662           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13663             attribute);
13664           break;
13665         }
13666         case 'y':
13667         case 'Y':
13668         {
13669           if (LocaleCompare(attribute,"y") == 0)
13670             {
13671               region.y=SvIV(ST(i));
13672               break;
13673             }
13674           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13675             attribute);
13676           break;
13677         }
13678         default:
13679         {
13680           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13681             attribute);
13682           break;
13683         }
13684       }
13685     }
13686     (void) SetImageStorageClass(image,DirectClass,exception);
13687     channel_mask=SetImageChannelMask(image,channel);
13688     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13689     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13690         (SvTYPE(av) != SVt_PVAV))
13691       PUSHs(&sv_undef);
13692     else
13693       {
13694         double
13695           scale;
13696
13697         register ssize_t
13698           i;
13699
13700         i=0;
13701         scale=1.0;
13702         if (normalize != MagickFalse)
13703           scale=QuantumRange;
13704         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13705             (i <= av_len(av)))
13706           {
13707             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13708               av_fetch(av,i,0)))),q);
13709             i++;
13710           }
13711         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13712             (i <= av_len(av)))
13713           {
13714             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13715               av_fetch(av,i,0)))),q);
13716             i++;
13717           }
13718         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13719             (i <= av_len(av)))
13720           {
13721             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13722               av_fetch(av,i,0)))),q);
13723             i++;
13724           }
13725         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13726             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13727           {
13728             SetPixelBlack(image,ClampToQuantum(scale*
13729               SvNV(*(av_fetch(av,i,0)))),q);
13730             i++;
13731           }
13732         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13733             (i <= av_len(av)))
13734           {
13735             SetPixelAlpha(image,ClampToQuantum(scale*
13736               SvNV(*(av_fetch(av,i,0)))),q);
13737             i++;
13738           }
13739         (void) SyncAuthenticPixels(image,exception);
13740       }
13741     (void) SetImageChannelMask(image,channel_mask);
13742
13743   PerlException:
13744     InheritPerlException(exception,perl_exception);
13745     exception=DestroyExceptionInfo(exception);
13746     SvREFCNT_dec(perl_exception);
13747   }
13748 \f
13749 #
13750 ###############################################################################
13751 #                                                                             #
13752 #                                                                             #
13753 #                                                                             #
13754 #   S m u s h                                                                 #
13755 #                                                                             #
13756 #                                                                             #
13757 #                                                                             #
13758 ###############################################################################
13759 #
13760 #
13761 void
13762 Smush(ref,...)
13763   Image::Magick ref=NO_INIT
13764   ALIAS:
13765     SmushImage  = 1
13766     smush       = 2
13767     smushimage  = 3
13768   PPCODE:
13769   {
13770     AV
13771       *av;
13772
13773     char
13774       *attribute;
13775
13776     ExceptionInfo
13777       *exception;
13778
13779     HV
13780       *hv;
13781
13782     Image
13783       *image;
13784
13785     register ssize_t
13786       i;
13787
13788     ssize_t
13789       offset,
13790       stack;
13791
13792     struct PackageInfo
13793       *info;
13794
13795     SV
13796       *av_reference,
13797       *perl_exception,
13798       *reference,
13799       *rv,
13800       *sv;
13801
13802     PERL_UNUSED_VAR(ref);
13803     PERL_UNUSED_VAR(ix);
13804     exception=AcquireExceptionInfo();
13805     perl_exception=newSVpv("",0);
13806     sv=NULL;
13807     attribute=NULL;
13808     av=NULL;
13809     if (sv_isobject(ST(0)) == 0)
13810       {
13811         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13812           PackageName);
13813         goto PerlException;
13814       }
13815     reference=SvRV(ST(0));
13816     hv=SvSTASH(reference);
13817     av=newAV();
13818     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13819     SvREFCNT_dec(av);
13820     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13821     if (image == (Image *) NULL)
13822       {
13823         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13824           PackageName);
13825         goto PerlException;
13826       }
13827     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13828     /*
13829       Get options.
13830     */
13831     offset=0;
13832     stack=MagickTrue;
13833     for (i=2; i < items; i+=2)
13834     {
13835       attribute=(char *) SvPV(ST(i-1),na);
13836       switch (*attribute)
13837       {
13838         case 'O':
13839         case 'o':
13840         {
13841           if (LocaleCompare(attribute,"offset") == 0)
13842             {
13843               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13844               break;
13845             }
13846           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13847             attribute);
13848           break;
13849         }
13850         case 'S':
13851         case 's':
13852         {
13853           if (LocaleCompare(attribute,"stack") == 0)
13854             {
13855               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13856                 SvPV(ST(i),na));
13857               if (stack < 0)
13858                 {
13859                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13860                     SvPV(ST(i),na));
13861                   return;
13862                 }
13863               break;
13864             }
13865           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13866             attribute);
13867           break;
13868         }
13869         default:
13870         {
13871           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13872             attribute);
13873           break;
13874         }
13875       }
13876     }
13877     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13878       exception);
13879     if (image == (Image *) NULL)
13880       goto PerlException;
13881     for ( ; image; image=image->next)
13882     {
13883       AddImageToRegistry(sv,image);
13884       rv=newRV(sv);
13885       av_push(av,sv_bless(rv,hv));
13886       SvREFCNT_dec(sv);
13887     }
13888     exception=DestroyExceptionInfo(exception);
13889     ST(0)=av_reference;
13890     SvREFCNT_dec(perl_exception);
13891     XSRETURN(1);
13892
13893   PerlException:
13894     InheritPerlException(exception,perl_exception);
13895     exception=DestroyExceptionInfo(exception);
13896     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13897     SvPOK_on(perl_exception);
13898     ST(0)=sv_2mortal(perl_exception);
13899     XSRETURN(1);
13900   }
13901 \f
13902 #
13903 ###############################################################################
13904 #                                                                             #
13905 #                                                                             #
13906 #                                                                             #
13907 #   S t a t i s t i c s                                                       #
13908 #                                                                             #
13909 #                                                                             #
13910 #                                                                             #
13911 ###############################################################################
13912 #
13913 #
13914 void
13915 Statistics(ref,...)
13916   Image::Magick ref=NO_INIT
13917   ALIAS:
13918     StatisticsImage = 1
13919     statistics      = 2
13920     statisticsimage = 3
13921   PPCODE:
13922   {
13923 #define ChannelStatistics(channel) \
13924 { \
13925   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13926     (double) channel_statistics[channel].depth); \
13927   PUSHs(sv_2mortal(newSVpv(message,0))); \
13928   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13929     channel_statistics[channel].minima/scale); \
13930   PUSHs(sv_2mortal(newSVpv(message,0))); \
13931   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13932     channel_statistics[channel].maxima/scale); \
13933   PUSHs(sv_2mortal(newSVpv(message,0))); \
13934   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13935     channel_statistics[channel].mean/scale); \
13936   PUSHs(sv_2mortal(newSVpv(message,0))); \
13937   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13938     channel_statistics[channel].standard_deviation/scale); \
13939   PUSHs(sv_2mortal(newSVpv(message,0))); \
13940   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13941     channel_statistics[channel].kurtosis); \
13942   PUSHs(sv_2mortal(newSVpv(message,0))); \
13943   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13944     channel_statistics[channel].skewness); \
13945   PUSHs(sv_2mortal(newSVpv(message,0))); \
13946 }
13947
13948     AV
13949       *av;
13950
13951     char
13952       message[MaxTextExtent];
13953
13954     ChannelStatistics
13955       *channel_statistics;
13956
13957     double
13958       scale;
13959
13960     ExceptionInfo
13961       *exception;
13962
13963     Image
13964       *image;
13965
13966     ssize_t
13967       count;
13968
13969     struct PackageInfo
13970       *info;
13971
13972     SV
13973       *perl_exception,
13974       *reference;
13975
13976     PERL_UNUSED_VAR(ref);
13977     PERL_UNUSED_VAR(ix);
13978     exception=AcquireExceptionInfo();
13979     perl_exception=newSVpv("",0);
13980     av=NULL;
13981     if (sv_isobject(ST(0)) == 0)
13982       {
13983         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13984           PackageName);
13985         goto PerlException;
13986       }
13987     reference=SvRV(ST(0));
13988     av=newAV();
13989     SvREFCNT_dec(av);
13990     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13991     if (image == (Image *) NULL)
13992       {
13993         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13994           PackageName);
13995         goto PerlException;
13996       }
13997     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13998     count=0;
13999     for ( ; image; image=image->next)
14000     {
14001       channel_statistics=GetImageStatistics(image,exception);
14002       if (channel_statistics == (ChannelStatistics *) NULL)
14003         continue;
14004       count++;
14005       EXTEND(sp,35*count);
14006       scale=(double) QuantumRange;
14007       ChannelStatistics(RedChannel);
14008       ChannelStatistics(GreenChannel);
14009       ChannelStatistics(BlueChannel);
14010       if (image->colorspace == CMYKColorspace)
14011         ChannelStatistics(BlackChannel);
14012       if (image->alpha_trait == BlendPixelTrait)
14013         ChannelStatistics(AlphaChannel);
14014       channel_statistics=(ChannelStatistics *)
14015         RelinquishMagickMemory(channel_statistics);
14016     }
14017
14018   PerlException:
14019     InheritPerlException(exception,perl_exception);
14020     exception=DestroyExceptionInfo(exception);
14021     SvREFCNT_dec(perl_exception);
14022   }
14023 \f
14024 #
14025 ###############################################################################
14026 #                                                                             #
14027 #                                                                             #
14028 #                                                                             #
14029 #   S y n c A u t h e n t i c P i x e l s                                     #
14030 #                                                                             #
14031 #                                                                             #
14032 #                                                                             #
14033 ###############################################################################
14034 #
14035 #
14036 void
14037 SyncAuthenticPixels(ref,...)
14038   Image::Magick ref = NO_INIT
14039   ALIAS:
14040     Syncauthenticpixels = 1
14041     SyncImagePixels = 2
14042     syncimagepixels = 3
14043   CODE:
14044   {
14045     ExceptionInfo
14046       *exception;
14047
14048     Image
14049       *image;
14050
14051     MagickBooleanType
14052       status;
14053
14054     struct PackageInfo
14055       *info;
14056
14057     SV
14058       *perl_exception,
14059       *reference;
14060
14061     PERL_UNUSED_VAR(ref);
14062     PERL_UNUSED_VAR(ix);
14063     exception=AcquireExceptionInfo();
14064     perl_exception=newSVpv("",0);
14065     if (sv_isobject(ST(0)) == 0)
14066       {
14067         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14068           PackageName);
14069         goto PerlException;
14070       }
14071
14072     reference=SvRV(ST(0));
14073     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14074     if (image == (Image *) NULL)
14075       {
14076         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14077           PackageName);
14078         goto PerlException;
14079       }
14080
14081     status=SyncAuthenticPixels(image,exception);
14082     if (status != MagickFalse)
14083       return;
14084
14085   PerlException:
14086     InheritPerlException(exception,perl_exception);
14087     exception=DestroyExceptionInfo(exception);
14088     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14089   }
14090 \f
14091 #
14092 ###############################################################################
14093 #                                                                             #
14094 #                                                                             #
14095 #                                                                             #
14096 #   T r a n s f o r m                                                         #
14097 #                                                                             #
14098 #                                                                             #
14099 #                                                                             #
14100 ###############################################################################
14101 #
14102 #
14103 void
14104 Transform(ref,...)
14105   Image::Magick ref=NO_INIT
14106   ALIAS:
14107     TransformImage = 1
14108     transform      = 2
14109     transformimage = 3
14110   PPCODE:
14111   {
14112     AV
14113       *av;
14114
14115     char
14116       *attribute,
14117       *crop_geometry,
14118       *geometry;
14119
14120     ExceptionInfo
14121       *exception;
14122
14123     HV
14124       *hv;
14125
14126     Image
14127       *clone,
14128       *image;
14129
14130     register ssize_t
14131       i;
14132
14133     struct PackageInfo
14134       *info;
14135
14136     SV
14137       *av_reference,
14138       *perl_exception,
14139       *reference,
14140       *rv,
14141       *sv;
14142
14143     PERL_UNUSED_VAR(ref);
14144     PERL_UNUSED_VAR(ix);
14145     exception=AcquireExceptionInfo();
14146     perl_exception=newSVpv("",0);
14147     sv=NULL;
14148     av=NULL;
14149     attribute=NULL;
14150     if (sv_isobject(ST(0)) == 0)
14151       {
14152         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14153           PackageName);
14154         goto PerlException;
14155       }
14156     reference=SvRV(ST(0));
14157     hv=SvSTASH(reference);
14158     av=newAV();
14159     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14160     SvREFCNT_dec(av);
14161     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14162     if (image == (Image *) NULL)
14163       {
14164         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14165           PackageName);
14166         goto PerlException;
14167       }
14168     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14169     /*
14170       Get attribute.
14171     */
14172     crop_geometry=(char *) NULL;
14173     geometry=(char *) NULL;
14174     for (i=2; i < items; i+=2)
14175     {
14176       attribute=(char *) SvPV(ST(i-1),na);
14177       switch (*attribute)
14178       {
14179         case 'c':
14180         case 'C':
14181         {
14182           if (LocaleCompare(attribute,"crop") == 0)
14183             {
14184               crop_geometry=SvPV(ST(i),na);
14185               break;
14186             }
14187           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14188             attribute);
14189           break;
14190         }
14191         case 'g':
14192         case 'G':
14193         {
14194           if (LocaleCompare(attribute,"geometry") == 0)
14195             {
14196               geometry=SvPV(ST(i),na);
14197               break;
14198             }
14199           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14200             attribute);
14201           break;
14202         }
14203         default:
14204         {
14205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14206             attribute);
14207           break;
14208         }
14209       }
14210     }
14211     for ( ; image; image=image->next)
14212     {
14213       clone=CloneImage(image,0,0,MagickTrue,exception);
14214       if (clone == (Image *) NULL)
14215         goto PerlException;
14216       TransformImage(&clone,crop_geometry,geometry,exception);
14217       for ( ; clone; clone=clone->next)
14218       {
14219         AddImageToRegistry(sv,clone);
14220         rv=newRV(sv);
14221         av_push(av,sv_bless(rv,hv));
14222         SvREFCNT_dec(sv);
14223       }
14224     }
14225     exception=DestroyExceptionInfo(exception);
14226     ST(0)=av_reference;
14227     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14228     XSRETURN(1);
14229
14230   PerlException:
14231     InheritPerlException(exception,perl_exception);
14232     exception=DestroyExceptionInfo(exception);
14233     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14234     SvPOK_on(perl_exception);
14235     ST(0)=sv_2mortal(perl_exception);
14236     XSRETURN(1);
14237   }
14238 \f
14239 #
14240 ###############################################################################
14241 #                                                                             #
14242 #                                                                             #
14243 #                                                                             #
14244 #   W r i t e                                                                 #
14245 #                                                                             #
14246 #                                                                             #
14247 #                                                                             #
14248 ###############################################################################
14249 #
14250 #
14251 void
14252 Write(ref,...)
14253   Image::Magick ref=NO_INIT
14254   ALIAS:
14255     WriteImage    = 1
14256     write         = 2
14257     writeimage    = 3
14258   PPCODE:
14259   {
14260     char
14261       filename[MaxTextExtent];
14262
14263     ExceptionInfo
14264       *exception;
14265
14266     Image
14267       *image,
14268       *next;
14269
14270     register ssize_t
14271       i;
14272
14273     ssize_t
14274       number_images,
14275       scene;
14276
14277     struct PackageInfo
14278       *info,
14279       *package_info;
14280
14281     SV
14282       *perl_exception,
14283       *reference;
14284
14285     PERL_UNUSED_VAR(ref);
14286     PERL_UNUSED_VAR(ix);
14287     exception=AcquireExceptionInfo();
14288     perl_exception=newSVpv("",0);
14289     number_images=0;
14290     package_info=(struct PackageInfo *) NULL;
14291     if (sv_isobject(ST(0)) == 0)
14292       {
14293         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14294           PackageName);
14295         goto PerlException;
14296       }
14297     reference=SvRV(ST(0));
14298     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14299     if (image == (Image *) NULL)
14300       {
14301         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14302           PackageName);
14303         goto PerlException;
14304       }
14305     package_info=ClonePackageInfo(info,exception);
14306     if (items == 2)
14307       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14308     else
14309       if (items > 2)
14310         for (i=2; i < items; i+=2)
14311           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14312             exception);
14313     (void) CopyMagickString(filename,package_info->image_info->filename,
14314       MaxTextExtent);
14315     scene=0;
14316     for (next=image; next; next=next->next)
14317     {
14318       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14319       next->scene=scene++;
14320     }
14321     SetImageInfo(package_info->image_info,(unsigned int)
14322       GetImageListLength(image),exception);
14323     for (next=image; next; next=next->next)
14324     {
14325       (void) WriteImage(package_info->image_info,next,exception);
14326       number_images++;
14327       if (package_info->image_info->adjoin)
14328         break;
14329     }
14330
14331   PerlException:
14332     if (package_info != (struct PackageInfo *) NULL)
14333       DestroyPackageInfo(package_info);
14334     InheritPerlException(exception,perl_exception);
14335     exception=DestroyExceptionInfo(exception);
14336     sv_setiv(perl_exception,(IV) number_images);
14337     SvPOK_on(perl_exception);
14338     ST(0)=sv_2mortal(perl_exception);
14339     XSRETURN(1);
14340   }