]> 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,
1111             MagickFalse,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,
1120               exception);
1121           break;
1122         }
1123       if (LocaleCompare(attribute,"antialias") == 0)
1124         {
1125           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1126             SvPV(sval,na)) : SvIV(sval);
1127           if (sp < 0)
1128             {
1129               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1130                 SvPV(sval,na));
1131               break;
1132             }
1133           if (info)
1134             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1135           break;
1136         }
1137       if (LocaleCompare(attribute,"area-limit") == 0)
1138         {
1139           MagickSizeType
1140             limit;
1141
1142           limit=MagickResourceInfinity;
1143           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1144             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1145               100.0);
1146           (void) SetMagickResourceLimit(AreaResource,limit);
1147           break;
1148         }
1149       if (LocaleCompare(attribute,"attenuate") == 0)
1150         {
1151           if (info)
1152             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1153           break;
1154         }
1155       if (LocaleCompare(attribute,"authenticate") == 0)
1156         {
1157           if (info)
1158             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1159           break;
1160         }
1161       if (info)
1162         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1163       for ( ; image; image=image->next)
1164         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1165       break;
1166     }
1167     case 'B':
1168     case 'b':
1169     {
1170       if (LocaleCompare(attribute,"background") == 0)
1171         {
1172           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1173             exception);
1174           if (info)
1175             info->image_info->background_color=target_color;
1176           for ( ; image; image=image->next)
1177             image->background_color=target_color;
1178           break;
1179         }
1180       if (LocaleCompare(attribute,"blue-primary") == 0)
1181         {
1182           for ( ; image; image=image->next)
1183           {
1184             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1185             image->chromaticity.blue_primary.x=geometry_info.rho;
1186             image->chromaticity.blue_primary.y=geometry_info.sigma;
1187             if ((flags & SigmaValue) == 0)
1188               image->chromaticity.blue_primary.y=
1189                 image->chromaticity.blue_primary.x;
1190           }
1191           break;
1192         }
1193       if (LocaleCompare(attribute,"bordercolor") == 0)
1194         {
1195           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1196             exception);
1197           if (info)
1198             info->image_info->border_color=target_color;
1199           for ( ; image; image=image->next)
1200             image->border_color=target_color;
1201           break;
1202         }
1203       if (info)
1204         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1205       for ( ; image; image=image->next)
1206         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1207       break;
1208     }
1209     case 'C':
1210     case 'c':
1211     {
1212       if (LocaleCompare(attribute,"cache-threshold") == 0)
1213         {
1214           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1215             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1216           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1217             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1218           break;
1219         }
1220       if (LocaleCompare(attribute,"clip-mask") == 0)
1221         {
1222           Image
1223             *clip_mask;
1224
1225           clip_mask=(Image *) NULL;
1226           if (SvPOK(sval))
1227             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1228           for ( ; image; image=image->next)
1229             SetImageMask(image,clip_mask,exception);
1230           break;
1231         }
1232       if (LocaleNCompare(attribute,"colormap",8) == 0)
1233         {
1234           for ( ; image; image=image->next)
1235           {
1236             int
1237               items;
1238
1239             long
1240               i;
1241
1242             if (image->storage_class == DirectClass)
1243               continue;
1244             i=0;
1245             items=sscanf(attribute,"%*[^[][%ld",&i);
1246             (void) items;
1247             if (i > (ssize_t) image->colors)
1248               i%=image->colors;
1249             if ((strchr(SvPV(sval,na),',') == 0) ||
1250                 (strchr(SvPV(sval,na),')') != 0))
1251               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1252                 image->colormap+i,exception);
1253             else
1254               {
1255                 color=image->colormap+i;
1256                 pixel.red=color->red;
1257                 pixel.green=color->green;
1258                 pixel.blue=color->blue;
1259                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1260                 pixel.red=geometry_info.rho;
1261                 pixel.green=geometry_info.sigma;
1262                 pixel.blue=geometry_info.xi;
1263                 color->red=ClampToQuantum(pixel.red);
1264                 color->green=ClampToQuantum(pixel.green);
1265                 color->blue=ClampToQuantum(pixel.blue);
1266               }
1267           }
1268           break;
1269         }
1270       if (LocaleCompare(attribute,"colorspace") == 0)
1271         {
1272           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1273             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1274           if (sp < 0)
1275             {
1276               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1277                 SvPV(sval,na));
1278               break;
1279             }
1280           for ( ; image; image=image->next)
1281             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1282               exception);
1283           break;
1284         }
1285       if (LocaleCompare(attribute,"comment") == 0)
1286         {
1287           for ( ; image; image=image->next)
1288             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1289               info ? info->image_info : (ImageInfo *) NULL,image,
1290               SvPV(sval,na),exception),exception);
1291           break;
1292         }
1293       if (LocaleCompare(attribute,"compression") == 0)
1294         {
1295           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1296             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1297           if (sp < 0)
1298             {
1299               ThrowPerlException(exception,OptionError,
1300                 "UnrecognizedImageCompression",SvPV(sval,na));
1301               break;
1302             }
1303           if (info)
1304             info->image_info->compression=(CompressionType) sp;
1305           for ( ; image; image=image->next)
1306             image->compression=(CompressionType) sp;
1307           break;
1308         }
1309       if (info)
1310         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1311       for ( ; image; image=image->next)
1312         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1313       break;
1314     }
1315     case 'D':
1316     case 'd':
1317     {
1318       if (LocaleCompare(attribute,"debug") == 0)
1319         {
1320           SetLogEventMask(SvPV(sval,na));
1321           break;
1322         }
1323       if (LocaleCompare(attribute,"delay") == 0)
1324         {
1325           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1326           for ( ; image; image=image->next)
1327           {
1328             image->delay=(size_t) floor(geometry_info.rho+0.5);
1329             if ((flags & SigmaValue) != 0)
1330               image->ticks_per_second=(ssize_t)
1331                 floor(geometry_info.sigma+0.5);
1332           }
1333           break;
1334         }
1335       if (LocaleCompare(attribute,"disk-limit") == 0)
1336         {
1337           MagickSizeType
1338             limit;
1339
1340           limit=MagickResourceInfinity;
1341           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1342             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1343               100.0);
1344           (void) SetMagickResourceLimit(DiskResource,limit);
1345           break;
1346         }
1347       if (LocaleCompare(attribute,"density") == 0)
1348         {
1349           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1350             {
1351               ThrowPerlException(exception,OptionError,"MissingGeometry",
1352                 SvPV(sval,na));
1353               break;
1354             }
1355           if (info)
1356             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1357           for ( ; image; image=image->next)
1358           {
1359             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1360             image->resolution.x=geometry_info.rho;
1361             image->resolution.y=geometry_info.sigma;
1362             if ((flags & SigmaValue) == 0)
1363               image->resolution.y=image->resolution.x;
1364           }
1365           break;
1366         }
1367       if (LocaleCompare(attribute,"depth") == 0)
1368         {
1369           if (info)
1370             info->image_info->depth=SvIV(sval);
1371           for ( ; image; image=image->next)
1372             (void) SetImageDepth(image,SvIV(sval),exception);
1373           break;
1374         }
1375       if (LocaleCompare(attribute,"dispose") == 0)
1376         {
1377           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1378             SvPV(sval,na)) : SvIV(sval);
1379           if (sp < 0)
1380             {
1381               ThrowPerlException(exception,OptionError,
1382                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1383               break;
1384             }
1385           for ( ; image; image=image->next)
1386             image->dispose=(DisposeType) sp;
1387           break;
1388         }
1389       if (LocaleCompare(attribute,"dither") == 0)
1390         {
1391           if (info)
1392             {
1393               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1394                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1395               if (sp < 0)
1396                 {
1397                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1398                     SvPV(sval,na));
1399                   break;
1400                 }
1401               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1402             }
1403           break;
1404         }
1405       if (LocaleCompare(attribute,"display") == 0)
1406         {
1407           display:
1408           if (info)
1409             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1410           break;
1411         }
1412       if (info)
1413         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1414       for ( ; image; image=image->next)
1415         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1416       break;
1417     }
1418     case 'E':
1419     case 'e':
1420     {
1421       if (LocaleCompare(attribute,"endian") == 0)
1422         {
1423           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1424             SvPV(sval,na)) : SvIV(sval);
1425           if (sp < 0)
1426             {
1427               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1428                 SvPV(sval,na));
1429               break;
1430             }
1431           if (info)
1432             info->image_info->endian=(EndianType) sp;
1433           for ( ; image; image=image->next)
1434             image->endian=(EndianType) sp;
1435           break;
1436         }
1437       if (LocaleCompare(attribute,"extract") == 0)
1438         {
1439           /*
1440             Set image extract geometry.
1441           */
1442           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1443           break;
1444         }
1445       if (info)
1446         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1447       for ( ; image; image=image->next)
1448         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1449       break;
1450     }
1451     case 'F':
1452     case 'f':
1453     {
1454       if (LocaleCompare(attribute,"filename") == 0)
1455         {
1456           if (info)
1457             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1458               MaxTextExtent);
1459           for ( ; image; image=image->next)
1460             (void) CopyMagickString(image->filename,SvPV(sval,na),
1461               MaxTextExtent);
1462           break;
1463         }
1464       if (LocaleCompare(attribute,"file") == 0)
1465         {
1466           FILE
1467             *file;
1468
1469           PerlIO
1470             *io_info;
1471
1472           if (info == (struct PackageInfo *) NULL)
1473             break;
1474           io_info=IoIFP(sv_2io(sval));
1475           if (io_info == (PerlIO *) NULL)
1476             {
1477               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1478                 PackageName);
1479               break;
1480             }
1481           file=PerlIO_findFILE(io_info);
1482           if (file == (FILE *) NULL)
1483             {
1484               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1485                 PackageName);
1486               break;
1487             }
1488           SetImageInfoFile(info->image_info,file);
1489           break;
1490         }
1491       if (LocaleCompare(attribute,"fill") == 0)
1492         {
1493           if (info)
1494             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1495           break;
1496         }
1497       if (LocaleCompare(attribute,"font") == 0)
1498         {
1499           if (info)
1500             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1501           break;
1502         }
1503       if (LocaleCompare(attribute,"foreground") == 0)
1504         break;
1505       if (LocaleCompare(attribute,"fuzz") == 0)
1506         {
1507           if (info)
1508             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1509               QuantumRange+1.0);
1510           for ( ; image; image=image->next)
1511             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1512               QuantumRange+1.0);
1513           break;
1514         }
1515       if (info)
1516         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1517       for ( ; image; image=image->next)
1518         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1519       break;
1520     }
1521     case 'G':
1522     case 'g':
1523     {
1524       if (LocaleCompare(attribute,"gamma") == 0)
1525         {
1526           for ( ; image; image=image->next)
1527             image->gamma=SvNV(sval);
1528           break;
1529         }
1530       if (LocaleCompare(attribute,"gravity") == 0)
1531         {
1532           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1533             SvPV(sval,na)) : SvIV(sval);
1534           if (sp < 0)
1535             {
1536               ThrowPerlException(exception,OptionError,
1537                 "UnrecognizedGravityType",SvPV(sval,na));
1538               break;
1539             }
1540           if (info)
1541             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1542           for ( ; image; image=image->next)
1543             image->gravity=(GravityType) sp;
1544           break;
1545         }
1546       if (LocaleCompare(attribute,"green-primary") == 0)
1547         {
1548           for ( ; image; image=image->next)
1549           {
1550             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1551             image->chromaticity.green_primary.x=geometry_info.rho;
1552             image->chromaticity.green_primary.y=geometry_info.sigma;
1553             if ((flags & SigmaValue) == 0)
1554               image->chromaticity.green_primary.y=
1555                 image->chromaticity.green_primary.x;
1556           }
1557           break;
1558         }
1559       if (info)
1560         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1561       for ( ; image; image=image->next)
1562         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1563       break;
1564     }
1565     case 'I':
1566     case 'i':
1567     {
1568       if (LocaleNCompare(attribute,"index",5) == 0)
1569         {
1570           int
1571             items;
1572
1573           long
1574             index;
1575
1576           register Quantum
1577             *q;
1578
1579           CacheView
1580             *image_view;
1581
1582           for ( ; image; image=image->next)
1583           {
1584             if (image->storage_class != PseudoClass)
1585               continue;
1586             x=0;
1587             y=0;
1588             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1589             (void) items;
1590             image_view=AcquireAuthenticCacheView(image,exception);
1591             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1592             if (q != (Quantum *) NULL)
1593               {
1594                 items=sscanf(SvPV(sval,na),"%ld",&index);
1595                 if ((index >= 0) && (index < (ssize_t) image->colors))
1596                   SetPixelIndex(image,index,q);
1597                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1598               }
1599             image_view=DestroyCacheView(image_view);
1600           }
1601           break;
1602         }
1603       if (LocaleCompare(attribute,"iterations") == 0)
1604         {
1605   iterations:
1606           for ( ; image; image=image->next)
1607             image->iterations=SvIV(sval);
1608           break;
1609         }
1610       if (LocaleCompare(attribute,"interlace") == 0)
1611         {
1612           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1613             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1614           if (sp < 0)
1615             {
1616               ThrowPerlException(exception,OptionError,
1617                 "UnrecognizedInterlaceType",SvPV(sval,na));
1618               break;
1619             }
1620           if (info)
1621             info->image_info->interlace=(InterlaceType) sp;
1622           for ( ; image; image=image->next)
1623             image->interlace=(InterlaceType) sp;
1624           break;
1625         }
1626       if (info)
1627         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1628       for ( ; image; image=image->next)
1629         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1630       break;
1631     }
1632     case 'L':
1633     case 'l':
1634     {
1635       if (LocaleCompare(attribute,"label") == 0)
1636         {
1637           for ( ; image; image=image->next)
1638             (void) SetImageProperty(image,"label",InterpretImageProperties(
1639               info ? info->image_info : (ImageInfo *) NULL,image,
1640               SvPV(sval,na),exception),exception);
1641           break;
1642         }
1643       if (LocaleCompare(attribute,"loop") == 0)
1644         goto iterations;
1645       if (info)
1646         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1647       for ( ; image; image=image->next)
1648         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1649       break;
1650     }
1651     case 'M':
1652     case 'm':
1653     {
1654       if (LocaleCompare(attribute,"magick") == 0)
1655         {
1656           if (info)
1657             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1658               "%s:",SvPV(sval,na));
1659           for ( ; image; image=image->next)
1660             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1661           break;
1662         }
1663       if (LocaleCompare(attribute,"map-limit") == 0)
1664         {
1665           MagickSizeType
1666             limit;
1667
1668           limit=MagickResourceInfinity;
1669           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1670             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1671               100.0);
1672           (void) SetMagickResourceLimit(MapResource,limit);
1673           break;
1674         }
1675       if (LocaleCompare(attribute,"mask") == 0)
1676         {
1677           Image
1678             *mask;
1679
1680           mask=(Image *) NULL;
1681           if (SvPOK(sval))
1682             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1683           for ( ; image; image=image->next)
1684             SetImageMask(image,mask,exception);
1685           break;
1686         }
1687       if (LocaleCompare(attribute,"mattecolor") == 0)
1688         {
1689           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1690             exception);
1691           if (info)
1692             info->image_info->matte_color=target_color;
1693           for ( ; image; image=image->next)
1694             image->matte_color=target_color;
1695           break;
1696         }
1697       if (LocaleCompare(attribute,"matte") == 0)
1698         {
1699           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1700             SvPV(sval,na)) : SvIV(sval);
1701           if (sp < 0)
1702             {
1703               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1704                 SvPV(sval,na));
1705               break;
1706             }
1707           for ( ; image; image=image->next)
1708             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1709           break;
1710         }
1711       if (LocaleCompare(attribute,"memory-limit") == 0)
1712         {
1713           MagickSizeType
1714             limit;
1715
1716           limit=MagickResourceInfinity;
1717           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1718             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1719               100.0);
1720           (void) SetMagickResourceLimit(MemoryResource,limit);
1721           break;
1722         }
1723       if (LocaleCompare(attribute,"monochrome") == 0)
1724         {
1725           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1726             SvPV(sval,na)) : SvIV(sval);
1727           if (sp < 0)
1728             {
1729               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1730                 SvPV(sval,na));
1731               break;
1732             }
1733           if (info)
1734             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1735           for ( ; image; image=image->next)
1736             (void) SetImageType(image,BilevelType,exception);
1737           break;
1738         }
1739       if (info)
1740         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1741       for ( ; image; image=image->next)
1742         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1743       break;
1744     }
1745     case 'O':
1746     case 'o':
1747     {
1748       if (LocaleCompare(attribute,"option") == 0)
1749         {
1750           if (info)
1751             DefineImageOption(info->image_info,SvPV(sval,na));
1752           break;
1753         }
1754       if (LocaleCompare(attribute,"orientation") == 0)
1755         {
1756           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1757             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1758           if (sp < 0)
1759             {
1760               ThrowPerlException(exception,OptionError,
1761                 "UnrecognizedOrientationType",SvPV(sval,na));
1762               break;
1763             }
1764           if (info)
1765             info->image_info->orientation=(OrientationType) sp;
1766           for ( ; image; image=image->next)
1767             image->orientation=(OrientationType) sp;
1768           break;
1769         }
1770       if (info)
1771         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1772       for ( ; image; image=image->next)
1773         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1774       break;
1775     }
1776     case 'P':
1777     case 'p':
1778     {
1779       if (LocaleCompare(attribute,"page") == 0)
1780         {
1781           char
1782             *geometry;
1783
1784           geometry=GetPageGeometry(SvPV(sval,na));
1785           if (info)
1786             (void) CloneString(&info->image_info->page,geometry);
1787           for ( ; image; image=image->next)
1788             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1789           geometry=(char *) RelinquishMagickMemory(geometry);
1790           break;
1791         }
1792       if (LocaleNCompare(attribute,"pixel",5) == 0)
1793         {
1794           int
1795             items;
1796
1797           PixelInfo
1798             pixel;
1799
1800           register Quantum
1801             *q;
1802
1803           CacheView
1804             *image_view;
1805
1806           for ( ; image; image=image->next)
1807           {
1808             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1809               break;
1810             x=0;
1811             y=0;
1812             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1813             (void) items;
1814             image_view=AcquireVirtualCacheView(image,exception);
1815             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1816             if (q != (Quantum *) NULL)
1817               {
1818                 if ((strchr(SvPV(sval,na),',') == 0) ||
1819                     (strchr(SvPV(sval,na),')') != 0))
1820                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1821                     &pixel,exception);
1822                 else
1823                   {
1824                     GetPixelInfo(image,&pixel);
1825                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1826                     pixel.red=geometry_info.rho;
1827                     if ((flags & SigmaValue) != 0)
1828                       pixel.green=geometry_info.sigma;
1829                     if ((flags & XiValue) != 0)
1830                       pixel.blue=geometry_info.xi;
1831                     if ((flags & PsiValue) != 0)
1832                       pixel.alpha=geometry_info.psi;
1833                     if ((flags & ChiValue) != 0)
1834                       pixel.black=geometry_info.chi;
1835                   }
1836                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1837                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1838                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1839                 if (image->colorspace == CMYKColorspace)
1840                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1841                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1842                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1843               }
1844             image_view=DestroyCacheView(image_view);
1845           }
1846           break;
1847         }
1848       if (LocaleCompare(attribute,"pointsize") == 0)
1849         {
1850           if (info)
1851             {
1852               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1853               info->image_info->pointsize=geometry_info.rho;
1854             }
1855           break;
1856         }
1857       if (LocaleCompare(attribute,"preview") == 0)
1858         {
1859           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1860             SvPV(sval,na)) : SvIV(sval);
1861           if (sp < 0)
1862             {
1863               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1864                 SvPV(sval,na));
1865               break;
1866             }
1867           if (info)
1868             info->image_info->preview_type=(PreviewType) sp;
1869           break;
1870         }
1871       if (info)
1872         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1873       for ( ; image; image=image->next)
1874         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1875       break;
1876     }
1877     case 'Q':
1878     case 'q':
1879     {
1880       if (LocaleCompare(attribute,"quality") == 0)
1881         {
1882           if (info)
1883             info->image_info->quality=SvIV(sval);
1884           for ( ; image; image=image->next)
1885             image->quality=SvIV(sval);
1886           break;
1887         }
1888       if (info)
1889         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1890       for ( ; image; image=image->next)
1891         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1892       break;
1893     }
1894     case 'R':
1895     case 'r':
1896     {
1897       if (LocaleCompare(attribute,"red-primary") == 0)
1898         {
1899           for ( ; image; image=image->next)
1900           {
1901             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1902             image->chromaticity.red_primary.x=geometry_info.rho;
1903             image->chromaticity.red_primary.y=geometry_info.sigma;
1904             if ((flags & SigmaValue) == 0)
1905               image->chromaticity.red_primary.y=
1906                 image->chromaticity.red_primary.x;
1907           }
1908           break;
1909         }
1910       if (LocaleCompare(attribute,"render") == 0)
1911         {
1912           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1913             SvPV(sval,na)) : SvIV(sval);
1914           if (sp < 0)
1915             {
1916               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1917                 SvPV(sval,na));
1918               break;
1919             }
1920          for ( ; image; image=image->next)
1921            image->rendering_intent=(RenderingIntent) sp;
1922          break;
1923        }
1924       if (LocaleCompare(attribute,"repage") == 0)
1925         {
1926           RectangleInfo
1927             geometry;
1928
1929           for ( ; image; image=image->next)
1930           {
1931             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1932             if ((flags & WidthValue) != 0)
1933               {
1934                 if ((flags & HeightValue) == 0)
1935                   geometry.height=geometry.width;
1936                 image->page.width=geometry.width;
1937                 image->page.height=geometry.height;
1938               }
1939             if ((flags & AspectValue) != 0)
1940               {
1941                 if ((flags & XValue) != 0)
1942                   image->page.x+=geometry.x;
1943                 if ((flags & YValue) != 0)
1944                   image->page.y+=geometry.y;
1945               }
1946             else
1947               {
1948                 if ((flags & XValue) != 0)
1949                   {
1950                     image->page.x=geometry.x;
1951                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1952                       image->page.width=image->columns+geometry.x;
1953                   }
1954                 if ((flags & YValue) != 0)
1955                   {
1956                     image->page.y=geometry.y;
1957                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1958                       image->page.height=image->rows+geometry.y;
1959                   }
1960               }
1961           }
1962           break;
1963         }
1964       if (info)
1965         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1966       for ( ; image; image=image->next)
1967         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1968       break;
1969     }
1970     case 'S':
1971     case 's':
1972     {
1973       if (LocaleCompare(attribute,"sampling-factor") == 0)
1974         {
1975           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1976             {
1977               ThrowPerlException(exception,OptionError,"MissingGeometry",
1978                 SvPV(sval,na));
1979               break;
1980             }
1981           if (info)
1982             (void) CloneString(&info->image_info->sampling_factor,
1983               SvPV(sval,na));
1984           break;
1985         }
1986       if (LocaleCompare(attribute,"scene") == 0)
1987         {
1988           for ( ; image; image=image->next)
1989             image->scene=SvIV(sval);
1990           break;
1991         }
1992       if (LocaleCompare(attribute,"server") == 0)
1993         goto display;
1994       if (LocaleCompare(attribute,"size") == 0)
1995         {
1996           if (info)
1997             {
1998               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1999                 {
2000                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2001                     SvPV(sval,na));
2002                   break;
2003                 }
2004               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2005             }
2006           break;
2007         }
2008       if (LocaleCompare(attribute,"stroke") == 0)
2009         {
2010           if (info)
2011             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2012           break;
2013         }
2014       if (info)
2015         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2016       for ( ; image; image=image->next)
2017         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2018       break;
2019     }
2020     case 'T':
2021     case 't':
2022     {
2023       if (LocaleCompare(attribute,"texture") == 0)
2024         {
2025           if (info)
2026             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2027           break;
2028         }
2029       if (LocaleCompare(attribute,"thread-limit") == 0)
2030         {
2031           MagickSizeType
2032             limit;
2033
2034           limit=MagickResourceInfinity;
2035           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2036             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2037               100.0);
2038           (void) SetMagickResourceLimit(ThreadResource,limit);
2039           break;
2040         }
2041       if (LocaleCompare(attribute,"tile-offset") == 0)
2042         {
2043           char
2044             *geometry;
2045
2046           geometry=GetPageGeometry(SvPV(sval,na));
2047           if (info)
2048             (void) CloneString(&info->image_info->page,geometry);
2049           for ( ; image; image=image->next)
2050             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2051               exception);
2052           geometry=(char *) RelinquishMagickMemory(geometry);
2053           break;
2054         }
2055       if (LocaleCompare(attribute,"time-limit") == 0)
2056         {
2057           MagickSizeType
2058             limit;
2059
2060           limit=MagickResourceInfinity;
2061           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2062             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2063               100.0);
2064           (void) SetMagickResourceLimit(TimeResource,limit);
2065           break;
2066         }
2067       if (LocaleCompare(attribute,"transparent-color") == 0)
2068         {
2069           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2070             exception);
2071           if (info)
2072             info->image_info->transparent_color=target_color;
2073           for ( ; image; image=image->next)
2074             image->transparent_color=target_color;
2075           break;
2076         }
2077       if (LocaleCompare(attribute,"type") == 0)
2078         {
2079           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2080             SvPV(sval,na)) : SvIV(sval);
2081           if (sp < 0)
2082             {
2083               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2084                 SvPV(sval,na));
2085               break;
2086             }
2087           if (info)
2088             info->image_info->type=(ImageType) sp;
2089           for ( ; image; image=image->next)
2090             SetImageType(image,(ImageType) sp,exception);
2091           break;
2092         }
2093       if (info)
2094         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2095       for ( ; image; image=image->next)
2096         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2097       break;
2098     }
2099     case 'U':
2100     case 'u':
2101     {
2102       if (LocaleCompare(attribute,"units") == 0)
2103         {
2104           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2105             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2106           if (sp < 0)
2107             {
2108               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2109                 SvPV(sval,na));
2110               break;
2111             }
2112           if (info)
2113             info->image_info->units=(ResolutionType) sp;
2114           for ( ; image; image=image->next)
2115           {
2116             ResolutionType
2117               units;
2118
2119             units=(ResolutionType) sp;
2120             if (image->units != units)
2121               switch (image->units)
2122               {
2123                 case UndefinedResolution:
2124                 case PixelsPerInchResolution:
2125                 {
2126                   if (units == PixelsPerCentimeterResolution)
2127                     {
2128                       image->resolution.x*=2.54;
2129                       image->resolution.y*=2.54;
2130                     }
2131                   break;
2132                 }
2133                 case PixelsPerCentimeterResolution:
2134                 {
2135                   if (units == PixelsPerInchResolution)
2136                     {
2137                       image->resolution.x/=2.54;
2138                       image->resolution.y/=2.54;
2139                     }
2140                   break;
2141                 }
2142               }
2143             image->units=units;
2144           }
2145           break;
2146         }
2147       if (info)
2148         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2149       for ( ; image; image=image->next)
2150         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2151       break;
2152     }
2153     case 'V':
2154     case 'v':
2155     {
2156       if (LocaleCompare(attribute,"verbose") == 0)
2157         {
2158           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2159             SvPV(sval,na)) : SvIV(sval);
2160           if (sp < 0)
2161             {
2162               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2163                 SvPV(sval,na));
2164               break;
2165             }
2166           if (info)
2167             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2168           break;
2169         }
2170       if (LocaleCompare(attribute,"view") == 0)
2171         {
2172           if (info)
2173             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2174           break;
2175         }
2176       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2177         {
2178           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2179             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2180           if (sp < 0)
2181             {
2182               ThrowPerlException(exception,OptionError,
2183                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2184               break;
2185             }
2186           for ( ; image; image=image->next)
2187             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2188           break;
2189         }
2190       if (info)
2191         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2192       for ( ; image; image=image->next)
2193         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2194       break;
2195     }
2196     case 'W':
2197     case 'w':
2198     {
2199       if (LocaleCompare(attribute,"white-point") == 0)
2200         {
2201           for ( ; image; image=image->next)
2202           {
2203             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2204             image->chromaticity.white_point.x=geometry_info.rho;
2205             image->chromaticity.white_point.y=geometry_info.sigma;
2206             if ((flags & SigmaValue) == 0)
2207               image->chromaticity.white_point.y=
2208                 image->chromaticity.white_point.x;
2209           }
2210           break;
2211         }
2212       if (info)
2213         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2214       for ( ; image; image=image->next)
2215         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2216       break;
2217     }
2218     default:
2219     {
2220       if (info)
2221         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2222       for ( ; image; image=image->next)
2223         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2224       break;
2225     }
2226   }
2227 }
2228 \f
2229 /*
2230 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2231 %                                                                             %
2232 %                                                                             %
2233 %                                                                             %
2234 %   S e t u p L i s t                                                         %
2235 %                                                                             %
2236 %                                                                             %
2237 %                                                                             %
2238 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2239 %
2240 %  Method SetupList returns the list of all the images linked by their
2241 %  image->next and image->previous link lists for use with ImageMagick.  If
2242 %  info is non-NULL, an info structure is returned in *info.  If
2243 %  reference_vector is non-NULL,an array of SV* are returned in
2244 %  *reference_vector.  Reference_vector is used when the images are going to be
2245 %  replaced with new Image*'s.
2246 %
2247 %  The format of the SetupList routine is:
2248 %
2249 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2250 %        SV ***reference_vector,ExceptionInfo *exception)
2251 %
2252 %  A description of each parameter follows:
2253 %
2254 %    o list: a list of strings.
2255 %
2256 %    o string: a character string.
2257 %
2258 %    o exception: Return any errors or warnings in this structure.
2259 %
2260 */
2261 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2262   SV ***reference_vector,ExceptionInfo *exception)
2263 {
2264   Image
2265     *image;
2266
2267   ssize_t
2268     current,
2269     last;
2270
2271   if (reference_vector)
2272     *reference_vector=NULL;
2273   if (info)
2274     *info=NULL;
2275   current=0;
2276   last=0;
2277   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2278   if (info && (SvTYPE(reference) == SVt_PVAV))
2279     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2280       exception);
2281   return(image);
2282 }
2283 \f
2284 /*
2285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2286 %                                                                             %
2287 %                                                                             %
2288 %                                                                             %
2289 %   s t r E Q c a s e                                                         %
2290 %                                                                             %
2291 %                                                                             %
2292 %                                                                             %
2293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2294 %
2295 %  strEQcase() compares two strings and returns 0 if they are the
2296 %  same or if the second string runs out first.  The comparison is case
2297 %  insensitive.
2298 %
2299 %  The format of the strEQcase routine is:
2300 %
2301 %      ssize_t strEQcase(const char *p,const char *q)
2302 %
2303 %  A description of each parameter follows:
2304 %
2305 %    o p: a character string.
2306 %
2307 %    o q: a character string.
2308 %
2309 %
2310 */
2311 static ssize_t strEQcase(const char *p,const char *q)
2312 {
2313   char
2314     c;
2315
2316   register ssize_t
2317     i;
2318
2319   for (i=0 ; (c=(*q)) != 0; i++)
2320   {
2321     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2322         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2323       return(0);
2324     p++;
2325     q++;
2326   }
2327   return(((*q == 0) && (*p == 0)) ? i : 0);
2328 }
2329 \f
2330 /*
2331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2332 %                                                                             %
2333 %                                                                             %
2334 %                                                                             %
2335 %   I m a g e : : M a g i c k                                                 %
2336 %                                                                             %
2337 %                                                                             %
2338 %                                                                             %
2339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2340 %
2341 %
2342 */
2343 MODULE = Image::Magick PACKAGE = Image::Magick
2344
2345 PROTOTYPES: ENABLE
2346
2347 BOOT:
2348   MagickCoreGenesis("PerlMagick",MagickFalse);
2349   SetWarningHandler(NULL);
2350   SetErrorHandler(NULL);
2351   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2352     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2353
2354 void
2355 UNLOAD()
2356   PPCODE:
2357   {
2358     if (magick_registry != (SplayTreeInfo *) NULL)
2359       magick_registry=DestroySplayTree(magick_registry);
2360     MagickCoreTerminus();
2361   }
2362
2363 double
2364 constant(name,argument)
2365   char *name
2366   ssize_t argument
2367 \f
2368 #
2369 ###############################################################################
2370 #                                                                             #
2371 #                                                                             #
2372 #                                                                             #
2373 #   A n i m a t e                                                             #
2374 #                                                                             #
2375 #                                                                             #
2376 #                                                                             #
2377 ###############################################################################
2378 #
2379 #
2380 void
2381 Animate(ref,...)
2382   Image::Magick ref=NO_INIT
2383   ALIAS:
2384     AnimateImage  = 1
2385     animate       = 2
2386     animateimage  = 3
2387   PPCODE:
2388   {
2389     ExceptionInfo
2390       *exception;
2391
2392     Image
2393       *image;
2394
2395     register ssize_t
2396       i;
2397
2398     struct PackageInfo
2399       *info,
2400       *package_info;
2401
2402     SV
2403       *perl_exception,
2404       *reference;
2405
2406     PERL_UNUSED_VAR(ref);
2407     PERL_UNUSED_VAR(ix);
2408     exception=AcquireExceptionInfo();
2409     perl_exception=newSVpv("",0);
2410     package_info=(struct PackageInfo *) NULL;
2411     if (sv_isobject(ST(0)) == 0)
2412       {
2413         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2414           PackageName);
2415         goto PerlException;
2416       }
2417     reference=SvRV(ST(0));
2418     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2419     if (image == (Image *) NULL)
2420       {
2421         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2422           PackageName);
2423         goto PerlException;
2424       }
2425     package_info=ClonePackageInfo(info,exception);
2426     if (items == 2)
2427       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2428     else
2429       if (items > 2)
2430         for (i=2; i < items; i+=2)
2431           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2432             exception);
2433     (void) AnimateImages(package_info->image_info,image,exception);
2434     (void) CatchImageException(image);
2435
2436   PerlException:
2437     if (package_info != (struct PackageInfo *) NULL)
2438       DestroyPackageInfo(package_info);
2439     InheritPerlException(exception,perl_exception);
2440     exception=DestroyExceptionInfo(exception);
2441     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2442     SvPOK_on(perl_exception);
2443     ST(0)=sv_2mortal(perl_exception);
2444     XSRETURN(1);
2445   }
2446 \f
2447 #
2448 ###############################################################################
2449 #                                                                             #
2450 #                                                                             #
2451 #                                                                             #
2452 #   A p p e n d                                                               #
2453 #                                                                             #
2454 #                                                                             #
2455 #                                                                             #
2456 ###############################################################################
2457 #
2458 #
2459 void
2460 Append(ref,...)
2461   Image::Magick ref=NO_INIT
2462   ALIAS:
2463     AppendImage  = 1
2464     append       = 2
2465     appendimage  = 3
2466   PPCODE:
2467   {
2468     AV
2469       *av;
2470
2471     char
2472       *attribute;
2473
2474     ExceptionInfo
2475       *exception;
2476
2477     HV
2478       *hv;
2479
2480     Image
2481       *image;
2482
2483     register ssize_t
2484       i;
2485
2486     ssize_t
2487       stack;
2488
2489     struct PackageInfo
2490       *info;
2491
2492     SV
2493       *av_reference,
2494       *perl_exception,
2495       *reference,
2496       *rv,
2497       *sv;
2498
2499     PERL_UNUSED_VAR(ref);
2500     PERL_UNUSED_VAR(ix);
2501     exception=AcquireExceptionInfo();
2502     perl_exception=newSVpv("",0);
2503     sv=NULL;
2504     attribute=NULL;
2505     av=NULL;
2506     if (sv_isobject(ST(0)) == 0)
2507       {
2508         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2509           PackageName);
2510         goto PerlException;
2511       }
2512     reference=SvRV(ST(0));
2513     hv=SvSTASH(reference);
2514     av=newAV();
2515     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2516     SvREFCNT_dec(av);
2517     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2518     if (image == (Image *) NULL)
2519       {
2520         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2521           PackageName);
2522         goto PerlException;
2523       }
2524     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2525     /*
2526       Get options.
2527     */
2528     stack=MagickTrue;
2529     for (i=2; i < items; i+=2)
2530     {
2531       attribute=(char *) SvPV(ST(i-1),na);
2532       switch (*attribute)
2533       {
2534         case 'S':
2535         case 's':
2536         {
2537           if (LocaleCompare(attribute,"stack") == 0)
2538             {
2539               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2540                 SvPV(ST(i),na));
2541               if (stack < 0)
2542                 {
2543                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2544                     SvPV(ST(i),na));
2545                   return;
2546                 }
2547               break;
2548             }
2549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2550             attribute);
2551           break;
2552         }
2553         default:
2554         {
2555           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2556             attribute);
2557           break;
2558         }
2559       }
2560     }
2561     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2562     if (image == (Image *) NULL)
2563       goto PerlException;
2564     for ( ; image; image=image->next)
2565     {
2566       AddImageToRegistry(sv,image);
2567       rv=newRV(sv);
2568       av_push(av,sv_bless(rv,hv));
2569       SvREFCNT_dec(sv);
2570     }
2571     exception=DestroyExceptionInfo(exception);
2572     ST(0)=av_reference;
2573     SvREFCNT_dec(perl_exception);
2574     XSRETURN(1);
2575
2576   PerlException:
2577     InheritPerlException(exception,perl_exception);
2578     exception=DestroyExceptionInfo(exception);
2579     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2580     SvPOK_on(perl_exception);
2581     ST(0)=sv_2mortal(perl_exception);
2582     XSRETURN(1);
2583   }
2584 \f
2585 #
2586 ###############################################################################
2587 #                                                                             #
2588 #                                                                             #
2589 #                                                                             #
2590 #   A v e r a g e                                                             #
2591 #                                                                             #
2592 #                                                                             #
2593 #                                                                             #
2594 ###############################################################################
2595 #
2596 #
2597 void
2598 Average(ref)
2599   Image::Magick ref=NO_INIT
2600   ALIAS:
2601     AverageImage   = 1
2602     average        = 2
2603     averageimage   = 3
2604   PPCODE:
2605   {
2606     AV
2607       *av;
2608
2609     char
2610       *p;
2611
2612     ExceptionInfo
2613       *exception;
2614
2615     HV
2616       *hv;
2617
2618     Image
2619       *image;
2620
2621     struct PackageInfo
2622       *info;
2623
2624     SV
2625       *perl_exception,
2626       *reference,
2627       *rv,
2628       *sv;
2629
2630     PERL_UNUSED_VAR(ref);
2631     PERL_UNUSED_VAR(ix);
2632     exception=AcquireExceptionInfo();
2633     perl_exception=newSVpv("",0);
2634     sv=NULL;
2635     if (sv_isobject(ST(0)) == 0)
2636       {
2637         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2638           PackageName);
2639         goto PerlException;
2640       }
2641     reference=SvRV(ST(0));
2642     hv=SvSTASH(reference);
2643     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2644     if (image == (Image *) NULL)
2645       {
2646         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2647           PackageName);
2648         goto PerlException;
2649       }
2650     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2651     if (image == (Image *) NULL)
2652       goto PerlException;
2653     /*
2654       Create blessed Perl array for the returned image.
2655     */
2656     av=newAV();
2657     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2658     SvREFCNT_dec(av);
2659     AddImageToRegistry(sv,image);
2660     rv=newRV(sv);
2661     av_push(av,sv_bless(rv,hv));
2662     SvREFCNT_dec(sv);
2663     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2664     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2665       "average-%.*s",(int) (MaxTextExtent-9),
2666       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2667     (void) CopyMagickString(image->filename,info->image_info->filename,
2668       MaxTextExtent);
2669     SetImageInfo(info->image_info,0,exception);
2670     exception=DestroyExceptionInfo(exception);
2671     SvREFCNT_dec(perl_exception);
2672     XSRETURN(1);
2673
2674   PerlException:
2675     InheritPerlException(exception,perl_exception);
2676     exception=DestroyExceptionInfo(exception);
2677     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2678     SvPOK_on(perl_exception);
2679     ST(0)=sv_2mortal(perl_exception);
2680     XSRETURN(1);
2681   }
2682 \f
2683 #
2684 ###############################################################################
2685 #                                                                             #
2686 #                                                                             #
2687 #                                                                             #
2688 #   B l o b T o I m a g e                                                     #
2689 #                                                                             #
2690 #                                                                             #
2691 #                                                                             #
2692 ###############################################################################
2693 #
2694 #
2695 void
2696 BlobToImage(ref,...)
2697   Image::Magick ref=NO_INIT
2698   ALIAS:
2699     BlobToImage  = 1
2700     blobtoimage  = 2
2701     blobto       = 3
2702   PPCODE:
2703   {
2704     AV
2705       *av;
2706
2707     char
2708       **keep,
2709       **list;
2710
2711     ExceptionInfo
2712       *exception;
2713
2714     HV
2715       *hv;
2716
2717     Image
2718       *image;
2719
2720     register char
2721       **p;
2722
2723     register ssize_t
2724       i;
2725
2726     ssize_t
2727       ac,
2728       n,
2729       number_images;
2730
2731     STRLEN
2732       *length;
2733
2734     struct PackageInfo
2735       *info;
2736
2737     SV
2738       *perl_exception,
2739       *reference,
2740       *rv,
2741       *sv;
2742
2743     PERL_UNUSED_VAR(ref);
2744     PERL_UNUSED_VAR(ix);
2745     exception=AcquireExceptionInfo();
2746     perl_exception=newSVpv("",0);
2747     sv=NULL;
2748     number_images=0;
2749     ac=(items < 2) ? 1 : items-1;
2750     length=(STRLEN *) NULL;
2751     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2752     if (list == (char **) NULL)
2753       {
2754         ThrowPerlException(exception,ResourceLimitError,
2755           "MemoryAllocationFailed",PackageName);
2756         goto PerlException;
2757       }
2758     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2759     if (length == (STRLEN *) NULL)
2760       {
2761         ThrowPerlException(exception,ResourceLimitError,
2762           "MemoryAllocationFailed",PackageName);
2763         goto PerlException;
2764       }
2765     if (sv_isobject(ST(0)) == 0)
2766       {
2767         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2768           PackageName);
2769         goto PerlException;
2770       }
2771     reference=SvRV(ST(0));
2772     hv=SvSTASH(reference);
2773     if (SvTYPE(reference) != SVt_PVAV)
2774       {
2775         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2776           PackageName);
2777         goto PerlException;
2778       }
2779     av=(AV *) reference;
2780     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2781       exception);
2782     n=1;
2783     if (items <= 1)
2784       {
2785         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2786         goto PerlException;
2787       }
2788     for (n=0, i=0; i < ac; i++)
2789     {
2790       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2791       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2792         {
2793           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2794           continue;
2795         }
2796       n++;
2797     }
2798     list[n]=(char *) NULL;
2799     keep=list;
2800     for (i=number_images=0; i < n; i++)
2801     {
2802       image=BlobToImage(info->image_info,list[i],length[i],exception);
2803       if (image == (Image *) NULL)
2804         break;
2805       for ( ; image; image=image->next)
2806       {
2807         AddImageToRegistry(sv,image);
2808         rv=newRV(sv);
2809         av_push(av,sv_bless(rv,hv));
2810         SvREFCNT_dec(sv);
2811         number_images++;
2812       }
2813     }
2814     /*
2815       Free resources.
2816     */
2817     for (i=0; i < n; i++)
2818       if (list[i] != (char *) NULL)
2819         for (p=keep; list[i] != *p++; )
2820           if (*p == (char *) NULL)
2821             {
2822               list[i]=(char *) RelinquishMagickMemory(list[i]);
2823               break;
2824             }
2825
2826   PerlException:
2827     if (list)
2828       list=(char **) RelinquishMagickMemory(list);
2829     if (length)
2830       length=(STRLEN *) RelinquishMagickMemory(length);
2831     InheritPerlException(exception,perl_exception);
2832     exception=DestroyExceptionInfo(exception);
2833     sv_setiv(perl_exception,(IV) number_images);
2834     SvPOK_on(perl_exception);
2835     ST(0)=sv_2mortal(perl_exception);
2836     XSRETURN(1);
2837   }
2838 \f
2839 #
2840 ###############################################################################
2841 #                                                                             #
2842 #                                                                             #
2843 #                                                                             #
2844 #   C h a n n e l F x                                                         #
2845 #                                                                             #
2846 #                                                                             #
2847 #                                                                             #
2848 ###############################################################################
2849 #
2850 #
2851 void
2852 ChannelFx(ref,...)
2853   Image::Magick ref=NO_INIT
2854   ALIAS:
2855     ChannelFxImage  = 1
2856     channelfx       = 2
2857     channelfximage  = 3
2858   PPCODE:
2859   {
2860     AV
2861       *av;
2862
2863     char
2864       *attribute,
2865       expression[MaxTextExtent];
2866
2867     ChannelType
2868       channel,
2869       channel_mask;
2870
2871     ExceptionInfo
2872       *exception;
2873
2874     HV
2875       *hv;
2876
2877     Image
2878       *image;
2879
2880     register ssize_t
2881       i;
2882
2883     struct PackageInfo
2884       *info;
2885
2886     SV
2887       *av_reference,
2888       *perl_exception,
2889       *reference,
2890       *rv,
2891       *sv;
2892
2893     PERL_UNUSED_VAR(ref);
2894     PERL_UNUSED_VAR(ix);
2895     exception=AcquireExceptionInfo();
2896     perl_exception=newSVpv("",0);
2897     sv=NULL;
2898     attribute=NULL;
2899     av=NULL;
2900     if (sv_isobject(ST(0)) == 0)
2901       {
2902         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2903           PackageName);
2904         goto PerlException;
2905       }
2906     reference=SvRV(ST(0));
2907     hv=SvSTASH(reference);
2908     av=newAV();
2909     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2910     SvREFCNT_dec(av);
2911     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2912     if (image == (Image *) NULL)
2913       {
2914         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2915           PackageName);
2916         goto PerlException;
2917       }
2918     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2919     /*
2920       Get options.
2921     */
2922     channel=DefaultChannels;
2923     (void) CopyMagickString(expression,"u",MaxTextExtent);
2924     if (items == 2)
2925       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2926     else
2927       for (i=2; i < items; i+=2)
2928       {
2929         attribute=(char *) SvPV(ST(i-1),na);
2930         switch (*attribute)
2931         {
2932           case 'C':
2933           case 'c':
2934           {
2935             if (LocaleCompare(attribute,"channel") == 0)
2936               {
2937                 ssize_t
2938                   option;
2939
2940                 option=ParseChannelOption(SvPV(ST(i),na));
2941                 if (option < 0)
2942                   {
2943                     ThrowPerlException(exception,OptionError,
2944                       "UnrecognizedType",SvPV(ST(i),na));
2945                     return;
2946                   }
2947                 channel=(ChannelType) option;
2948                 break;
2949               }
2950             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2951               attribute);
2952             break;
2953           }
2954           case 'E':
2955           case 'e':
2956           {
2957             if (LocaleCompare(attribute,"expression") == 0)
2958               {
2959                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2960                   MaxTextExtent);
2961                 break;
2962               }
2963             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2964               attribute);
2965             break;
2966           }
2967           default:
2968           {
2969             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2970               attribute);
2971             break;
2972           }
2973         }
2974       }
2975     channel_mask=SetImageChannelMask(image,channel);
2976     image=ChannelFxImage(image,expression,exception);
2977     if (image != (Image *) NULL)
2978       (void) SetImageChannelMask(image,channel_mask);
2979     if (image == (Image *) NULL)
2980       goto PerlException;
2981     for ( ; image; image=image->next)
2982     {
2983       AddImageToRegistry(sv,image);
2984       rv=newRV(sv);
2985       av_push(av,sv_bless(rv,hv));
2986       SvREFCNT_dec(sv);
2987     }
2988     exception=DestroyExceptionInfo(exception);
2989     ST(0)=av_reference;
2990     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2991     XSRETURN(1);
2992
2993   PerlException:
2994     InheritPerlException(exception,perl_exception);
2995     exception=DestroyExceptionInfo(exception);
2996     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2997     SvPOK_on(perl_exception);
2998     ST(0)=sv_2mortal(perl_exception);
2999     XSRETURN(1);
3000   }
3001 \f
3002 #
3003 ###############################################################################
3004 #                                                                             #
3005 #                                                                             #
3006 #                                                                             #
3007 #   C l o n e                                                                 #
3008 #                                                                             #
3009 #                                                                             #
3010 #                                                                             #
3011 ###############################################################################
3012 #
3013 #
3014 void
3015 Clone(ref)
3016   Image::Magick ref=NO_INIT
3017   ALIAS:
3018     CopyImage   = 1
3019     copy        = 2
3020     copyimage   = 3
3021     CloneImage  = 4
3022     clone       = 5
3023     cloneimage  = 6
3024     Clone       = 7
3025   PPCODE:
3026   {
3027     AV
3028       *av;
3029
3030     ExceptionInfo
3031       *exception;
3032
3033     HV
3034       *hv;
3035
3036     Image
3037       *clone,
3038       *image;
3039
3040     struct PackageInfo
3041       *info;
3042
3043     SV
3044       *perl_exception,
3045       *reference,
3046       *rv,
3047       *sv;
3048
3049     PERL_UNUSED_VAR(ref);
3050     PERL_UNUSED_VAR(ix);
3051     exception=AcquireExceptionInfo();
3052     perl_exception=newSVpv("",0);
3053     sv=NULL;
3054     if (sv_isobject(ST(0)) == 0)
3055       {
3056         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3057           PackageName);
3058         goto PerlException;
3059       }
3060     reference=SvRV(ST(0));
3061     hv=SvSTASH(reference);
3062     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3063     if (image == (Image *) NULL)
3064       {
3065         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3066           PackageName);
3067         goto PerlException;
3068       }
3069     /*
3070       Create blessed Perl array for the returned image.
3071     */
3072     av=newAV();
3073     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3074     SvREFCNT_dec(av);
3075     for ( ; image; image=image->next)
3076     {
3077       clone=CloneImage(image,0,0,MagickTrue,exception);
3078       if (clone == (Image *) NULL)
3079         break;
3080       AddImageToRegistry(sv,clone);
3081       rv=newRV(sv);
3082       av_push(av,sv_bless(rv,hv));
3083       SvREFCNT_dec(sv);
3084     }
3085     exception=DestroyExceptionInfo(exception);
3086     SvREFCNT_dec(perl_exception);
3087     XSRETURN(1);
3088
3089   PerlException:
3090     InheritPerlException(exception,perl_exception);
3091     exception=DestroyExceptionInfo(exception);
3092     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3093     SvPOK_on(perl_exception);
3094     ST(0)=sv_2mortal(perl_exception);
3095     XSRETURN(1);
3096   }
3097 \f
3098 #
3099 ###############################################################################
3100 #                                                                             #
3101 #                                                                             #
3102 #                                                                             #
3103 #   C L O N E                                                                 #
3104 #                                                                             #
3105 #                                                                             #
3106 #                                                                             #
3107 ###############################################################################
3108 #
3109 #
3110 void
3111 CLONE(ref,...)
3112   SV *ref;
3113   CODE:
3114   {
3115     PERL_UNUSED_VAR(ref);
3116     if (magick_registry != (SplayTreeInfo *) NULL)
3117       {
3118         register Image
3119           *p;
3120
3121         ResetSplayTreeIterator(magick_registry);
3122         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3123         while (p != (Image *) NULL)
3124         {
3125           ReferenceImage(p);
3126           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3127         }
3128       }
3129   }
3130 \f
3131 #
3132 ###############################################################################
3133 #                                                                             #
3134 #                                                                             #
3135 #                                                                             #
3136 #   C o a l e s c e                                                           #
3137 #                                                                             #
3138 #                                                                             #
3139 #                                                                             #
3140 ###############################################################################
3141 #
3142 #
3143 void
3144 Coalesce(ref)
3145   Image::Magick ref=NO_INIT
3146   ALIAS:
3147     CoalesceImage   = 1
3148     coalesce        = 2
3149     coalesceimage   = 3
3150   PPCODE:
3151   {
3152     AV
3153       *av;
3154
3155     ExceptionInfo
3156       *exception;
3157
3158     HV
3159       *hv;
3160
3161     Image
3162       *image;
3163
3164     struct PackageInfo
3165       *info;
3166
3167     SV
3168       *av_reference,
3169       *perl_exception,
3170       *reference,
3171       *rv,
3172       *sv;
3173
3174     PERL_UNUSED_VAR(ref);
3175     PERL_UNUSED_VAR(ix);
3176     exception=AcquireExceptionInfo();
3177     perl_exception=newSVpv("",0);
3178     sv=NULL;
3179     if (sv_isobject(ST(0)) == 0)
3180       {
3181         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3182           PackageName);
3183         goto PerlException;
3184       }
3185     reference=SvRV(ST(0));
3186     hv=SvSTASH(reference);
3187     av=newAV();
3188     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3189     SvREFCNT_dec(av);
3190     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3191     if (image == (Image *) NULL)
3192       {
3193         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3194           PackageName);
3195         goto PerlException;
3196       }
3197     image=CoalesceImages(image,exception);
3198     if (image == (Image *) NULL)
3199       goto PerlException;
3200     for ( ; image; image=image->next)
3201     {
3202       AddImageToRegistry(sv,image);
3203       rv=newRV(sv);
3204       av_push(av,sv_bless(rv,hv));
3205       SvREFCNT_dec(sv);
3206     }
3207     exception=DestroyExceptionInfo(exception);
3208     ST(0)=av_reference;
3209     SvREFCNT_dec(perl_exception);
3210     XSRETURN(1);
3211
3212   PerlException:
3213     InheritPerlException(exception,perl_exception);
3214     exception=DestroyExceptionInfo(exception);
3215     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3216     SvPOK_on(perl_exception);
3217     ST(0)=sv_2mortal(perl_exception);
3218     XSRETURN(1);
3219   }
3220 \f
3221 #
3222 ###############################################################################
3223 #                                                                             #
3224 #                                                                             #
3225 #                                                                             #
3226 #   C o m p a r e                                                             #
3227 #                                                                             #
3228 #                                                                             #
3229 #                                                                             #
3230 ###############################################################################
3231 #
3232 #
3233 void
3234 Compare(ref,...)
3235   Image::Magick ref=NO_INIT
3236   ALIAS:
3237     CompareImages = 1
3238     compare      = 2
3239     compareimage = 3
3240   PPCODE:
3241   {
3242     AV
3243       *av;
3244
3245     char
3246       *attribute;
3247
3248     double
3249       distortion;
3250
3251     ExceptionInfo
3252       *exception;
3253
3254     HV
3255       *hv;
3256
3257     Image
3258       *difference_image,
3259       *image,
3260       *reconstruct_image;
3261
3262     MetricType
3263       metric;
3264
3265     register ssize_t
3266       i;
3267
3268     ssize_t
3269       option;
3270
3271     struct PackageInfo
3272       *info;
3273
3274     SV
3275       *av_reference,
3276       *perl_exception,
3277       *reference,
3278       *rv,
3279       *sv;
3280
3281     PERL_UNUSED_VAR(ref);
3282     PERL_UNUSED_VAR(ix);
3283     exception=AcquireExceptionInfo();
3284     perl_exception=newSVpv("",0);
3285     sv=NULL;
3286     av=NULL;
3287     attribute=NULL;
3288     if (sv_isobject(ST(0)) == 0)
3289       {
3290         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3291           PackageName);
3292         goto PerlException;
3293       }
3294     reference=SvRV(ST(0));
3295     hv=SvSTASH(reference);
3296     av=newAV();
3297     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3298     SvREFCNT_dec(av);
3299     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3300     if (image == (Image *) NULL)
3301       {
3302         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3303           PackageName);
3304         goto PerlException;
3305       }
3306     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3307     /*
3308       Get attribute.
3309     */
3310     reconstruct_image=image;
3311     metric=RootMeanSquaredErrorMetric;
3312     for (i=2; i < items; i+=2)
3313     {
3314       attribute=(char *) SvPV(ST(i-1),na);
3315       switch (*attribute)
3316       {
3317         case 'C':
3318         case 'c':
3319         {
3320           if (LocaleCompare(attribute,"channel") == 0)
3321             {
3322               ssize_t
3323                 option;
3324
3325               option=ParseChannelOption(SvPV(ST(i),na));
3326               if (option < 0)
3327                 {
3328                   ThrowPerlException(exception,OptionError,
3329                     "UnrecognizedType",SvPV(ST(i),na));
3330                   return;
3331                 }
3332               SetPixelChannelMask(image,(ChannelType) option);
3333               break;
3334             }
3335           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3336             attribute);
3337           break;
3338         }
3339         case 'F':
3340         case 'f':
3341         {
3342           if (LocaleCompare(attribute,"fuzz") == 0)
3343             {
3344               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3345               break;
3346             }
3347           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3348             attribute);
3349           break;
3350         }
3351         case 'I':
3352         case 'i':
3353         {
3354           if (LocaleCompare(attribute,"image") == 0)
3355             {
3356               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3357                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3358               break;
3359             }
3360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3361             attribute);
3362           break;
3363         }
3364         case 'M':
3365         case 'm':
3366         {
3367           if (LocaleCompare(attribute,"metric") == 0)
3368             {
3369               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3370                 SvPV(ST(i),na));
3371               if (option < 0)
3372                 {
3373                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3374                     SvPV(ST(i),na));
3375                   break;
3376                 }
3377               metric=(MetricType) option;
3378               break;
3379             }
3380           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3381             attribute);
3382           break;
3383         }
3384         default:
3385         {
3386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3387             attribute);
3388           break;
3389         }
3390       }
3391     }
3392     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3393       exception);
3394     if (difference_image != (Image *) NULL)
3395       {
3396         difference_image->error.mean_error_per_pixel=distortion;
3397         AddImageToRegistry(sv,difference_image);
3398         rv=newRV(sv);
3399         av_push(av,sv_bless(rv,hv));
3400         SvREFCNT_dec(sv);
3401       }
3402     exception=DestroyExceptionInfo(exception);
3403     ST(0)=av_reference;
3404     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3405     XSRETURN(1);
3406
3407   PerlException:
3408     InheritPerlException(exception,perl_exception);
3409     exception=DestroyExceptionInfo(exception);
3410     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3411     SvPOK_on(perl_exception);
3412     ST(0)=sv_2mortal(perl_exception);
3413     XSRETURN(1);
3414   }
3415 \f
3416 #
3417 ###############################################################################
3418 #                                                                             #
3419 #                                                                             #
3420 #                                                                             #
3421 #   C o m p a r e L a y e r s                                                 #
3422 #                                                                             #
3423 #                                                                             #
3424 #                                                                             #
3425 ###############################################################################
3426 #
3427 #
3428 void
3429 CompareLayers(ref)
3430   Image::Magick ref=NO_INIT
3431   ALIAS:
3432     CompareImagesLayers   = 1
3433     comparelayers        = 2
3434     compareimagelayers   = 3
3435   PPCODE:
3436   {
3437     AV
3438       *av;
3439
3440     char
3441       *attribute;
3442
3443     ExceptionInfo
3444       *exception;
3445
3446     HV
3447       *hv;
3448
3449     Image
3450       *image;
3451
3452     LayerMethod
3453       method;
3454
3455     register ssize_t
3456       i;
3457
3458     ssize_t
3459       option;
3460
3461     struct PackageInfo
3462       *info;
3463
3464     SV
3465       *av_reference,
3466       *perl_exception,
3467       *reference,
3468       *rv,
3469       *sv;
3470
3471     PERL_UNUSED_VAR(ref);
3472     PERL_UNUSED_VAR(ix);
3473     exception=AcquireExceptionInfo();
3474     perl_exception=newSVpv("",0);
3475     sv=NULL;
3476     if (sv_isobject(ST(0)) == 0)
3477       {
3478         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3479           PackageName);
3480         goto PerlException;
3481       }
3482     reference=SvRV(ST(0));
3483     hv=SvSTASH(reference);
3484     av=newAV();
3485     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3486     SvREFCNT_dec(av);
3487     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3488     if (image == (Image *) NULL)
3489       {
3490         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3491           PackageName);
3492         goto PerlException;
3493       }
3494     method=CompareAnyLayer;
3495     for (i=2; i < items; i+=2)
3496     {
3497       attribute=(char *) SvPV(ST(i-1),na);
3498       switch (*attribute)
3499       {
3500         case 'M':
3501         case 'm':
3502         {
3503           if (LocaleCompare(attribute,"method") == 0)
3504             {
3505               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3506                 SvPV(ST(i),na));
3507               if (option < 0)
3508                 {
3509                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3510                     SvPV(ST(i),na));
3511                   break;
3512                 }
3513                method=(LayerMethod) option;
3514               break;
3515             }
3516           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3517             attribute);
3518           break;
3519         }
3520         default:
3521         {
3522           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3523             attribute);
3524           break;
3525         }
3526       }
3527     }
3528     image=CompareImagesLayers(image,method,exception);
3529     if (image == (Image *) NULL)
3530       goto PerlException;
3531     for ( ; image; image=image->next)
3532     {
3533       AddImageToRegistry(sv,image);
3534       rv=newRV(sv);
3535       av_push(av,sv_bless(rv,hv));
3536       SvREFCNT_dec(sv);
3537     }
3538     exception=DestroyExceptionInfo(exception);
3539     ST(0)=av_reference;
3540     SvREFCNT_dec(perl_exception);
3541     XSRETURN(1);
3542
3543   PerlException:
3544     InheritPerlException(exception,perl_exception);
3545     exception=DestroyExceptionInfo(exception);
3546     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3547     SvPOK_on(perl_exception);
3548     ST(0)=sv_2mortal(perl_exception);
3549     XSRETURN(1);
3550   }
3551 \f
3552 #
3553 ###############################################################################
3554 #                                                                             #
3555 #                                                                             #
3556 #                                                                             #
3557 #   D e s t r o y                                                             #
3558 #                                                                             #
3559 #                                                                             #
3560 #                                                                             #
3561 ###############################################################################
3562 #
3563 #
3564 void
3565 DESTROY(ref)
3566   Image::Magick ref=NO_INIT
3567   PPCODE:
3568   {
3569     SV
3570       *reference;
3571
3572     PERL_UNUSED_VAR(ref);
3573     if (sv_isobject(ST(0)) == 0)
3574       croak("ReferenceIsNotMyType");
3575     reference=SvRV(ST(0));
3576     switch (SvTYPE(reference))
3577     {
3578       case SVt_PVAV:
3579       {
3580         char
3581           message[MaxTextExtent];
3582
3583         const SV
3584           *key;
3585
3586         HV
3587           *hv;
3588
3589         GV
3590           **gvp;
3591
3592         struct PackageInfo
3593           *info;
3594
3595         SV
3596           *sv;
3597
3598         /*
3599           Array (AV *) reference
3600         */
3601         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3602           XS_VERSION,reference);
3603         hv=gv_stashpv(PackageName, FALSE);
3604         if (!hv)
3605           break;
3606         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3607         if (!gvp)
3608           break;
3609         sv=GvSV(*gvp);
3610         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3611           {
3612             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3613             DestroyPackageInfo(info);
3614           }
3615         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3616         (void) key;
3617         break;
3618       }
3619       case SVt_PVMG:
3620       {
3621         Image
3622           *image;
3623
3624         /*
3625           Blessed scalar = (Image *) SvIV(reference)
3626         */
3627         image=INT2PTR(Image *,SvIV(reference));
3628         if (image != (Image *) NULL)
3629           DeleteImageFromRegistry(reference,image);
3630         break;
3631       }
3632       default:
3633         break;
3634     }
3635   }
3636 \f
3637 #
3638 ###############################################################################
3639 #                                                                             #
3640 #                                                                             #
3641 #                                                                             #
3642 #   D i s p l a y                                                             #
3643 #                                                                             #
3644 #                                                                             #
3645 #                                                                             #
3646 ###############################################################################
3647 #
3648 #
3649 void
3650 Display(ref,...)
3651   Image::Magick ref=NO_INIT
3652   ALIAS:
3653     DisplayImage  = 1
3654     display       = 2
3655     displayimage  = 3
3656   PPCODE:
3657   {
3658     ExceptionInfo
3659       *exception;
3660
3661     Image
3662       *image;
3663
3664     register ssize_t
3665       i;
3666
3667     struct PackageInfo
3668       *info,
3669       *package_info;
3670
3671     SV
3672       *perl_exception,
3673       *reference;
3674
3675     PERL_UNUSED_VAR(ref);
3676     PERL_UNUSED_VAR(ix);
3677     exception=AcquireExceptionInfo();
3678     perl_exception=newSVpv("",0);
3679     package_info=(struct PackageInfo *) NULL;
3680     if (sv_isobject(ST(0)) == 0)
3681       {
3682         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3683           PackageName);
3684         goto PerlException;
3685       }
3686     reference=SvRV(ST(0));
3687     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3688     if (image == (Image *) NULL)
3689       {
3690         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3691           PackageName);
3692         goto PerlException;
3693       }
3694     package_info=ClonePackageInfo(info,exception);
3695     if (items == 2)
3696       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3697     else
3698       if (items > 2)
3699         for (i=2; i < items; i+=2)
3700           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3701             exception);
3702     (void) DisplayImages(package_info->image_info,image,exception);
3703     (void) CatchImageException(image);
3704
3705   PerlException:
3706     if (package_info != (struct PackageInfo *) NULL)
3707       DestroyPackageInfo(package_info);
3708     InheritPerlException(exception,perl_exception);
3709     exception=DestroyExceptionInfo(exception);
3710     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3711     SvPOK_on(perl_exception);
3712     ST(0)=sv_2mortal(perl_exception);
3713     XSRETURN(1);
3714   }
3715 \f
3716 #
3717 ###############################################################################
3718 #                                                                             #
3719 #                                                                             #
3720 #                                                                             #
3721 #   E v a l u a t e I m a g e s                                               #
3722 #                                                                             #
3723 #                                                                             #
3724 #                                                                             #
3725 ###############################################################################
3726 #
3727 #
3728 void
3729 EvaluateImages(ref)
3730   Image::Magick ref=NO_INIT
3731   ALIAS:
3732     EvaluateImages   = 1
3733     evaluateimages   = 2
3734   PPCODE:
3735   {
3736     AV
3737       *av;
3738
3739     char
3740       *attribute,
3741       *p;
3742
3743     ExceptionInfo
3744       *exception;
3745
3746     HV
3747       *hv;
3748
3749     Image
3750       *image;
3751
3752     MagickEvaluateOperator
3753       op;
3754
3755     register ssize_t
3756       i;
3757
3758     struct PackageInfo
3759       *info;
3760
3761     SV
3762       *perl_exception,
3763       *reference,
3764       *rv,
3765       *sv;
3766
3767     PERL_UNUSED_VAR(ref);
3768     PERL_UNUSED_VAR(ix);
3769     exception=AcquireExceptionInfo();
3770     perl_exception=newSVpv("",0);
3771     sv=NULL;
3772     if (sv_isobject(ST(0)) == 0)
3773       {
3774         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3775           PackageName);
3776         goto PerlException;
3777       }
3778     reference=SvRV(ST(0));
3779     hv=SvSTASH(reference);
3780     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3781     if (image == (Image *) NULL)
3782       {
3783         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3784           PackageName);
3785         goto PerlException;
3786       }
3787     op=MeanEvaluateOperator;
3788     if (items == 2)
3789       {
3790         ssize_t
3791           in;
3792
3793         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3794           SvPV(ST(1),na));
3795         if (in < 0)
3796           {
3797             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3798               SvPV(ST(1),na));
3799             return;
3800           }
3801         op=(MagickEvaluateOperator) in;
3802       }
3803     else
3804       for (i=2; i < items; i+=2)
3805       {
3806         attribute=(char *) SvPV(ST(i-1),na);
3807         switch (*attribute)
3808         {
3809           case 'O':
3810           case 'o':
3811           {
3812             if (LocaleCompare(attribute,"operator") == 0)
3813               {
3814                 ssize_t
3815                   in;
3816
3817                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3818                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3819                 if (in < 0)
3820                   {
3821                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3822                       SvPV(ST(i),na));
3823                     return;
3824                   }
3825                 op=(MagickEvaluateOperator) in;
3826                 break;
3827               }
3828             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3829               attribute);
3830             break;
3831           }
3832           default:
3833           {
3834             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3835               attribute);
3836             break;
3837           }
3838         }
3839       }
3840     image=EvaluateImages(image,op,exception);
3841     if (image == (Image *) NULL)
3842       goto PerlException;
3843     /*
3844       Create blessed Perl array for the returned image.
3845     */
3846     av=newAV();
3847     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3848     SvREFCNT_dec(av);
3849     AddImageToRegistry(sv,image);
3850     rv=newRV(sv);
3851     av_push(av,sv_bless(rv,hv));
3852     SvREFCNT_dec(sv);
3853     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3854     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3855       "evaluate-%.*s",(int) (MaxTextExtent-9),
3856       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3857     (void) CopyMagickString(image->filename,info->image_info->filename,
3858       MaxTextExtent);
3859     SetImageInfo(info->image_info,0,exception);
3860     exception=DestroyExceptionInfo(exception);
3861     SvREFCNT_dec(perl_exception);
3862     XSRETURN(1);
3863
3864   PerlException:
3865     InheritPerlException(exception,perl_exception);
3866     exception=DestroyExceptionInfo(exception);
3867     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3868     SvPOK_on(perl_exception);
3869     ST(0)=sv_2mortal(perl_exception);
3870     XSRETURN(1);
3871   }
3872 \f
3873 #
3874 ###############################################################################
3875 #                                                                             #
3876 #                                                                             #
3877 #                                                                             #
3878 #   F e a t u r e s                                                           #
3879 #                                                                             #
3880 #                                                                             #
3881 #                                                                             #
3882 ###############################################################################
3883 #
3884 #
3885 void
3886 Features(ref,...)
3887   Image::Magick ref=NO_INIT
3888   ALIAS:
3889     FeaturesImage = 1
3890     features      = 2
3891     featuresimage = 3
3892   PPCODE:
3893   {
3894 #define ChannelFeatures(channel,direction) \
3895 { \
3896   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3897     channel_features[channel].angular_second_moment[direction]); \
3898   PUSHs(sv_2mortal(newSVpv(message,0))); \
3899   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3900     channel_features[channel].contrast[direction]); \
3901   PUSHs(sv_2mortal(newSVpv(message,0))); \
3902   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3903     channel_features[channel].contrast[direction]); \
3904   PUSHs(sv_2mortal(newSVpv(message,0))); \
3905   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3906     channel_features[channel].variance_sum_of_squares[direction]); \
3907   PUSHs(sv_2mortal(newSVpv(message,0))); \
3908   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3909     channel_features[channel].inverse_difference_moment[direction]); \
3910   PUSHs(sv_2mortal(newSVpv(message,0))); \
3911   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3912     channel_features[channel].sum_average[direction]); \
3913   PUSHs(sv_2mortal(newSVpv(message,0))); \
3914   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3915     channel_features[channel].sum_variance[direction]); \
3916   PUSHs(sv_2mortal(newSVpv(message,0))); \
3917   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3918     channel_features[channel].sum_entropy[direction]); \
3919   PUSHs(sv_2mortal(newSVpv(message,0))); \
3920   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3921     channel_features[channel].entropy[direction]); \
3922   PUSHs(sv_2mortal(newSVpv(message,0))); \
3923   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3924     channel_features[channel].difference_variance[direction]); \
3925   PUSHs(sv_2mortal(newSVpv(message,0))); \
3926   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3927     channel_features[channel].difference_entropy[direction]); \
3928   PUSHs(sv_2mortal(newSVpv(message,0))); \
3929   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3930     channel_features[channel].measure_of_correlation_1[direction]); \
3931   PUSHs(sv_2mortal(newSVpv(message,0))); \
3932   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3933     channel_features[channel].measure_of_correlation_2[direction]); \
3934   PUSHs(sv_2mortal(newSVpv(message,0))); \
3935   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3936     channel_features[channel].maximum_correlation_coefficient[direction]); \
3937   PUSHs(sv_2mortal(newSVpv(message,0))); \
3938 }
3939
3940     AV
3941       *av;
3942
3943     char
3944       *attribute,
3945       message[MaxTextExtent];
3946
3947     ChannelFeatures
3948       *channel_features;
3949
3950     double
3951       distance;
3952
3953     ExceptionInfo
3954       *exception;
3955
3956     Image
3957       *image;
3958
3959     register ssize_t
3960       i;
3961
3962     ssize_t
3963       count;
3964
3965     struct PackageInfo
3966       *info;
3967
3968     SV
3969       *perl_exception,
3970       *reference;
3971
3972     PERL_UNUSED_VAR(ref);
3973     PERL_UNUSED_VAR(ix);
3974     exception=AcquireExceptionInfo();
3975     perl_exception=newSVpv("",0);
3976     av=NULL;
3977     if (sv_isobject(ST(0)) == 0)
3978       {
3979         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3980           PackageName);
3981         goto PerlException;
3982       }
3983     reference=SvRV(ST(0));
3984     av=newAV();
3985     SvREFCNT_dec(av);
3986     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3987     if (image == (Image *) NULL)
3988       {
3989         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3990           PackageName);
3991         goto PerlException;
3992       }
3993     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3994     distance=1;
3995     for (i=2; i < items; i+=2)
3996     {
3997       attribute=(char *) SvPV(ST(i-1),na);
3998       switch (*attribute)
3999       {
4000         case 'D':
4001         case 'd':
4002         {
4003           if (LocaleCompare(attribute,"distance") == 0)
4004             {
4005               distance=StringToLong((char *) SvPV(ST(1),na));
4006               break;
4007             }
4008           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4009             attribute);
4010           break;
4011         }
4012         default:
4013         {
4014           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4015             attribute);
4016           break;
4017         }
4018       }
4019     }
4020     count=0;
4021     for ( ; image; image=image->next)
4022     {
4023       channel_features=GetImageFeatures(image,distance,exception);
4024       if (channel_features == (ChannelFeatures *) NULL)
4025         continue;
4026       count++;
4027       EXTEND(sp,75*count);
4028       for (i=0; i < 4; i++)
4029       {
4030         ChannelFeatures(RedChannel,i);
4031         ChannelFeatures(GreenChannel,i);
4032         ChannelFeatures(BlueChannel,i);
4033         if (image->colorspace == CMYKColorspace)
4034           ChannelFeatures(BlackChannel,i);
4035         if (image->alpha_trait == BlendPixelTrait)
4036           ChannelFeatures(AlphaChannel,i);
4037       }
4038       channel_features=(ChannelFeatures *)
4039         RelinquishMagickMemory(channel_features);
4040     }
4041
4042   PerlException:
4043     InheritPerlException(exception,perl_exception);
4044     exception=DestroyExceptionInfo(exception);
4045     SvREFCNT_dec(perl_exception);
4046   }
4047 \f
4048 #
4049 ###############################################################################
4050 #                                                                             #
4051 #                                                                             #
4052 #                                                                             #
4053 #   F l a t t e n                                                             #
4054 #                                                                             #
4055 #                                                                             #
4056 #                                                                             #
4057 ###############################################################################
4058 #
4059 #
4060 void
4061 Flatten(ref)
4062   Image::Magick ref=NO_INIT
4063   ALIAS:
4064     FlattenImage   = 1
4065     flatten        = 2
4066     flattenimage   = 3
4067   PPCODE:
4068   {
4069     AV
4070       *av;
4071
4072     char
4073       *attribute,
4074       *p;
4075
4076     ExceptionInfo
4077       *exception;
4078
4079     HV
4080       *hv;
4081
4082     Image
4083       *image;
4084
4085     PixelInfo
4086       background_color;
4087
4088     register ssize_t
4089       i;
4090
4091     struct PackageInfo
4092       *info;
4093
4094     SV
4095       *perl_exception,
4096       *reference,
4097       *rv,
4098       *sv;
4099
4100     PERL_UNUSED_VAR(ref);
4101     PERL_UNUSED_VAR(ix);
4102     exception=AcquireExceptionInfo();
4103     perl_exception=newSVpv("",0);
4104     sv=NULL;
4105     if (sv_isobject(ST(0)) == 0)
4106       {
4107         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4108           PackageName);
4109         goto PerlException;
4110       }
4111     reference=SvRV(ST(0));
4112     hv=SvSTASH(reference);
4113     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4114     if (image == (Image *) NULL)
4115       {
4116         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4117           PackageName);
4118         goto PerlException;
4119       }
4120     background_color=image->background_color;
4121     if (items == 2)
4122       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4123         &background_color,exception);
4124     else
4125       for (i=2; i < items; i+=2)
4126       {
4127         attribute=(char *) SvPV(ST(i-1),na);
4128         switch (*attribute)
4129         {
4130           case 'B':
4131           case 'b':
4132           {
4133             if (LocaleCompare(attribute,"background") == 0)
4134               {
4135                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4136                   AllCompliance,&background_color,exception);
4137                 break;
4138               }
4139             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4140               attribute);
4141             break;
4142           }
4143           default:
4144           {
4145             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4146               attribute);
4147             break;
4148           }
4149         }
4150       }
4151     image->background_color=background_color;
4152     image=MergeImageLayers(image,FlattenLayer,exception);
4153     if (image == (Image *) NULL)
4154       goto PerlException;
4155     /*
4156       Create blessed Perl array for the returned image.
4157     */
4158     av=newAV();
4159     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4160     SvREFCNT_dec(av);
4161     AddImageToRegistry(sv,image);
4162     rv=newRV(sv);
4163     av_push(av,sv_bless(rv,hv));
4164     SvREFCNT_dec(sv);
4165     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4166     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4167       "flatten-%.*s",(int) (MaxTextExtent-9),
4168       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4169     (void) CopyMagickString(image->filename,info->image_info->filename,
4170       MaxTextExtent);
4171     SetImageInfo(info->image_info,0,exception);
4172     exception=DestroyExceptionInfo(exception);
4173     SvREFCNT_dec(perl_exception);
4174     XSRETURN(1);
4175
4176   PerlException:
4177     InheritPerlException(exception,perl_exception);
4178     exception=DestroyExceptionInfo(exception);
4179     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4180     SvPOK_on(perl_exception);  /* return messages in string context */
4181     ST(0)=sv_2mortal(perl_exception);
4182     XSRETURN(1);
4183   }
4184 \f
4185 #
4186 ###############################################################################
4187 #                                                                             #
4188 #                                                                             #
4189 #                                                                             #
4190 #   F x                                                                       #
4191 #                                                                             #
4192 #                                                                             #
4193 #                                                                             #
4194 ###############################################################################
4195 #
4196 #
4197 void
4198 Fx(ref,...)
4199   Image::Magick ref=NO_INIT
4200   ALIAS:
4201     FxImage  = 1
4202     fx       = 2
4203     fximage  = 3
4204   PPCODE:
4205   {
4206     AV
4207       *av;
4208
4209     char
4210       *attribute,
4211       expression[MaxTextExtent];
4212
4213     ChannelType
4214       channel,
4215       channel_mask;
4216
4217     ExceptionInfo
4218       *exception;
4219
4220     HV
4221       *hv;
4222
4223     Image
4224       *image;
4225
4226     register ssize_t
4227       i;
4228
4229     struct PackageInfo
4230       *info;
4231
4232     SV
4233       *av_reference,
4234       *perl_exception,
4235       *reference,
4236       *rv,
4237       *sv;
4238
4239     PERL_UNUSED_VAR(ref);
4240     PERL_UNUSED_VAR(ix);
4241     exception=AcquireExceptionInfo();
4242     perl_exception=newSVpv("",0);
4243     sv=NULL;
4244     attribute=NULL;
4245     av=NULL;
4246     if (sv_isobject(ST(0)) == 0)
4247       {
4248         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4249           PackageName);
4250         goto PerlException;
4251       }
4252     reference=SvRV(ST(0));
4253     hv=SvSTASH(reference);
4254     av=newAV();
4255     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4256     SvREFCNT_dec(av);
4257     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4258     if (image == (Image *) NULL)
4259       {
4260         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4261           PackageName);
4262         goto PerlException;
4263       }
4264     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4265     /*
4266       Get options.
4267     */
4268     channel=DefaultChannels;
4269     (void) CopyMagickString(expression,"u",MaxTextExtent);
4270     if (items == 2)
4271       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4272     else
4273       for (i=2; i < items; i+=2)
4274       {
4275         attribute=(char *) SvPV(ST(i-1),na);
4276         switch (*attribute)
4277         {
4278           case 'C':
4279           case 'c':
4280           {
4281             if (LocaleCompare(attribute,"channel") == 0)
4282               {
4283                 ssize_t
4284                   option;
4285
4286                 option=ParseChannelOption(SvPV(ST(i),na));
4287                 if (option < 0)
4288                   {
4289                     ThrowPerlException(exception,OptionError,
4290                       "UnrecognizedType",SvPV(ST(i),na));
4291                     return;
4292                   }
4293                 channel=(ChannelType) option;
4294                 break;
4295               }
4296             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4297               attribute);
4298             break;
4299           }
4300           case 'E':
4301           case 'e':
4302           {
4303             if (LocaleCompare(attribute,"expression") == 0)
4304               {
4305                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4306                   MaxTextExtent);
4307                 break;
4308               }
4309             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4310               attribute);
4311             break;
4312           }
4313           default:
4314           {
4315             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4316               attribute);
4317             break;
4318           }
4319         }
4320       }
4321     channel_mask=SetImageChannelMask(image,channel);
4322     image=FxImage(image,expression,exception);
4323     if (image != (Image *) NULL)
4324       (void) SetImageChannelMask(image,channel_mask);
4325     if (image == (Image *) NULL)
4326       goto PerlException;
4327     for ( ; image; image=image->next)
4328     {
4329       AddImageToRegistry(sv,image);
4330       rv=newRV(sv);
4331       av_push(av,sv_bless(rv,hv));
4332       SvREFCNT_dec(sv);
4333     }
4334     exception=DestroyExceptionInfo(exception);
4335     ST(0)=av_reference;
4336     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4337     XSRETURN(1);
4338
4339   PerlException:
4340     InheritPerlException(exception,perl_exception);
4341     exception=DestroyExceptionInfo(exception);
4342     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4343     SvPOK_on(perl_exception);
4344     ST(0)=sv_2mortal(perl_exception);
4345     XSRETURN(1);
4346   }
4347 \f
4348 #
4349 ###############################################################################
4350 #                                                                             #
4351 #                                                                             #
4352 #                                                                             #
4353 #   G e t                                                                     #
4354 #                                                                             #
4355 #                                                                             #
4356 #                                                                             #
4357 ###############################################################################
4358 #
4359 #
4360 void
4361 Get(ref,...)
4362   Image::Magick ref=NO_INIT
4363   ALIAS:
4364     GetAttributes = 1
4365     GetAttribute  = 2
4366     get           = 3
4367     getattributes = 4
4368     getattribute  = 5
4369   PPCODE:
4370   {
4371     char
4372       *attribute,
4373       color[MaxTextExtent];
4374
4375     const char
4376       *value;
4377
4378     ExceptionInfo
4379       *exception;
4380
4381     Image
4382       *image;
4383
4384     long
4385       j;
4386
4387     register ssize_t
4388       i;
4389
4390     struct PackageInfo
4391       *info;
4392
4393     SV
4394       *perl_exception,
4395       *reference,
4396       *s;
4397
4398     PERL_UNUSED_VAR(ref);
4399     PERL_UNUSED_VAR(ix);
4400     exception=AcquireExceptionInfo();
4401     perl_exception=newSVpv("",0);
4402     if (sv_isobject(ST(0)) == 0)
4403       {
4404         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4405           PackageName);
4406         XSRETURN_EMPTY;
4407       }
4408     reference=SvRV(ST(0));
4409     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4410     if (image == (Image *) NULL && !info)
4411       XSRETURN_EMPTY;
4412     EXTEND(sp,items);
4413     for (i=1; i < items; i++)
4414     {
4415       attribute=(char *) SvPV(ST(i),na);
4416       s=NULL;
4417       switch (*attribute)
4418       {
4419         case 'A':
4420         case 'a':
4421         {
4422           if (LocaleCompare(attribute,"adjoin") == 0)
4423             {
4424               if (info)
4425                 s=newSViv((ssize_t) info->image_info->adjoin);
4426               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4427               continue;
4428             }
4429           if (LocaleCompare(attribute,"antialias") == 0)
4430             {
4431               if (info)
4432                 s=newSViv((ssize_t) info->image_info->antialias);
4433               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4434               continue;
4435             }
4436           if (LocaleCompare(attribute,"area") == 0)
4437             {
4438               s=newSViv(GetMagickResource(AreaResource));
4439               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4440               continue;
4441             }
4442           if (LocaleCompare(attribute,"attenuate") == 0)
4443             {
4444               const char
4445                 *value;
4446
4447               value=GetImageProperty(image,attribute,exception);
4448               if (value != (const char *) NULL)
4449                 s=newSVpv(value,0);
4450               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4451               continue;
4452             }
4453           if (LocaleCompare(attribute,"authenticate") == 0)
4454             {
4455               if (info)
4456                 {
4457                   const char
4458                     *option;
4459
4460                   option=GetImageOption(info->image_info,attribute);
4461                   if (option != (const char *) NULL)
4462                     s=newSVpv(option,0);
4463                 }
4464               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4465               continue;
4466             }
4467           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4468             attribute);
4469           break;
4470         }
4471         case 'B':
4472         case 'b':
4473         {
4474           if (LocaleCompare(attribute,"background") == 0)
4475             {
4476               if (image == (Image *) NULL)
4477                 break;
4478               (void) FormatLocaleString(color,MaxTextExtent,
4479                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4480                 image->background_color.green,image->background_color.blue,
4481                 image->background_color.alpha);
4482               s=newSVpv(color,0);
4483               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4484               continue;
4485             }
4486           if (LocaleCompare(attribute,"base-columns") == 0)
4487             {
4488               if (image != (Image *) NULL)
4489                 s=newSViv((ssize_t) image->magick_columns);
4490               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4491               continue;
4492             }
4493           if (LocaleCompare(attribute,"base-filename") == 0)
4494             {
4495               if (image != (Image *) NULL)
4496                 s=newSVpv(image->magick_filename,0);
4497               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4498               continue;
4499             }
4500           if (LocaleCompare(attribute,"base-height") == 0)
4501             {
4502               if (image != (Image *) NULL)
4503                 s=newSViv((ssize_t) image->magick_rows);
4504               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4505               continue;
4506             }
4507           if (LocaleCompare(attribute,"base-rows") == 0)
4508             {
4509               if (image != (Image *) NULL)
4510                 s=newSViv((ssize_t) image->magick_rows);
4511               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4512               continue;
4513             }
4514           if (LocaleCompare(attribute,"base-width") == 0)
4515             {
4516               if (image != (Image *) NULL)
4517                 s=newSViv((ssize_t) image->magick_columns);
4518               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4519               continue;
4520             }
4521           if (LocaleCompare(attribute,"blue-primary") == 0)
4522             {
4523               if (image == (Image *) NULL)
4524                 break;
4525               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4526                 image->chromaticity.blue_primary.x,
4527                 image->chromaticity.blue_primary.y);
4528               s=newSVpv(color,0);
4529               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4530               continue;
4531             }
4532           if (LocaleCompare(attribute,"bordercolor") == 0)
4533             {
4534               if (image == (Image *) NULL)
4535                 break;
4536               (void) FormatLocaleString(color,MaxTextExtent,
4537                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4538                 image->border_color.green,image->border_color.blue,
4539                 image->border_color.alpha);
4540               s=newSVpv(color,0);
4541               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4542               continue;
4543             }
4544           if (LocaleCompare(attribute,"bounding-box") == 0)
4545             {
4546               char
4547                 geometry[MaxTextExtent];
4548
4549               RectangleInfo
4550                 page;
4551
4552               if (image == (Image *) NULL)
4553                 break;
4554               page=GetImageBoundingBox(image,exception);
4555               (void) FormatLocaleString(geometry,MaxTextExtent,
4556                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4557                 page.height,(double) page.x,(double) page.y);
4558               s=newSVpv(geometry,0);
4559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4560               continue;
4561             }
4562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4563             attribute);
4564           break;
4565         }
4566         case 'C':
4567         case 'c':
4568         {
4569           if (LocaleCompare(attribute,"class") == 0)
4570             {
4571               if (image == (Image *) NULL)
4572                 break;
4573               s=newSViv(image->storage_class);
4574               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4575                 image->storage_class));
4576               SvIOK_on(s);
4577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4578               continue;
4579             }
4580           if (LocaleCompare(attribute,"clip-mask") == 0)
4581             {
4582               if (image != (Image *) NULL)
4583                 {
4584                   Image
4585                     *mask_image;
4586
4587                   SV
4588                     *sv;
4589
4590                   sv=NULL;
4591                   if (image->mask == MagickFalse)
4592                     ClipImage(image,exception);
4593                   mask_image=GetImageMask(image,exception);
4594                   if (mask_image != (Image *) NULL)
4595                     {
4596                       AddImageToRegistry(sv,mask_image);
4597                       s=sv_bless(newRV(sv),SvSTASH(reference));
4598                     }
4599                 }
4600               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4601               continue;
4602             }
4603           if (LocaleCompare(attribute,"clip-path") == 0)
4604             {
4605               if (image != (Image *) NULL)
4606                 {
4607                   Image
4608                     *mask_image;
4609
4610                   SV
4611                     *sv;
4612
4613                   sv=NULL;
4614                   if (image->mask != MagickFalse)
4615                     ClipImage(image,exception);
4616                   mask_image=GetImageMask(image,exception);
4617                   if (mask_image != (Image *) NULL)
4618                     {
4619                       AddImageToRegistry(sv,mask_image);
4620                       s=sv_bless(newRV(sv),SvSTASH(reference));
4621                     }
4622                 }
4623               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4624               continue;
4625             }
4626           if (LocaleCompare(attribute,"compression") == 0)
4627             {
4628               j=info ? info->image_info->compression : image ?
4629                 image->compression : UndefinedCompression;
4630               if (info)
4631                 if (info->image_info->compression == UndefinedCompression)
4632                   j=image->compression;
4633               s=newSViv(j);
4634               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4635                 j));
4636               SvIOK_on(s);
4637               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4638               continue;
4639             }
4640           if (LocaleCompare(attribute,"colorspace") == 0)
4641             {
4642               j=image ? image->colorspace : RGBColorspace;
4643               s=newSViv(j);
4644               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4645                 j));
4646               SvIOK_on(s);
4647               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4648               continue;
4649             }
4650           if (LocaleCompare(attribute,"colors") == 0)
4651             {
4652               if (image != (Image *) NULL)
4653                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4654                   exception));
4655               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4656               continue;
4657             }
4658           if (LocaleNCompare(attribute,"colormap",8) == 0)
4659             {
4660               int
4661                 items;
4662
4663               if (image == (Image *) NULL || !image->colormap)
4664                 break;
4665               j=0;
4666               items=sscanf(attribute,"%*[^[][%ld",&j);
4667               (void) items;
4668               if (j > (ssize_t) image->colors)
4669                 j%=image->colors;
4670               (void) FormatLocaleString(color,MaxTextExtent,
4671                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4672                 image->colormap[j].green,image->colormap[j].blue,
4673                 image->colormap[j].alpha);
4674               s=newSVpv(color,0);
4675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4676               continue;
4677             }
4678           if (LocaleCompare(attribute,"columns") == 0)
4679             {
4680               if (image != (Image *) NULL)
4681                 s=newSViv((ssize_t) image->columns);
4682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683               continue;
4684             }
4685           if (LocaleCompare(attribute,"comment") == 0)
4686             {
4687               const char
4688                 *value;
4689
4690               value=GetImageProperty(image,attribute,exception);
4691               if (value != (const char *) NULL)
4692                 s=newSVpv(value,0);
4693               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4694               continue;
4695             }
4696           if (LocaleCompare(attribute,"copyright") == 0)
4697             {
4698               s=newSVpv(GetMagickCopyright(),0);
4699               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4700               continue;
4701             }
4702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4703             attribute);
4704           break;
4705         }
4706         case 'D':
4707         case 'd':
4708         {
4709           if (LocaleCompare(attribute,"density") == 0)
4710             {
4711               char
4712                 geometry[MaxTextExtent];
4713
4714               if (image == (Image *) NULL)
4715                 break;
4716               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4717                 image->resolution.x,image->resolution.y);
4718               s=newSVpv(geometry,0);
4719               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4720               continue;
4721             }
4722           if (LocaleCompare(attribute,"delay") == 0)
4723             {
4724               if (image != (Image *) NULL)
4725                 s=newSViv((ssize_t) image->delay);
4726               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4727               continue;
4728             }
4729           if (LocaleCompare(attribute,"depth") == 0)
4730             {
4731               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4732               if (image != (Image *) NULL)
4733                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4734               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4735               continue;
4736             }
4737           if (LocaleCompare(attribute,"directory") == 0)
4738             {
4739               if (image && image->directory)
4740                 s=newSVpv(image->directory,0);
4741               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4742               continue;
4743             }
4744           if (LocaleCompare(attribute,"dispose") == 0)
4745             {
4746               if (image == (Image *) NULL)
4747                 break;
4748
4749               s=newSViv(image->dispose);
4750               (void) sv_setpv(s,
4751                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4752               SvIOK_on(s);
4753               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4754               continue;
4755             }
4756           if (LocaleCompare(attribute,"disk") == 0)
4757             {
4758               s=newSViv(GetMagickResource(DiskResource));
4759               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4760               continue;
4761             }
4762           if (LocaleCompare(attribute,"dither") == 0)
4763             {
4764               if (info)
4765                 s=newSViv((ssize_t) info->image_info->dither);
4766               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4767               continue;
4768             }
4769           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4770             {
4771               if (info && info->image_info->server_name)
4772                 s=newSVpv(info->image_info->server_name,0);
4773               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4774               continue;
4775             }
4776           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4777             attribute);
4778           break;
4779         }
4780         case 'E':
4781         case 'e':
4782         {
4783           if (LocaleCompare(attribute,"elapsed-time") == 0)
4784             {
4785               if (image != (Image *) NULL)
4786                 s=newSVnv(GetElapsedTime(&image->timer));
4787               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4788               continue;
4789             }
4790           if (LocaleCompare(attribute,"endian") == 0)
4791             {
4792               j=info ? info->image_info->endian : image ? image->endian :
4793                 UndefinedEndian;
4794               s=newSViv(j);
4795               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4796               SvIOK_on(s);
4797               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4798               continue;
4799             }
4800           if (LocaleCompare(attribute,"error") == 0)
4801             {
4802               if (image != (Image *) NULL)
4803                 s=newSVnv(image->error.mean_error_per_pixel);
4804               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4805               continue;
4806             }
4807           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4808             attribute);
4809           break;
4810         }
4811         case 'F':
4812         case 'f':
4813         {
4814           if (LocaleCompare(attribute,"filesize") == 0)
4815             {
4816               if (image != (Image *) NULL)
4817                 s=newSViv((ssize_t) GetBlobSize(image));
4818               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4819               continue;
4820             }
4821           if (LocaleCompare(attribute,"filename") == 0)
4822             {
4823               if (info && info->image_info->filename &&
4824                   *info->image_info->filename)
4825                 s=newSVpv(info->image_info->filename,0);
4826               if (image != (Image *) NULL)
4827                 s=newSVpv(image->filename,0);
4828               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4829               continue;
4830             }
4831           if (LocaleCompare(attribute,"filter") == 0)
4832             {
4833               s=image ? newSViv(image->filter) : newSViv(0);
4834               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4835                 image->filter));
4836               SvIOK_on(s);
4837               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4838               continue;
4839             }
4840           if (LocaleCompare(attribute,"font") == 0)
4841             {
4842               if (info && info->image_info->font)
4843                 s=newSVpv(info->image_info->font,0);
4844               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4845               continue;
4846             }
4847           if (LocaleCompare(attribute,"foreground") == 0)
4848             continue;
4849           if (LocaleCompare(attribute,"format") == 0)
4850             {
4851               const MagickInfo
4852                 *magick_info;
4853
4854               magick_info=(const MagickInfo *) NULL;
4855               if (info && (*info->image_info->magick != '\0'))
4856                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4857               if (image != (Image *) NULL)
4858                 magick_info=GetMagickInfo(image->magick,exception);
4859               if ((magick_info != (const MagickInfo *) NULL) &&
4860                   (*magick_info->description != '\0'))
4861                 s=newSVpv((char *) magick_info->description,0);
4862               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4863               continue;
4864             }
4865           if (LocaleCompare(attribute,"fuzz") == 0)
4866             {
4867               if (info)
4868                 s=newSVnv(info->image_info->fuzz);
4869               if (image != (Image *) NULL)
4870                 s=newSVnv(image->fuzz);
4871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4872               continue;
4873             }
4874           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4875             attribute);
4876           break;
4877         }
4878         case 'G':
4879         case 'g':
4880         {
4881           if (LocaleCompare(attribute,"gamma") == 0)
4882             {
4883               if (image != (Image *) NULL)
4884                 s=newSVnv(image->gamma);
4885               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4886               continue;
4887             }
4888           if (LocaleCompare(attribute,"geometry") == 0)
4889             {
4890               if (image && image->geometry)
4891                 s=newSVpv(image->geometry,0);
4892               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4893               continue;
4894             }
4895           if (LocaleCompare(attribute,"gravity") == 0)
4896             {
4897               s=image ? newSViv(image->gravity) : newSViv(0);
4898               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4899                 image->gravity));
4900               SvIOK_on(s);
4901               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4902               continue;
4903             }
4904           if (LocaleCompare(attribute,"green-primary") == 0)
4905             {
4906               if (image == (Image *) NULL)
4907                 break;
4908               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4909                 image->chromaticity.green_primary.x,
4910                 image->chromaticity.green_primary.y);
4911               s=newSVpv(color,0);
4912               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4913               continue;
4914             }
4915           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4916             attribute);
4917           break;
4918         }
4919         case 'H':
4920         case 'h':
4921         {
4922           if (LocaleCompare(attribute,"height") == 0)
4923             {
4924               if (image != (Image *) NULL)
4925                 s=newSViv((ssize_t) image->rows);
4926               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4927               continue;
4928             }
4929           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4930             attribute);
4931           break;
4932         }
4933         case 'I':
4934         case 'i':
4935         {
4936           if (LocaleCompare(attribute,"icc") == 0)
4937             {
4938               if (image != (Image *) NULL)
4939                 {
4940                   const StringInfo
4941                     *profile;
4942
4943                   profile=GetImageProfile(image,"icc");
4944                   if (profile != (StringInfo *) NULL)
4945                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4946                       GetStringInfoLength(profile));
4947                 }
4948               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4949               continue;
4950             }
4951           if (LocaleCompare(attribute,"icm") == 0)
4952             {
4953               if (image != (Image *) NULL)
4954                 {
4955                   const StringInfo
4956                     *profile;
4957
4958                   profile=GetImageProfile(image,"icm");
4959                   if (profile != (const StringInfo *) NULL)
4960                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4961                       GetStringInfoLength(profile));
4962                 }
4963               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4964               continue;
4965             }
4966           if (LocaleCompare(attribute,"id") == 0)
4967             {
4968               if (image != (Image *) NULL)
4969                 {
4970                   char
4971                     key[MaxTextExtent];
4972
4973                   MagickBooleanType
4974                     status;
4975
4976                   static ssize_t
4977                     id = 0;
4978
4979                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4980                     id);
4981                   status=SetImageRegistry(ImageRegistryType,key,image,
4982                     exception);
4983                   (void) status;
4984                   s=newSViv(id++);
4985                 }
4986               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4987               continue;
4988             }
4989           if (LocaleNCompare(attribute,"index",5) == 0)
4990             {
4991               char
4992                 name[MaxTextExtent];
4993
4994               int
4995                 items;
4996
4997               long
4998                 x,
4999                 y;
5000
5001               register const Quantum
5002                 *p;
5003
5004               CacheView
5005                 *image_view;
5006
5007               if (image == (Image *) NULL)
5008                 break;
5009               if (image->storage_class != PseudoClass)
5010                 break;
5011               x=0;
5012               y=0;
5013               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5014               (void) items;
5015               image_view=AcquireVirtualCacheView(image,exception);
5016               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5017               if (p != (const Quantum *) NULL)
5018                 {
5019                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5020                     GetPixelIndex(image,p));
5021                   s=newSVpv(name,0);
5022                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5023                 }
5024               image_view=DestroyCacheView(image_view);
5025               continue;
5026             }
5027           if (LocaleCompare(attribute,"iptc") == 0)
5028             {
5029               if (image != (Image *) NULL)
5030                 {
5031                   const StringInfo
5032                     *profile;
5033
5034                   profile=GetImageProfile(image,"iptc");
5035                   if (profile != (const StringInfo *) NULL)
5036                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5037                       GetStringInfoLength(profile));
5038                 }
5039               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5040               continue;
5041             }
5042           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5043             {
5044               if (image != (Image *) NULL)
5045                 s=newSViv((ssize_t) image->iterations);
5046               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5047               continue;
5048             }
5049           if (LocaleCompare(attribute,"interlace") == 0)
5050             {
5051               j=info ? info->image_info->interlace : image ? image->interlace :
5052                 UndefinedInterlace;
5053               s=newSViv(j);
5054               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5055                 j));
5056               SvIOK_on(s);
5057               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5058               continue;
5059             }
5060           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5061             attribute);
5062           break;
5063         }
5064         case 'L':
5065         case 'l':
5066         {
5067           if (LocaleCompare(attribute,"label") == 0)
5068             {
5069               const char
5070                 *value;
5071
5072               if (image == (Image *) NULL)
5073                 break;
5074               value=GetImageProperty(image,"Label",exception);
5075               if (value != (const char *) NULL)
5076                 s=newSVpv(value,0);
5077               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5078               continue;
5079             }
5080           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5081             {
5082               if (image != (Image *) NULL)
5083                 s=newSViv((ssize_t) image->iterations);
5084               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5085               continue;
5086             }
5087           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5088             attribute);
5089           break;
5090         }
5091         case 'M':
5092         case 'm':
5093         {
5094           if (LocaleCompare(attribute,"magick") == 0)
5095             {
5096               if (info && *info->image_info->magick)
5097                 s=newSVpv(info->image_info->magick,0);
5098               if (image != (Image *) NULL)
5099                 s=newSVpv(image->magick,0);
5100               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5101               continue;
5102             }
5103           if (LocaleCompare(attribute,"map") == 0)
5104             {
5105               s=newSViv(GetMagickResource(MapResource));
5106               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5107               continue;
5108             }
5109           if (LocaleCompare(attribute,"maximum-error") == 0)
5110             {
5111               if (image != (Image *) NULL)
5112                 s=newSVnv(image->error.normalized_maximum_error);
5113               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5114               continue;
5115             }
5116           if (LocaleCompare(attribute,"memory") == 0)
5117             {
5118               s=newSViv(GetMagickResource(MemoryResource));
5119               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5120               continue;
5121             }
5122           if (LocaleCompare(attribute,"mean-error") == 0)
5123             {
5124               if (image != (Image *) NULL)
5125                 s=newSVnv(image->error.normalized_mean_error);
5126               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5127               continue;
5128             }
5129           if (LocaleCompare(attribute,"mime") == 0)
5130             {
5131               if (info && *info->image_info->magick)
5132                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5133               if (image != (Image *) NULL)
5134                 s=newSVpv(MagickToMime(image->magick),0);
5135               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5136               continue;
5137             }
5138           if (LocaleCompare(attribute,"mattecolor") == 0)
5139             {
5140               if (image == (Image *) NULL)
5141                 break;
5142               (void) FormatLocaleString(color,MaxTextExtent,
5143                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5144                 image->matte_color.green,image->matte_color.blue,
5145                 image->matte_color.alpha);
5146               s=newSVpv(color,0);
5147               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5148               continue;
5149             }
5150           if (LocaleCompare(attribute,"matte") == 0)
5151             {
5152               if (image != (Image *) NULL)
5153                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5154                   1 : 0);
5155               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5156               continue;
5157             }
5158           if (LocaleCompare(attribute,"mime") == 0)
5159             {
5160               const char
5161                 *magick;
5162
5163               magick=NULL;
5164               if (info && *info->image_info->magick)
5165                 magick=info->image_info->magick;
5166               if (image != (Image *) NULL)
5167                 magick=image->magick;
5168               if (magick)
5169                 {
5170                   char
5171                     *mime;
5172
5173                   mime=MagickToMime(magick);
5174                   s=newSVpv(mime,0);
5175                   mime=(char *) RelinquishMagickMemory(mime);
5176                 }
5177               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5178               continue;
5179             }
5180           if (LocaleCompare(attribute,"monochrome") == 0)
5181             {
5182               if (image == (Image *) NULL)
5183                 continue;
5184               j=info ? info->image_info->monochrome :
5185                 IsImageMonochrome(image,exception);
5186               s=newSViv(j);
5187               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5188               continue;
5189             }
5190           if (LocaleCompare(attribute,"montage") == 0)
5191             {
5192               if (image && image->montage)
5193                 s=newSVpv(image->montage,0);
5194               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5195               continue;
5196             }
5197           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5198             attribute);
5199           break;
5200         }
5201         case 'O':
5202         case 'o':
5203         {
5204           if (LocaleCompare(attribute,"orientation") == 0)
5205             {
5206               j=info ? info->image_info->orientation : image ?
5207                 image->orientation : UndefinedOrientation;
5208               s=newSViv(j);
5209               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5210                 j));
5211               SvIOK_on(s);
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5216             attribute);
5217           break;
5218         }
5219         case 'P':
5220         case 'p':
5221         {
5222           if (LocaleCompare(attribute,"page") == 0)
5223             {
5224               if (info && info->image_info->page)
5225                 s=newSVpv(info->image_info->page,0);
5226               if (image != (Image *) NULL)
5227                 {
5228                   char
5229                     geometry[MaxTextExtent];
5230
5231                   (void) FormatLocaleString(geometry,MaxTextExtent,
5232                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5233                     (double) image->page.height,(double) image->page.x,(double)
5234                     image->page.y);
5235                   s=newSVpv(geometry,0);
5236                 }
5237               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5238               continue;
5239             }
5240           if (LocaleCompare(attribute,"page.x") == 0)
5241             {
5242               if (image != (Image *) NULL)
5243                 s=newSViv((ssize_t) image->page.x);
5244               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5245               continue;
5246             }
5247           if (LocaleCompare(attribute,"page.y") == 0)
5248             {
5249               if (image != (Image *) NULL)
5250                 s=newSViv((ssize_t) image->page.y);
5251               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5252               continue;
5253             }
5254           if (LocaleNCompare(attribute,"pixel",5) == 0)
5255             {
5256               char
5257                 tuple[MaxTextExtent];
5258
5259               int
5260                 items;
5261
5262               long
5263                 x,
5264                 y;
5265
5266               register const Quantum
5267                 *p;
5268
5269               if (image == (Image *) NULL)
5270                 break;
5271               x=0;
5272               y=0;
5273               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5274               (void) items;
5275               p=GetVirtualPixels(image,x,y,1,1,exception);
5276               if (image->colorspace != CMYKColorspace)
5277                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5278                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5279                   GetPixelRed(image,p),GetPixelGreen(image,p),
5280                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5281               else
5282                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5283                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5284                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5285                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5286                   GetPixelAlpha(image,p));
5287               s=newSVpv(tuple,0);
5288               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5289               continue;
5290             }
5291           if (LocaleCompare(attribute,"pointsize") == 0)
5292             {
5293               if (info)
5294                 s=newSViv((ssize_t) info->image_info->pointsize);
5295               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5296               continue;
5297             }
5298           if (LocaleCompare(attribute,"preview") == 0)
5299             {
5300               s=newSViv(info->image_info->preview_type);
5301               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5302                 info->image_info->preview_type));
5303               SvIOK_on(s);
5304               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5305               continue;
5306             }
5307           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5308             attribute);
5309           break;
5310         }
5311         case 'Q':
5312         case 'q':
5313         {
5314           if (LocaleCompare(attribute,"quality") == 0)
5315             {
5316               if (info)
5317                 s=newSViv((ssize_t) info->image_info->quality);
5318               if (image != (Image *) NULL)
5319                 s=newSViv((ssize_t) image->quality);
5320               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5321               continue;
5322             }
5323           if (LocaleCompare(attribute,"quantum") == 0)
5324             {
5325               if (info)
5326                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5327               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5328               continue;
5329             }
5330           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5331             attribute);
5332           break;
5333         }
5334         case 'R':
5335         case 'r':
5336         {
5337           if (LocaleCompare(attribute,"rendering-intent") == 0)
5338             {
5339               s=newSViv(image->rendering_intent);
5340               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5341                 image->rendering_intent));
5342               SvIOK_on(s);
5343               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5344               continue;
5345             }
5346           if (LocaleCompare(attribute,"red-primary") == 0)
5347             {
5348               if (image == (Image *) NULL)
5349                 break;
5350               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5351                 image->chromaticity.red_primary.x,
5352                 image->chromaticity.red_primary.y);
5353               s=newSVpv(color,0);
5354               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5355               continue;
5356             }
5357           if (LocaleCompare(attribute,"rows") == 0)
5358             {
5359               if (image != (Image *) NULL)
5360                 s=newSViv((ssize_t) image->rows);
5361               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5362               continue;
5363             }
5364           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5365             attribute);
5366           break;
5367         }
5368         case 'S':
5369         case 's':
5370         {
5371           if (LocaleCompare(attribute,"sampling-factor") == 0)
5372             {
5373               if (info && info->image_info->sampling_factor)
5374                 s=newSVpv(info->image_info->sampling_factor,0);
5375               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5376               continue;
5377             }
5378           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5379             {
5380               if (info && info->image_info->server_name)
5381                 s=newSVpv(info->image_info->server_name,0);
5382               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5383               continue;
5384             }
5385           if (LocaleCompare(attribute,"size") == 0)
5386             {
5387               if (info && info->image_info->size)
5388                 s=newSVpv(info->image_info->size,0);
5389               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5390               continue;
5391             }
5392           if (LocaleCompare(attribute,"scene") == 0)
5393             {
5394               if (image != (Image *) NULL)
5395                 s=newSViv((ssize_t) image->scene);
5396               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5397               continue;
5398             }
5399           if (LocaleCompare(attribute,"scenes") == 0)
5400             {
5401               if (image != (Image *) NULL)
5402                 s=newSViv((ssize_t) info->image_info->number_scenes);
5403               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5404               continue;
5405             }
5406           if (LocaleCompare(attribute,"signature") == 0)
5407             {
5408               const char
5409                 *value;
5410
5411               if (image == (Image *) NULL)
5412                 break;
5413               (void) SignatureImage(image,exception);
5414               value=GetImageProperty(image,"Signature",exception);
5415               if (value != (const char *) NULL)
5416                 s=newSVpv(value,0);
5417               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5418               continue;
5419             }
5420           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5421             attribute);
5422           break;
5423         }
5424         case 'T':
5425         case 't':
5426         {
5427           if (LocaleCompare(attribute,"taint") == 0)
5428             {
5429               if (image != (Image *) NULL)
5430                 s=newSViv((ssize_t) IsTaintImage(image));
5431               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5432               continue;
5433             }
5434           if (LocaleCompare(attribute,"texture") == 0)
5435             {
5436               if (info && info->image_info->texture)
5437                 s=newSVpv(info->image_info->texture,0);
5438               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5439               continue;
5440             }
5441           if (LocaleCompare(attribute,"total-ink-density") == 0)
5442             {
5443               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5444               if (image != (Image *) NULL)
5445                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5446               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5447               continue;
5448             }
5449           if (LocaleCompare(attribute,"transparent-color") == 0)
5450             {
5451               if (image == (Image *) NULL)
5452                 break;
5453               (void) FormatLocaleString(color,MaxTextExtent,
5454                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5455                 image->transparent_color.green,image->transparent_color.blue,
5456                 image->transparent_color.alpha);
5457               s=newSVpv(color,0);
5458               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5459               continue;
5460             }
5461           if (LocaleCompare(attribute,"type") == 0)
5462             {
5463               if (image == (Image *) NULL)
5464                 break;
5465               j=(ssize_t) GetImageType(image,exception);
5466               s=newSViv(j);
5467               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5468               SvIOK_on(s);
5469               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5470               continue;
5471             }
5472           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5473             attribute);
5474           break;
5475         }
5476         case 'U':
5477         case 'u':
5478         {
5479           if (LocaleCompare(attribute,"units") == 0)
5480             {
5481               j=info ? info->image_info->units : image ? image->units :
5482                 UndefinedResolution;
5483               if (info && (info->image_info->units == UndefinedResolution))
5484                 if (image)
5485                   j=image->units;
5486               if (j == UndefinedResolution)
5487                 s=newSVpv("undefined units",0);
5488               else
5489                 if (j == PixelsPerInchResolution)
5490                   s=newSVpv("pixels / inch",0);
5491                 else
5492                   s=newSVpv("pixels / centimeter",0);
5493               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5494               continue;
5495             }
5496           if (LocaleCompare(attribute,"user-time") == 0)
5497             {
5498               if (image != (Image *) NULL)
5499                 s=newSVnv(GetUserTime(&image->timer));
5500               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5501               continue;
5502             }
5503           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5504             attribute);
5505           break;
5506         }
5507         case 'V':
5508         case 'v':
5509         {
5510           if (LocaleCompare(attribute,"verbose") == 0)
5511             {
5512               if (info)
5513                 s=newSViv((ssize_t) info->image_info->verbose);
5514               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5515               continue;
5516             }
5517           if (LocaleCompare(attribute,"version") == 0)
5518             {
5519               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5520               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5521               continue;
5522             }
5523           if (LocaleCompare(attribute,"view") == 0)
5524             {
5525               if (info && info->image_info->view)
5526                 s=newSVpv(info->image_info->view,0);
5527               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5528               continue;
5529             }
5530           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5531             {
5532               if (image == (Image *) NULL)
5533                 break;
5534               j=(ssize_t) GetImageVirtualPixelMethod(image);
5535               s=newSViv(j);
5536               (void) sv_setpv(s,CommandOptionToMnemonic(
5537                 MagickVirtualPixelOptions,j));
5538               SvIOK_on(s);
5539               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5540               continue;
5541             }
5542           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5543             attribute);
5544           break;
5545         }
5546         case 'W':
5547         case 'w':
5548         {
5549           if (LocaleCompare(attribute,"white-point") == 0)
5550             {
5551               if (image == (Image *) NULL)
5552                 break;
5553               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5554                 image->chromaticity.white_point.x,
5555                 image->chromaticity.white_point.y);
5556               s=newSVpv(color,0);
5557               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5558               continue;
5559             }
5560           if (LocaleCompare(attribute,"width") == 0)
5561             {
5562               if (image != (Image *) NULL)
5563                 s=newSViv((ssize_t) image->columns);
5564               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5565               continue;
5566             }
5567           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5568              attribute);
5569           break;
5570         }
5571         case 'X':
5572         case 'x':
5573         {
5574           if (LocaleCompare(attribute,"x-resolution") == 0)
5575             {
5576               if (image != (Image *) NULL)
5577                 s=newSVnv(image->resolution.x);
5578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5579               continue;
5580             }
5581           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5582             attribute);
5583           break;
5584         }
5585         case 'Y':
5586         case 'y':
5587         {
5588           if (LocaleCompare(attribute,"y-resolution") == 0)
5589             {
5590               if (image != (Image *) NULL)
5591                 s=newSVnv(image->resolution.y);
5592               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5593               continue;
5594             }
5595           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5596             attribute);
5597           break;
5598         }
5599         default:
5600           break;
5601       }
5602       if (image == (Image *) NULL)
5603         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5604           attribute)
5605       else
5606         {
5607           value=GetImageProperty(image,attribute,exception);
5608           if (value != (const char *) NULL)
5609             {
5610               s=newSVpv(value,0);
5611               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5612             }
5613           else
5614             if (*attribute != '%')
5615               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5616                 attribute)
5617             else
5618               {
5619                  char
5620                    *meta;
5621
5622                  meta=InterpretImageProperties(info ? info->image_info :
5623                    (ImageInfo *) NULL,image,attribute,exception);
5624                  s=newSVpv(meta,0);
5625                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5626                  meta=(char *) RelinquishMagickMemory(meta);
5627               }
5628         }
5629     }
5630     exception=DestroyExceptionInfo(exception);
5631     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5632   }
5633 \f
5634 #
5635 ###############################################################################
5636 #                                                                             #
5637 #                                                                             #
5638 #                                                                             #
5639 #   G e t A u t h e n t i c P i x e l s                                       #
5640 #                                                                             #
5641 #                                                                             #
5642 #                                                                             #
5643 ###############################################################################
5644 #
5645 #
5646 void *
5647 GetAuthenticPixels(ref,...)
5648   Image::Magick ref = NO_INIT
5649   ALIAS:
5650     getauthenticpixels = 1
5651     GetImagePixels = 2
5652     getimagepixels = 3
5653   CODE:
5654   {
5655     char
5656       *attribute;
5657
5658     ExceptionInfo
5659       *exception;
5660
5661     Image
5662       *image;
5663
5664     RectangleInfo
5665       region;
5666
5667     ssize_t
5668       i;
5669
5670     struct PackageInfo
5671       *info;
5672
5673     SV
5674       *perl_exception,
5675       *reference;
5676
5677     void
5678       *blob = NULL;
5679
5680     PERL_UNUSED_VAR(ref);
5681     PERL_UNUSED_VAR(ix);
5682     exception=AcquireExceptionInfo();
5683     perl_exception=newSVpv("",0);
5684     if (sv_isobject(ST(0)) == 0)
5685       {
5686         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5687           PackageName);
5688         goto PerlException;
5689       }
5690     reference=SvRV(ST(0));
5691
5692     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5693     if (image == (Image *) NULL)
5694       {
5695         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5696           PackageName);
5697         goto PerlException;
5698       }
5699
5700     region.x=0;
5701     region.y=0;
5702     region.width=image->columns;
5703     region.height=1;
5704     if (items == 1)
5705       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5706     for (i=2; i < items; i+=2)
5707     {
5708       attribute=(char *) SvPV(ST(i-1),na);
5709       switch (*attribute)
5710       {
5711         case 'g':
5712         case 'G':
5713         {
5714           if (LocaleCompare(attribute,"geometry") == 0)
5715             {
5716               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5717               break;
5718             }
5719           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5720             attribute);
5721           break;
5722         }
5723         case 'H':
5724         case 'h':
5725         {
5726           if (LocaleCompare(attribute,"height") == 0)
5727             {
5728               region.height=SvIV(ST(i));
5729               continue;
5730             }
5731           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5732             attribute);
5733           break;
5734         }
5735         case 'X':
5736         case 'x':
5737         {
5738           if (LocaleCompare(attribute,"x") == 0)
5739             {
5740               region.x=SvIV(ST(i));
5741               continue;
5742             }
5743           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5744             attribute);
5745           break;
5746         }
5747         case 'Y':
5748         case 'y':
5749         {
5750           if (LocaleCompare(attribute,"y") == 0)
5751             {
5752               region.y=SvIV(ST(i));
5753               continue;
5754             }
5755           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5756             attribute);
5757           break;
5758         }
5759         case 'W':
5760         case 'w':
5761         {
5762           if (LocaleCompare(attribute,"width") == 0)
5763             {
5764               region.width=SvIV(ST(i));
5765               continue;
5766             }
5767           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5768             attribute);
5769           break;
5770         }
5771       }
5772     }
5773     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5774       region.height,exception);
5775     if (blob != (void *) NULL)
5776       goto PerlEnd;
5777
5778   PerlException:
5779     InheritPerlException(exception,perl_exception);
5780     exception=DestroyExceptionInfo(exception);
5781     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5782
5783   PerlEnd:
5784     RETVAL = blob;
5785   }
5786   OUTPUT:
5787     RETVAL
5788 \f
5789 #
5790 ###############################################################################
5791 #                                                                             #
5792 #                                                                             #
5793 #                                                                             #
5794 #   G e t V i r t u a l P i x e l s                                           #
5795 #                                                                             #
5796 #                                                                             #
5797 #                                                                             #
5798 ###############################################################################
5799 #
5800 #
5801 void *
5802 GetVirtualPixels(ref,...)
5803   Image::Magick ref = NO_INIT
5804   ALIAS:
5805     getvirtualpixels = 1
5806     AcquireImagePixels = 2
5807     acquireimagepixels = 3
5808   CODE:
5809   {
5810     char
5811       *attribute;
5812
5813     const void
5814       *blob = NULL;
5815
5816     ExceptionInfo
5817       *exception;
5818
5819     Image
5820       *image;
5821
5822     RectangleInfo
5823       region;
5824
5825     ssize_t
5826       i;
5827
5828     struct PackageInfo
5829       *info;
5830
5831     SV
5832       *perl_exception,
5833       *reference;
5834
5835     PERL_UNUSED_VAR(ref);
5836     PERL_UNUSED_VAR(ix);
5837     exception=AcquireExceptionInfo();
5838     perl_exception=newSVpv("",0);
5839     if (sv_isobject(ST(0)) == 0)
5840       {
5841         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5842           PackageName);
5843         goto PerlException;
5844       }
5845     reference=SvRV(ST(0));
5846
5847     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5848     if (image == (Image *) NULL)
5849       {
5850         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5851           PackageName);
5852         goto PerlException;
5853       }
5854
5855     region.x=0;
5856     region.y=0;
5857     region.width=image->columns;
5858     region.height=1;
5859     if (items == 1)
5860       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5861     for (i=2; i < items; i+=2)
5862     {
5863       attribute=(char *) SvPV(ST(i-1),na);
5864       switch (*attribute)
5865       {
5866         case 'g':
5867         case 'G':
5868         {
5869           if (LocaleCompare(attribute,"geometry") == 0)
5870             {
5871               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5872               break;
5873             }
5874           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5875             attribute);
5876           break;
5877         }
5878         case 'H':
5879         case 'h':
5880         {
5881           if (LocaleCompare(attribute,"height") == 0)
5882             {
5883               region.height=SvIV(ST(i));
5884               continue;
5885             }
5886           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5887             attribute);
5888           break;
5889         }
5890         case 'X':
5891         case 'x':
5892         {
5893           if (LocaleCompare(attribute,"x") == 0)
5894             {
5895               region.x=SvIV(ST(i));
5896               continue;
5897             }
5898           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5899             attribute);
5900           break;
5901         }
5902         case 'Y':
5903         case 'y':
5904         {
5905           if (LocaleCompare(attribute,"y") == 0)
5906             {
5907               region.y=SvIV(ST(i));
5908               continue;
5909             }
5910           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5911             attribute);
5912           break;
5913         }
5914         case 'W':
5915         case 'w':
5916         {
5917           if (LocaleCompare(attribute,"width") == 0)
5918             {
5919               region.width=SvIV(ST(i));
5920               continue;
5921             }
5922           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5923             attribute);
5924           break;
5925         }
5926       }
5927     }
5928     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5929       region.height,exception);
5930     if (blob != (void *) NULL)
5931       goto PerlEnd;
5932
5933   PerlException:
5934     InheritPerlException(exception,perl_exception);
5935     exception=DestroyExceptionInfo(exception);
5936     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5937
5938   PerlEnd:
5939     RETVAL = (void *) blob;
5940   }
5941   OUTPUT:
5942     RETVAL
5943 \f
5944 #
5945 ###############################################################################
5946 #                                                                             #
5947 #                                                                             #
5948 #                                                                             #
5949 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5950 #                                                                             #
5951 #                                                                             #
5952 #                                                                             #
5953 ###############################################################################
5954 #
5955 #
5956 void *
5957 GetAuthenticMetacontent(ref,...)
5958   Image::Magick ref = NO_INIT
5959   ALIAS:
5960     getauthenticmetacontent = 1
5961     GetMetacontent = 2
5962     getmetacontent = 3
5963   CODE:
5964   {
5965     ExceptionInfo
5966       *exception;
5967
5968     Image
5969       *image;
5970
5971     struct PackageInfo
5972       *info;
5973
5974     SV
5975       *perl_exception,
5976       *reference;
5977
5978     void
5979       *blob = NULL;
5980
5981     PERL_UNUSED_VAR(ref);
5982     PERL_UNUSED_VAR(ix);
5983     exception=AcquireExceptionInfo();
5984     perl_exception=newSVpv("",0);
5985     if (sv_isobject(ST(0)) == 0)
5986       {
5987         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5988           PackageName);
5989         goto PerlException;
5990       }
5991     reference=SvRV(ST(0));
5992
5993     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5994     if (image == (Image *) NULL)
5995       {
5996         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5997           PackageName);
5998         goto PerlException;
5999       }
6000
6001     blob=(void *) GetAuthenticMetacontent(image);
6002     if (blob != (void *) NULL)
6003       goto PerlEnd;
6004
6005   PerlException:
6006     InheritPerlException(exception,perl_exception);
6007     exception=DestroyExceptionInfo(exception);
6008     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6009
6010   PerlEnd:
6011     RETVAL = blob;
6012   }
6013   OUTPUT:
6014     RETVAL
6015 \f
6016 #
6017 ###############################################################################
6018 #                                                                             #
6019 #                                                                             #
6020 #                                                                             #
6021 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6022 #                                                                             #
6023 #                                                                             #
6024 #                                                                             #
6025 ###############################################################################
6026 #
6027 #
6028 void *
6029 GetVirtualMetacontent(ref,...)
6030   Image::Magick ref = NO_INIT
6031   ALIAS:
6032     getvirtualmetacontent = 1
6033   CODE:
6034   {
6035     ExceptionInfo
6036       *exception;
6037
6038     Image
6039       *image;
6040
6041     struct PackageInfo
6042       *info;
6043
6044     SV
6045       *perl_exception,
6046       *reference;
6047
6048     void
6049       *blob = NULL;
6050
6051     PERL_UNUSED_VAR(ref);
6052     PERL_UNUSED_VAR(ix);
6053     exception=AcquireExceptionInfo();
6054     perl_exception=newSVpv("",0);
6055     if (sv_isobject(ST(0)) == 0)
6056       {
6057         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6058           PackageName);
6059         goto PerlException;
6060       }
6061     reference=SvRV(ST(0));
6062
6063     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6064     if (image == (Image *) NULL)
6065       {
6066         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6067           PackageName);
6068         goto PerlException;
6069       }
6070
6071     blob=(void *) GetVirtualMetacontent(image);
6072     if (blob != (void *) NULL)
6073       goto PerlEnd;
6074
6075   PerlException:
6076     InheritPerlException(exception,perl_exception);
6077     exception=DestroyExceptionInfo(exception);
6078     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6079
6080   PerlEnd:
6081     RETVAL = blob;
6082   }
6083   OUTPUT:
6084     RETVAL
6085 \f
6086 #
6087 ###############################################################################
6088 #                                                                             #
6089 #                                                                             #
6090 #                                                                             #
6091 #   H i s t o g r a m                                                         #
6092 #                                                                             #
6093 #                                                                             #
6094 #                                                                             #
6095 ###############################################################################
6096 #
6097 #
6098 void
6099 Histogram(ref,...)
6100   Image::Magick ref=NO_INIT
6101   ALIAS:
6102     HistogramImage = 1
6103     histogram      = 2
6104     histogramimage = 3
6105   PPCODE:
6106   {
6107     AV
6108       *av;
6109
6110     char
6111       message[MaxTextExtent];
6112
6113     PixelInfo
6114       *histogram;
6115
6116     ExceptionInfo
6117       *exception;
6118
6119     Image
6120       *image;
6121
6122     register ssize_t
6123       i;
6124
6125     ssize_t
6126       count;
6127
6128     struct PackageInfo
6129       *info;
6130
6131     SV
6132       *perl_exception,
6133       *reference;
6134
6135     size_t
6136       number_colors;
6137
6138     PERL_UNUSED_VAR(ref);
6139     PERL_UNUSED_VAR(ix);
6140     exception=AcquireExceptionInfo();
6141     perl_exception=newSVpv("",0);
6142     av=NULL;
6143     if (sv_isobject(ST(0)) == 0)
6144       {
6145         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6146           PackageName);
6147         goto PerlException;
6148       }
6149     reference=SvRV(ST(0));
6150     av=newAV();
6151     SvREFCNT_dec(av);
6152     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6153     if (image == (Image *) NULL)
6154       {
6155         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6156           PackageName);
6157         goto PerlException;
6158       }
6159     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6160     count=0;
6161     for ( ; image; image=image->next)
6162     {
6163       histogram=GetImageHistogram(image,&number_colors,exception);
6164       if (histogram == (PixelInfo *) NULL)
6165         continue;
6166       count+=(ssize_t) number_colors;
6167       EXTEND(sp,6*count);
6168       for (i=0; i < (ssize_t) number_colors; i++)
6169       {
6170         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6171           histogram[i].red);
6172         PUSHs(sv_2mortal(newSVpv(message,0)));
6173         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6174           histogram[i].green);
6175         PUSHs(sv_2mortal(newSVpv(message,0)));
6176         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6177           histogram[i].blue);
6178         PUSHs(sv_2mortal(newSVpv(message,0)));
6179         if (image->colorspace == CMYKColorspace)
6180           {
6181             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6182               histogram[i].black);
6183             PUSHs(sv_2mortal(newSVpv(message,0)));
6184           }
6185         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6186           histogram[i].alpha);
6187         PUSHs(sv_2mortal(newSVpv(message,0)));
6188         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6189           histogram[i].count);
6190         PUSHs(sv_2mortal(newSVpv(message,0)));
6191       }
6192       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6193     }
6194
6195   PerlException:
6196     InheritPerlException(exception,perl_exception);
6197     exception=DestroyExceptionInfo(exception);
6198     SvREFCNT_dec(perl_exception);
6199   }
6200 \f
6201 #
6202 ###############################################################################
6203 #                                                                             #
6204 #                                                                             #
6205 #                                                                             #
6206 #   G e t P i x e l                                                           #
6207 #                                                                             #
6208 #                                                                             #
6209 #                                                                             #
6210 ###############################################################################
6211 #
6212 #
6213 void
6214 GetPixel(ref,...)
6215   Image::Magick ref=NO_INIT
6216   ALIAS:
6217     getpixel = 1
6218     getPixel = 2
6219   PPCODE:
6220   {
6221     AV
6222       *av;
6223
6224     char
6225       *attribute;
6226
6227     ExceptionInfo
6228       *exception;
6229
6230     Image
6231       *image;
6232
6233     MagickBooleanType
6234       normalize;
6235
6236     RectangleInfo
6237       region;
6238
6239     register const Quantum
6240       *p;
6241
6242     register ssize_t
6243       i;
6244
6245     ssize_t
6246       option;
6247
6248     struct PackageInfo
6249       *info;
6250
6251     SV
6252       *perl_exception,
6253       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6254
6255     PERL_UNUSED_VAR(ref);
6256     PERL_UNUSED_VAR(ix);
6257     exception=AcquireExceptionInfo();
6258     perl_exception=newSVpv("",0);
6259     reference=SvRV(ST(0));
6260     av=(AV *) reference;
6261     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6262       exception);
6263     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6264     if (image == (Image *) NULL)
6265       {
6266         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6267           PackageName);
6268         goto PerlException;
6269       }
6270     normalize=MagickTrue;
6271     region.x=0;
6272     region.y=0;
6273     region.width=image->columns;
6274     region.height=1;
6275     if (items == 1)
6276       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6277     for (i=2; i < items; i+=2)
6278     {
6279       attribute=(char *) SvPV(ST(i-1),na);
6280       switch (*attribute)
6281       {
6282         case 'C':
6283         case 'c':
6284         {
6285           if (LocaleCompare(attribute,"channel") == 0)
6286             {
6287               ssize_t
6288                 option;
6289
6290               option=ParseChannelOption(SvPV(ST(i),na));
6291               if (option < 0)
6292                 {
6293                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6294                     SvPV(ST(i),na));
6295                   return;
6296                 }
6297               SetPixelChannelMask(image,(ChannelType) option);
6298               break;
6299             }
6300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6301             attribute);
6302           break;
6303         }
6304         case 'g':
6305         case 'G':
6306         {
6307           if (LocaleCompare(attribute,"geometry") == 0)
6308             {
6309               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6310               break;
6311             }
6312           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6313             attribute);
6314           break;
6315         }
6316         case 'N':
6317         case 'n':
6318         {
6319           if (LocaleCompare(attribute,"normalize") == 0)
6320             {
6321               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6322                 SvPV(ST(i),na));
6323               if (option < 0)
6324                 {
6325                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6326                     SvPV(ST(i),na));
6327                   break;
6328                 }
6329              normalize=option != 0 ? MagickTrue : MagickFalse;
6330              break;
6331             }
6332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6333             attribute);
6334           break;
6335         }
6336         case 'x':
6337         case 'X':
6338         {
6339           if (LocaleCompare(attribute,"x") == 0)
6340             {
6341               region.x=SvIV(ST(i));
6342               break;
6343             }
6344           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6345             attribute);
6346           break;
6347         }
6348         case 'y':
6349         case 'Y':
6350         {
6351           if (LocaleCompare(attribute,"y") == 0)
6352             {
6353               region.y=SvIV(ST(i));
6354               break;
6355             }
6356           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6357             attribute);
6358           break;
6359         }
6360         default:
6361         {
6362           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6363             attribute);
6364           break;
6365         }
6366       }
6367     }
6368     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6369     if (p == (const Quantum *) NULL)
6370       PUSHs(&sv_undef);
6371     else
6372       {
6373         double
6374           scale;
6375
6376         scale=1.0;
6377         if (normalize != MagickFalse)
6378           scale=1.0/QuantumRange;
6379         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6380           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6381         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6382           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6383         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6384           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6385         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6386             (image->colorspace == CMYKColorspace))
6387           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6388         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6389           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6390       }
6391
6392   PerlException:
6393     InheritPerlException(exception,perl_exception);
6394     exception=DestroyExceptionInfo(exception);
6395     SvREFCNT_dec(perl_exception);
6396   }
6397 \f
6398 #
6399 ###############################################################################
6400 #                                                                             #
6401 #                                                                             #
6402 #                                                                             #
6403 #   G e t P i x e l s                                                         #
6404 #                                                                             #
6405 #                                                                             #
6406 #                                                                             #
6407 ###############################################################################
6408 #
6409 #
6410 void
6411 GetPixels(ref,...)
6412   Image::Magick ref=NO_INIT
6413   ALIAS:
6414     getpixels = 1
6415     getPixels = 2
6416   PPCODE:
6417   {
6418     AV
6419       *av;
6420
6421     char
6422       *attribute;
6423
6424     const char
6425       *map;
6426
6427     ExceptionInfo
6428       *exception;
6429
6430     Image
6431       *image;
6432
6433     MagickBooleanType
6434       normalize,
6435       status;
6436
6437     RectangleInfo
6438       region;
6439
6440     register ssize_t
6441       i;
6442
6443     ssize_t
6444       option;
6445
6446     struct PackageInfo
6447       *info;
6448
6449     SV
6450       *perl_exception,
6451       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6452
6453     PERL_UNUSED_VAR(ref);
6454     PERL_UNUSED_VAR(ix);
6455     exception=AcquireExceptionInfo();
6456     perl_exception=newSVpv("",0);
6457     reference=SvRV(ST(0));
6458     av=(AV *) reference;
6459     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6460       exception);
6461     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6462     if (image == (Image *) NULL)
6463       {
6464         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6465           PackageName);
6466         goto PerlException;
6467       }
6468     map="RGB";
6469     if (image->alpha_trait == BlendPixelTrait)
6470       map="RGBA";
6471     if (image->colorspace == CMYKColorspace)
6472       {
6473         map="CMYK";
6474         if (image->alpha_trait == BlendPixelTrait)
6475           map="CMYKA";
6476       }
6477     normalize=MagickFalse;
6478     region.x=0;
6479     region.y=0;
6480     region.width=image->columns;
6481     region.height=1;
6482     if (items == 1)
6483       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6484     for (i=2; i < items; i+=2)
6485     {
6486       attribute=(char *) SvPV(ST(i-1),na);
6487       switch (*attribute)
6488       {
6489         case 'g':
6490         case 'G':
6491         {
6492           if (LocaleCompare(attribute,"geometry") == 0)
6493             {
6494               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6495               break;
6496             }
6497           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6498             attribute);
6499           break;
6500         }
6501         case 'H':
6502         case 'h':
6503         {
6504           if (LocaleCompare(attribute,"height") == 0)
6505             {
6506               region.height=SvIV(ST(i));
6507               break;
6508             }
6509           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6510             attribute);
6511           break;
6512         }
6513         case 'M':
6514         case 'm':
6515         {
6516           if (LocaleCompare(attribute,"map") == 0)
6517             {
6518               map=SvPV(ST(i),na);
6519               break;
6520             }
6521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6522             attribute);
6523           break;
6524         }
6525         case 'N':
6526         case 'n':
6527         {
6528           if (LocaleCompare(attribute,"normalize") == 0)
6529             {
6530               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6531                 SvPV(ST(i),na));
6532               if (option < 0)
6533                 {
6534                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6535                     SvPV(ST(i),na));
6536                   break;
6537                 }
6538              normalize=option != 0 ? MagickTrue : MagickFalse;
6539              break;
6540             }
6541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6542             attribute);
6543           break;
6544         }
6545         case 'W':
6546         case 'w':
6547         {
6548           if (LocaleCompare(attribute,"width") == 0)
6549             {
6550               region.width=SvIV(ST(i));
6551               break;
6552             }
6553           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6554             attribute);
6555           break;
6556         }
6557         case 'x':
6558         case 'X':
6559         {
6560           if (LocaleCompare(attribute,"x") == 0)
6561             {
6562               region.x=SvIV(ST(i));
6563               break;
6564             }
6565           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6566             attribute);
6567           break;
6568         }
6569         case 'y':
6570         case 'Y':
6571         {
6572           if (LocaleCompare(attribute,"y") == 0)
6573             {
6574               region.y=SvIV(ST(i));
6575               break;
6576             }
6577           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6578             attribute);
6579           break;
6580         }
6581         default:
6582         {
6583           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6584             attribute);
6585           break;
6586         }
6587       }
6588     }
6589     if (normalize != MagickFalse)
6590       {
6591         float
6592           *pixels;
6593
6594         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6595           region.height*sizeof(*pixels));
6596         if (pixels == (float *) NULL)
6597           {
6598             ThrowPerlException(exception,ResourceLimitError,
6599               "MemoryAllocationFailed",PackageName);
6600             goto PerlException;
6601           }
6602         status=ExportImagePixels(image,region.x,region.y,region.width,
6603           region.height,map,FloatPixel,pixels,exception);
6604         if (status == MagickFalse)
6605           PUSHs(&sv_undef);
6606         else
6607           {
6608             EXTEND(sp,strlen(map)*region.width*region.height);
6609             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6610               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6611           }
6612         pixels=(float *) RelinquishMagickMemory(pixels);
6613       }
6614     else
6615       {
6616         Quantum
6617           *pixels;
6618
6619         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6620           region.height*sizeof(*pixels));
6621         if (pixels == (Quantum *) NULL)
6622           {
6623             ThrowPerlException(exception,ResourceLimitError,
6624               "MemoryAllocationFailed",PackageName);
6625             goto PerlException;
6626           }
6627         status=ExportImagePixels(image,region.x,region.y,region.width,
6628           region.height,map,QuantumPixel,pixels,exception);
6629         if (status == MagickFalse)
6630           PUSHs(&sv_undef);
6631         else
6632           {
6633             EXTEND(sp,strlen(map)*region.width*region.height);
6634             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6635               PUSHs(sv_2mortal(newSViv(pixels[i])));
6636           }
6637         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6638       }
6639
6640   PerlException:
6641     InheritPerlException(exception,perl_exception);
6642     exception=DestroyExceptionInfo(exception);
6643     SvREFCNT_dec(perl_exception);
6644   }
6645 \f
6646 #
6647 ###############################################################################
6648 #                                                                             #
6649 #                                                                             #
6650 #                                                                             #
6651 #   I m a g e T o B l o b                                                     #
6652 #                                                                             #
6653 #                                                                             #
6654 #                                                                             #
6655 ###############################################################################
6656 #
6657 #
6658 void
6659 ImageToBlob(ref,...)
6660   Image::Magick ref=NO_INIT
6661   ALIAS:
6662     ImageToBlob  = 1
6663     imagetoblob  = 2
6664     toblob       = 3
6665     blob         = 4
6666   PPCODE:
6667   {
6668     char
6669       filename[MaxTextExtent];
6670
6671     ExceptionInfo
6672       *exception;
6673
6674     Image
6675       *image,
6676       *next;
6677
6678     register ssize_t
6679       i;
6680
6681     struct PackageInfo
6682       *info,
6683       *package_info;
6684
6685     size_t
6686       length;
6687
6688     ssize_t
6689       scene;
6690
6691     SV
6692       *perl_exception,
6693       *reference;
6694
6695     void
6696       *blob;
6697
6698     PERL_UNUSED_VAR(ref);
6699     PERL_UNUSED_VAR(ix);
6700     exception=AcquireExceptionInfo();
6701     perl_exception=newSVpv("",0);
6702     package_info=(struct PackageInfo *) NULL;
6703     if (sv_isobject(ST(0)) == 0)
6704       {
6705         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6706           PackageName);
6707         goto PerlException;
6708       }
6709     reference=SvRV(ST(0));
6710     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6711     if (image == (Image *) NULL)
6712       {
6713         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6714           PackageName);
6715         goto PerlException;
6716       }
6717     package_info=ClonePackageInfo(info,exception);
6718     for (i=2; i < items; i+=2)
6719       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6720     (void) CopyMagickString(filename,package_info->image_info->filename,
6721       MaxTextExtent);
6722     scene=0;
6723     for (next=image; next; next=next->next)
6724     {
6725       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6726       next->scene=scene++;
6727     }
6728     SetImageInfo(package_info->image_info,(unsigned int)
6729       GetImageListLength(image),exception);
6730     EXTEND(sp,(ssize_t) GetImageListLength(image));
6731     for ( ; image; image=image->next)
6732     {
6733       length=0;
6734       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6735       if (blob != (char *) NULL)
6736         {
6737           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6738           blob=(unsigned char *) RelinquishMagickMemory(blob);
6739         }
6740       if (package_info->image_info->adjoin)
6741         break;
6742     }
6743
6744   PerlException:
6745     if (package_info != (struct PackageInfo *) NULL)
6746       DestroyPackageInfo(package_info);
6747     InheritPerlException(exception,perl_exception);
6748     exception=DestroyExceptionInfo(exception);
6749     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6750   }
6751 \f
6752 #
6753 ###############################################################################
6754 #                                                                             #
6755 #                                                                             #
6756 #                                                                             #
6757 #   L a y e r s                                                               #
6758 #                                                                             #
6759 #                                                                             #
6760 #                                                                             #
6761 ###############################################################################
6762 #
6763 #
6764 void
6765 Layers(ref,...)
6766   Image::Magick ref=NO_INIT
6767   ALIAS:
6768     Layers                = 1
6769     layers           = 2
6770     OptimizeImageLayers   = 3
6771     optimizelayers        = 4
6772     optimizeimagelayers   = 5
6773   PPCODE:
6774   {
6775     AV
6776       *av;
6777
6778     char
6779       *attribute;
6780
6781     CompositeOperator
6782       compose;
6783
6784     ExceptionInfo
6785       *exception;
6786
6787     HV
6788       *hv;
6789
6790     Image
6791       *image,
6792       *layers;
6793
6794     LayerMethod
6795       method;
6796
6797     register ssize_t
6798       i;
6799
6800     ssize_t
6801       option,
6802       sp;
6803
6804     struct PackageInfo
6805       *info;
6806
6807     SV
6808       *av_reference,
6809       *perl_exception,
6810       *reference,
6811       *rv,
6812       *sv;
6813
6814     PERL_UNUSED_VAR(ref);
6815     PERL_UNUSED_VAR(ix);
6816     exception=AcquireExceptionInfo();
6817     perl_exception=newSVpv("",0);
6818     sv=NULL;
6819     if (sv_isobject(ST(0)) == 0)
6820       {
6821         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6822           PackageName);
6823         goto PerlException;
6824       }
6825     reference=SvRV(ST(0));
6826     hv=SvSTASH(reference);
6827     av=newAV();
6828     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6829     SvREFCNT_dec(av);
6830     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6831     if (image == (Image *) NULL)
6832       {
6833         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6834           PackageName);
6835         goto PerlException;
6836       }
6837     compose=image->compose;
6838     method=OptimizeLayer;
6839     for (i=2; i < items; i+=2)
6840     {
6841       attribute=(char *) SvPV(ST(i-1),na);
6842       switch (*attribute)
6843       {
6844         case 'C':
6845         case 'c':
6846         {
6847           if (LocaleCompare(attribute,"compose") == 0)
6848             {
6849               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6850                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6851               if (sp < 0)
6852                 {
6853                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6854                     SvPV(ST(i),na));
6855                   break;
6856                 }
6857               compose=(CompositeOperator) sp;
6858               break;
6859             }
6860           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6861             attribute);
6862           break;
6863         }
6864         case 'M':
6865         case 'm':
6866         {
6867           if (LocaleCompare(attribute,"method") == 0)
6868             {
6869               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6870                 SvPV(ST(i),na));
6871               if (option < 0)
6872                 {
6873                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6874                     SvPV(ST(i),na));
6875                   break;
6876                 }
6877               method=(LayerMethod) option;
6878               break;
6879             }
6880           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6881             attribute);
6882           break;
6883         }
6884         default:
6885         {
6886           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6887             attribute);
6888           break;
6889         }
6890       }
6891     }
6892     layers=(Image *) NULL;
6893     switch (method)
6894     {
6895       case CompareAnyLayer:
6896       case CompareClearLayer:
6897       case CompareOverlayLayer:
6898       default:
6899       {
6900         layers=CompareImagesLayers(image,method,exception);
6901         break;
6902       }
6903       case MergeLayer:
6904       case FlattenLayer:
6905       case MosaicLayer:
6906       {
6907         layers=MergeImageLayers(image,method,exception);
6908         break;
6909       }
6910       case DisposeLayer:
6911       {
6912         layers=DisposeImages(image,exception);
6913         break;
6914       }
6915       case OptimizeImageLayer:
6916       {
6917         layers=OptimizeImageLayers(image,exception);
6918         break;
6919       }
6920       case OptimizePlusLayer:
6921       {
6922         layers=OptimizePlusImageLayers(image,exception);
6923         break;
6924       }
6925       case OptimizeTransLayer:
6926       {
6927         OptimizeImageTransparency(image,exception);
6928         break;
6929       }
6930       case RemoveDupsLayer:
6931       {
6932         RemoveDuplicateLayers(&image,exception);
6933         break;
6934       }
6935       case RemoveZeroLayer:
6936       {
6937         RemoveZeroDelayLayers(&image,exception);
6938         break;
6939       }
6940       case OptimizeLayer:
6941       {
6942         QuantizeInfo
6943           *quantize_info;
6944
6945         /*
6946           General Purpose, GIF Animation Optimizer.
6947         */
6948         layers=CoalesceImages(image,exception);
6949         if (layers == (Image *) NULL)
6950           break;
6951         image=layers;
6952         layers=OptimizeImageLayers(image,exception);
6953         if (layers == (Image *) NULL)
6954           break;
6955         image=DestroyImageList(image);
6956         image=layers;
6957         layers=(Image *) NULL;
6958         OptimizeImageTransparency(image,exception);
6959         quantize_info=AcquireQuantizeInfo(info->image_info);
6960         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
6961         quantize_info=DestroyQuantizeInfo(quantize_info);
6962         break;
6963       }
6964       case CompositeLayer:
6965       {
6966         Image
6967           *source;
6968
6969         RectangleInfo
6970           geometry;
6971
6972         /*
6973           Split image sequence at the first 'NULL:' image.
6974         */
6975         source=image;
6976         while (source != (Image *) NULL)
6977         {
6978           source=GetNextImageInList(source);
6979           if ((source != (Image *) NULL) &&
6980               (LocaleCompare(source->magick,"NULL") == 0))
6981             break;
6982         }
6983         if (source != (Image *) NULL)
6984           {
6985             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6986                 (GetNextImageInList(source) == (Image *) NULL))
6987               source=(Image *) NULL;
6988             else
6989               {
6990                 /*
6991                   Separate the two lists, junk the null: image.
6992                 */
6993                 source=SplitImageList(source->previous);
6994                 DeleteImageFromList(&source);
6995               }
6996           }
6997         if (source == (Image *) NULL)
6998           {
6999             (void) ThrowMagickException(exception,GetMagickModule(),
7000               OptionError,"MissingNullSeparator","layers Composite");
7001             break;
7002           }
7003         /*
7004           Adjust offset with gravity and virtual canvas.
7005         */
7006         SetGeometry(image,&geometry);
7007         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7008         geometry.width=source->page.width != 0 ? source->page.width :
7009           source->columns;
7010         geometry.height=source->page.height != 0 ? source->page.height :
7011           source->rows;
7012         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7013           image->columns,image->page.height != 0 ? image->page.height :
7014           image->rows,image->gravity,&geometry);
7015         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7016         source=DestroyImageList(source);
7017         break;
7018       }
7019     }
7020     if (layers != (Image *) NULL)
7021       image=layers;
7022     if (image == (Image *) NULL)
7023       goto PerlException;
7024     for ( ; image; image=image->next)
7025     {
7026       AddImageToRegistry(sv,image);
7027       rv=newRV(sv);
7028       av_push(av,sv_bless(rv,hv));
7029       SvREFCNT_dec(sv);
7030     }
7031     exception=DestroyExceptionInfo(exception);
7032     ST(0)=av_reference;
7033     SvREFCNT_dec(perl_exception);
7034     XSRETURN(1);
7035
7036   PerlException:
7037     InheritPerlException(exception,perl_exception);
7038     exception=DestroyExceptionInfo(exception);
7039     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7040     SvPOK_on(perl_exception);
7041     ST(0)=sv_2mortal(perl_exception);
7042     XSRETURN(1);
7043   }
7044 \f
7045 #
7046 ###############################################################################
7047 #                                                                             #
7048 #                                                                             #
7049 #                                                                             #
7050 #   M a g i c k T o M i m e                                                   #
7051 #                                                                             #
7052 #                                                                             #
7053 #                                                                             #
7054 ###############################################################################
7055 #
7056 #
7057 SV *
7058 MagickToMime(ref,name)
7059   Image::Magick ref=NO_INIT
7060   char *name
7061   ALIAS:
7062     magicktomime = 1
7063   CODE:
7064   {
7065     char
7066       *mime;
7067
7068     PERL_UNUSED_VAR(ref);
7069     PERL_UNUSED_VAR(ix);
7070     mime=MagickToMime(name);
7071     RETVAL=newSVpv(mime,0);
7072     mime=(char *) RelinquishMagickMemory(mime);
7073   }
7074   OUTPUT:
7075     RETVAL
7076 \f
7077 #
7078 ###############################################################################
7079 #                                                                             #
7080 #                                                                             #
7081 #                                                                             #
7082 #   M o g r i f y                                                             #
7083 #                                                                             #
7084 #                                                                             #
7085 #                                                                             #
7086 ###############################################################################
7087 #
7088 #
7089 void
7090 Mogrify(ref,...)
7091   Image::Magick ref=NO_INIT
7092   ALIAS:
7093     Comment            =   1
7094     CommentImage       =   2
7095     Label              =   3
7096     LabelImage         =   4
7097     AddNoise           =   5
7098     AddNoiseImage      =   6
7099     Colorize           =   7
7100     ColorizeImage      =   8
7101     Border             =   9
7102     BorderImage        =  10
7103     Blur               =  11
7104     BlurImage          =  12
7105     Chop               =  13
7106     ChopImage          =  14
7107     Crop               =  15
7108     CropImage          =  16
7109     Despeckle          =  17
7110     DespeckleImage     =  18
7111     Edge               =  19
7112     EdgeImage          =  20
7113     Emboss             =  21
7114     EmbossImage        =  22
7115     Enhance            =  23
7116     EnhanceImage       =  24
7117     Flip               =  25
7118     FlipImage          =  26
7119     Flop               =  27
7120     FlopImage          =  28
7121     Frame              =  29
7122     FrameImage         =  30
7123     Implode            =  31
7124     ImplodeImage       =  32
7125     Magnify            =  33
7126     MagnifyImage       =  34
7127     MedianFilter       =  35
7128     MedianConvolveImage  =  36
7129     Minify             =  37
7130     MinifyImage        =  38
7131     OilPaint           =  39
7132     OilPaintImage      =  40
7133     ReduceNoise        =  41
7134     ReduceNoiseImage   =  42
7135     Roll               =  43
7136     RollImage          =  44
7137     Rotate             =  45
7138     RotateImage        =  46
7139     Sample             =  47
7140     SampleImage        =  48
7141     Scale              =  49
7142     ScaleImage         =  50
7143     Shade              =  51
7144     ShadeImage         =  52
7145     Sharpen            =  53
7146     SharpenImage       =  54
7147     Shear              =  55
7148     ShearImage         =  56
7149     Spread             =  57
7150     SpreadImage        =  58
7151     Swirl              =  59
7152     SwirlImage         =  60
7153     Resize             =  61
7154     ResizeImage        =  62
7155     Zoom               =  63
7156     ZoomImage          =  64
7157     Annotate           =  65
7158     AnnotateImage      =  66
7159     ColorFloodfill     =  67
7160     ColorFloodfillImage=  68
7161     Composite          =  69
7162     CompositeImage     =  70
7163     Contrast           =  71
7164     ContrastImage      =  72
7165     CycleColormap      =  73
7166     CycleColormapImage =  74
7167     Draw               =  75
7168     DrawImage          =  76
7169     Equalize           =  77
7170     EqualizeImage      =  78
7171     Gamma              =  79
7172     GammaImage         =  80
7173     Map                =  81
7174     MapImage           =  82
7175     MatteFloodfill     =  83
7176     MatteFloodfillImage=  84
7177     Modulate           =  85
7178     ModulateImage      =  86
7179     Negate             =  87
7180     NegateImage        =  88
7181     Normalize          =  89
7182     NormalizeImage     =  90
7183     NumberColors       =  91
7184     NumberColorsImage  =  92
7185     Opaque             =  93
7186     OpaqueImage        =  94
7187     Quantize           =  95
7188     QuantizeImage      =  96
7189     Raise              =  97
7190     RaiseImage         =  98
7191     Segment            =  99
7192     SegmentImage       = 100
7193     Signature          = 101
7194     SignatureImage     = 102
7195     Solarize           = 103
7196     SolarizeImage      = 104
7197     Sync               = 105
7198     SyncImage          = 106
7199     Texture            = 107
7200     TextureImage       = 108
7201     Evaluate           = 109
7202     EvaluateImage      = 110
7203     Transparent        = 111
7204     TransparentImage   = 112
7205     Threshold          = 113
7206     ThresholdImage     = 114
7207     Charcoal           = 115
7208     CharcoalImage      = 116
7209     Trim               = 117
7210     TrimImage          = 118
7211     Wave               = 119
7212     WaveImage          = 120
7213     Separate           = 121
7214     SeparateImage      = 122
7215     Stereo             = 125
7216     StereoImage        = 126
7217     Stegano            = 127
7218     SteganoImage       = 128
7219     Deconstruct        = 129
7220     DeconstructImage   = 130
7221     GaussianBlur       = 131
7222     GaussianBlurImage  = 132
7223     Convolve           = 133
7224     ConvolveImage      = 134
7225     Profile            = 135
7226     ProfileImage       = 136
7227     UnsharpMask        = 137
7228     UnsharpMaskImage   = 138
7229     MotionBlur         = 139
7230     MotionBlurImage    = 140
7231     OrderedDither      = 141
7232     OrderedDitherImage = 142
7233     Shave              = 143
7234     ShaveImage         = 144
7235     Level              = 145
7236     LevelImage         = 146
7237     Clip               = 147
7238     ClipImage          = 148
7239     AffineTransform    = 149
7240     AffineTransformImage = 150
7241     Difference         = 151
7242     DifferenceImage    = 152
7243     AdaptiveThreshold  = 153
7244     AdaptiveThresholdImage = 154
7245     Resample           = 155
7246     ResampleImage      = 156
7247     Describe           = 157
7248     DescribeImage      = 158
7249     BlackThreshold     = 159
7250     BlackThresholdImage= 160
7251     WhiteThreshold     = 161
7252     WhiteThresholdImage= 162
7253     RadialBlur         = 163
7254     RadialBlurImage    = 164
7255     Thumbnail          = 165
7256     ThumbnailImage     = 166
7257     Strip              = 167
7258     StripImage         = 168
7259     Tint               = 169
7260     TintImage          = 170
7261     Channel            = 171
7262     ChannelImage       = 172
7263     Splice             = 173
7264     SpliceImage        = 174
7265     Posterize          = 175
7266     PosterizeImage     = 176
7267     Shadow             = 177
7268     ShadowImage        = 178
7269     Identify           = 179
7270     IdentifyImage      = 180
7271     SepiaTone          = 181
7272     SepiaToneImage     = 182
7273     SigmoidalContrast  = 183
7274     SigmoidalContrastImage = 184
7275     Extent             = 185
7276     ExtentImage        = 186
7277     Vignette           = 187
7278     VignetteImage      = 188
7279     ContrastStretch    = 189
7280     ContrastStretchImage = 190
7281     Sans0              = 191
7282     Sans0Image         = 192
7283     Sans1              = 193
7284     Sans1Image         = 194
7285     AdaptiveSharpen    = 195
7286     AdaptiveSharpenImage = 196
7287     Transpose          = 197
7288     TransposeImage     = 198
7289     Transverse         = 199
7290     TransverseImage    = 200
7291     AutoOrient         = 201
7292     AutoOrientImage    = 202
7293     AdaptiveBlur       = 203
7294     AdaptiveBlurImage  = 204
7295     Sketch             = 205
7296     SketchImage        = 206
7297     UniqueColors       = 207
7298     UniqueColorsImage  = 208
7299     AdaptiveResize     = 209
7300     AdaptiveResizeImage= 210
7301     ClipMask           = 211
7302     ClipMaskImage      = 212
7303     LinearStretch      = 213
7304     LinearStretchImage = 214
7305     ColorMatrix        = 215
7306     ColorMatrixImage   = 216
7307     Mask               = 217
7308     MaskImage          = 218
7309     Polaroid           = 219
7310     PolaroidImage      = 220
7311     FloodfillPaint     = 221
7312     FloodfillPaintImage= 222
7313     Distort            = 223
7314     DistortImage       = 224
7315     Clut               = 225
7316     ClutImage          = 226
7317     LiquidRescale      = 227
7318     LiquidRescaleImage = 228
7319     Encipher           = 229
7320     EncipherImage      = 230
7321     Decipher           = 231
7322     DecipherImage      = 232
7323     Deskew             = 233
7324     DeskewImage        = 234
7325     Remap              = 235
7326     RemapImage         = 236
7327     SparseColor        = 237
7328     SparseColorImage   = 238
7329     Function           = 239
7330     FunctionImage      = 240
7331     SelectiveBlur      = 241
7332     SelectiveBlurImage = 242
7333     HaldClut           = 243
7334     HaldClutImage      = 244
7335     BlueShift          = 245
7336     BlueShiftImage     = 246
7337     ForwardFourierTransform  = 247
7338     ForwardFourierTransformImage = 248
7339     InverseFourierTransform = 249
7340     InverseFourierTransformImage = 250
7341     ColorDecisionList  = 251
7342     ColorDecisionListImage = 252
7343     AutoGamma          = 253
7344     AutoGammaImage     = 254
7345     AutoLevel          = 255
7346     AutoLevelImage     = 256
7347     LevelColors        = 257
7348     LevelImageColors   = 258
7349     Clamp              = 259
7350     ClampImage         = 260
7351     BrightnessContrast = 261
7352     BrightnessContrastImage = 262
7353     Morphology         = 263
7354     MorphologyImage    = 264
7355     Color              = 265
7356     ColorImage         = 266
7357     Mode               = 267
7358     ModeImage          = 268
7359     Statistic          = 269
7360     StatisticImage     = 270
7361     Perceptible        = 271
7362     PerceptibleImage   = 272
7363     Poly               = 273
7364     PolyImage          = 274
7365     MogrifyRegion      = 666
7366   PPCODE:
7367   {
7368     AffineMatrix
7369       affine,
7370       current;
7371
7372     char
7373       attribute_flag[MaxArguments],
7374       message[MaxTextExtent];
7375
7376     ChannelType
7377       channel,
7378       channel_mask;
7379
7380     CompositeOperator
7381       compose;
7382
7383     const char
7384       *attribute,
7385       *value;
7386
7387     double
7388       angle;
7389
7390     ExceptionInfo
7391       *exception;
7392
7393     GeometryInfo
7394       geometry_info;
7395
7396     Image
7397       *image,
7398       *next,
7399       *region_image;
7400
7401     MagickBooleanType
7402       status;
7403
7404     MagickStatusType
7405       flags;
7406
7407     PixelInfo
7408       fill_color;
7409
7410     RectangleInfo
7411       geometry,
7412       region_info;
7413
7414     register ssize_t
7415       i;
7416
7417     ssize_t
7418       base,
7419       j,
7420       number_images;
7421
7422     struct Methods
7423       *rp;
7424
7425     struct PackageInfo
7426       *info;
7427
7428     SV
7429       *perl_exception,
7430       **pv,
7431       *reference,
7432       **reference_vector;
7433
7434     struct ArgumentList
7435       argument_list[MaxArguments];
7436
7437     PERL_UNUSED_VAR(ref);
7438     PERL_UNUSED_VAR(ix);
7439     exception=AcquireExceptionInfo();
7440     perl_exception=newSVpv("",0);
7441     reference_vector=NULL;
7442     region_image=NULL;
7443     number_images=0;
7444     base=2;
7445     if (sv_isobject(ST(0)) == 0)
7446       {
7447         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7448           PackageName);
7449         goto PerlException;
7450       }
7451     reference=SvRV(ST(0));
7452     region_info.width=0;
7453     region_info.height=0;
7454     region_info.x=0;
7455     region_info.y=0;
7456     region_image=(Image *) NULL;
7457     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7458     if (ix && (ix != 666))
7459       {
7460         /*
7461           Called as Method(...)
7462         */
7463         ix=(ix+1)/2;
7464         rp=(&Methods[ix-1]);
7465         attribute=rp->name;
7466       }
7467     else
7468       {
7469         /*
7470           Called as Mogrify("Method",...)
7471         */
7472         attribute=(char *) SvPV(ST(1),na);
7473         if (ix)
7474           {
7475             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7476             attribute=(char *) SvPV(ST(2),na);
7477             base++;
7478           }
7479         for (rp=Methods; ; rp++)
7480         {
7481           if (rp >= EndOf(Methods))
7482             {
7483               ThrowPerlException(exception,OptionError,
7484                 "UnrecognizedPerlMagickMethod",attribute);
7485               goto PerlException;
7486             }
7487           if (strEQcase(attribute,rp->name))
7488             break;
7489         }
7490         ix=rp-Methods+1;
7491         base++;
7492       }
7493     if (image == (Image *) NULL)
7494       {
7495         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7496         goto PerlException;
7497       }
7498     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7499     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7500     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7501     {
7502       Arguments
7503         *pp,
7504         *qq;
7505
7506       ssize_t
7507         ssize_test;
7508
7509       struct ArgumentList
7510         *al;
7511
7512       SV
7513         *sv;
7514
7515       sv=NULL;
7516       ssize_test=0;
7517       pp=(Arguments *) NULL;
7518       qq=rp->arguments;
7519       if (i == items)
7520         {
7521           pp=rp->arguments,
7522           sv=ST(i-1);
7523         }
7524       else
7525         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7526         {
7527           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7528             break;
7529           if (strEQcase(attribute,qq->method) > ssize_test)
7530             {
7531               pp=qq;
7532               ssize_test=strEQcase(attribute,qq->method);
7533             }
7534         }
7535       if (pp == (Arguments *) NULL)
7536         {
7537           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7538             attribute);
7539           goto continue_outer_loop;
7540         }
7541       al=(&argument_list[pp-rp->arguments]);
7542       switch (pp->type)
7543       {
7544         case ArrayReference:
7545         {
7546           if (SvTYPE(sv) != SVt_RV)
7547             {
7548               (void) FormatLocaleString(message,MaxTextExtent,
7549                 "invalid %.60s value",pp->method);
7550               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7551               goto continue_outer_loop;
7552             }
7553           al->array_reference=SvRV(sv);
7554           break;
7555         }
7556         case RealReference:
7557         {
7558           al->real_reference=SvNV(sv);
7559           break;
7560         }
7561         case FileReference:
7562         {
7563           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7564           break;
7565         }
7566         case ImageReference:
7567         {
7568           if (!sv_isobject(sv) ||
7569               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7570                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7571             {
7572               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7573                 PackageName);
7574               goto PerlException;
7575             }
7576           break;
7577         }
7578         case IntegerReference:
7579         {
7580           al->integer_reference=SvIV(sv);
7581           break;
7582         }
7583         case StringReference:
7584         {
7585           al->string_reference=(char *) SvPV(sv,al->length);
7586           if (sv_isobject(sv))
7587             al->image_reference=SetupList(aTHX_ SvRV(sv),
7588               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7589           break;
7590         }
7591         default:
7592         {
7593           /*
7594             Is a string; look up name.
7595           */
7596           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7597             {
7598               al->string_reference=(char *) SvPV(sv,al->length);
7599               al->integer_reference=(-1);
7600               break;
7601             }
7602           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7603             MagickFalse,SvPV(sv,na));
7604           if (pp->type == MagickChannelOptions)
7605             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7606           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7607             {
7608               (void) FormatLocaleString(message,MaxTextExtent,
7609                 "invalid %.60s value",pp->method);
7610               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7611               goto continue_outer_loop;
7612             }
7613           break;
7614         }
7615       }
7616       attribute_flag[pp-rp->arguments]++;
7617       continue_outer_loop: ;
7618     }
7619     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7620     pv=reference_vector;
7621     SetGeometryInfo(&geometry_info);
7622     channel=DefaultChannels;
7623     for (next=image; next; next=next->next)
7624     {
7625       image=next;
7626       SetGeometry(image,&geometry);
7627       if ((region_info.width*region_info.height) != 0)
7628         {
7629           region_image=image;
7630           image=CropImage(image,&region_info,exception);
7631         }
7632       switch (ix)
7633       {
7634         default:
7635         {
7636           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7637           ThrowPerlException(exception,OptionError,
7638             "UnrecognizedPerlMagickMethod",message);
7639           goto PerlException;
7640         }
7641         case 1:  /* Comment */
7642         {
7643           if (attribute_flag[0] == 0)
7644             argument_list[0].string_reference=(char *) NULL;
7645           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7646             info ? info->image_info : (ImageInfo *) NULL,image,
7647             argument_list[0].string_reference,exception),exception);
7648           break;
7649         }
7650         case 2:  /* Label */
7651         {
7652           if (attribute_flag[0] == 0)
7653             argument_list[0].string_reference=(char *) NULL;
7654           (void) SetImageProperty(image,"label",InterpretImageProperties(
7655             info ? info->image_info : (ImageInfo *) NULL,image,
7656             argument_list[0].string_reference,exception),exception);
7657           break;
7658         }
7659         case 3:  /* AddNoise */
7660         {
7661           double
7662             attenuate;
7663
7664           if (attribute_flag[0] == 0)
7665             argument_list[0].integer_reference=UniformNoise;
7666           attenuate=1.0;
7667           if (attribute_flag[1] != 0)
7668             attenuate=argument_list[1].real_reference;
7669           if (attribute_flag[2] != 0)
7670             channel=(ChannelType) argument_list[2].integer_reference;
7671           channel_mask=SetImageChannelMask(image,channel);
7672           image=AddNoiseImage(image,(NoiseType)
7673             argument_list[0].integer_reference,attenuate,exception);
7674           if (image != (Image *) NULL)
7675             (void) SetImageChannelMask(image,channel_mask);
7676           break;
7677         }
7678         case 4:  /* Colorize */
7679         {
7680           PixelInfo
7681             target;
7682
7683           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7684             0,0,&target,exception);
7685           if (attribute_flag[0] != 0)
7686             (void) QueryColorCompliance(argument_list[0].string_reference,
7687               AllCompliance,&target,exception);
7688           if (attribute_flag[1] == 0)
7689             argument_list[1].string_reference="100%";
7690           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7691             exception);
7692           break;
7693         }
7694         case 5:  /* Border */
7695         {
7696           CompositeOperator
7697             compose;
7698
7699           geometry.width=0;
7700           geometry.height=0;
7701           if (attribute_flag[0] != 0)
7702             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7703               &geometry,exception);
7704           if (attribute_flag[1] != 0)
7705             geometry.width=argument_list[1].integer_reference;
7706           if (attribute_flag[2] != 0)
7707             geometry.height=argument_list[2].integer_reference;
7708           if (attribute_flag[3] != 0)
7709             QueryColorCompliance(argument_list[3].string_reference,
7710               AllCompliance,&image->border_color,exception);
7711           if (attribute_flag[4] != 0)
7712             QueryColorCompliance(argument_list[4].string_reference,
7713               AllCompliance,&image->border_color,exception);
7714           if (attribute_flag[5] != 0)
7715             QueryColorCompliance(argument_list[5].string_reference,
7716               AllCompliance,&image->border_color,exception);
7717           compose=image->compose;
7718           if (attribute_flag[6] != 0)
7719             compose=(CompositeOperator) argument_list[6].integer_reference;
7720           image=BorderImage(image,&geometry,compose,exception);
7721           break;
7722         }
7723         case 6:  /* Blur */
7724         {
7725           if (attribute_flag[0] != 0)
7726             {
7727               flags=ParseGeometry(argument_list[0].string_reference,
7728                 &geometry_info);
7729               if ((flags & SigmaValue) == 0)
7730                 geometry_info.sigma=1.0;
7731             }
7732           if (attribute_flag[1] != 0)
7733             geometry_info.rho=argument_list[1].real_reference;
7734           if (attribute_flag[2] != 0)
7735             geometry_info.sigma=argument_list[2].real_reference;
7736           if (attribute_flag[3] != 0)
7737             channel=(ChannelType) argument_list[3].integer_reference;
7738           channel_mask=SetImageChannelMask(image,channel);
7739           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7740             exception);
7741           if (image != (Image *) NULL)
7742             (void) SetImageChannelMask(image,channel_mask);
7743           break;
7744         }
7745         case 7:  /* Chop */
7746         {
7747           if (attribute_flag[0] != 0)
7748             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7749               &geometry,exception);
7750           if (attribute_flag[1] != 0)
7751             geometry.width=argument_list[1].integer_reference;
7752           if (attribute_flag[2] != 0)
7753             geometry.height=argument_list[2].integer_reference;
7754           if (attribute_flag[3] != 0)
7755             geometry.x=argument_list[3].integer_reference;
7756           if (attribute_flag[4] != 0)
7757             geometry.y=argument_list[4].integer_reference;
7758           image=ChopImage(image,&geometry,exception);
7759           break;
7760         }
7761         case 8:  /* Crop */
7762         {
7763           if (attribute_flag[6] != 0)
7764             image->gravity=(GravityType) argument_list[6].integer_reference;
7765           if (attribute_flag[0] != 0)
7766             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7767               &geometry,exception);
7768           if (attribute_flag[1] != 0)
7769             geometry.width=argument_list[1].integer_reference;
7770           if (attribute_flag[2] != 0)
7771             geometry.height=argument_list[2].integer_reference;
7772           if (attribute_flag[3] != 0)
7773             geometry.x=argument_list[3].integer_reference;
7774           if (attribute_flag[4] != 0)
7775             geometry.y=argument_list[4].integer_reference;
7776           if (attribute_flag[5] != 0)
7777             image->fuzz=StringToDoubleInterval(
7778               argument_list[5].string_reference,(double) QuantumRange+1.0);
7779           image=CropImage(image,&geometry,exception);
7780           break;
7781         }
7782         case 9:  /* Despeckle */
7783         {
7784           image=DespeckleImage(image,exception);
7785           break;
7786         }
7787         case 10:  /* Edge */
7788         {
7789           if (attribute_flag[0] != 0)
7790             geometry_info.rho=argument_list[0].real_reference;
7791           image=EdgeImage(image,geometry_info.rho,geometry_info.sigma,
7792             exception);
7793           break;
7794         }
7795         case 11:  /* Emboss */
7796         {
7797           if (attribute_flag[0] != 0)
7798             {
7799               flags=ParseGeometry(argument_list[0].string_reference,
7800                 &geometry_info);
7801               if ((flags & SigmaValue) == 0)
7802                 geometry_info.sigma=1.0;
7803             }
7804           if (attribute_flag[1] != 0)
7805             geometry_info.rho=argument_list[1].real_reference;
7806           if (attribute_flag[2] != 0)
7807             geometry_info.sigma=argument_list[2].real_reference;
7808           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7809             exception);
7810           break;
7811         }
7812         case 12:  /* Enhance */
7813         {
7814           image=EnhanceImage(image,exception);
7815           break;
7816         }
7817         case 13:  /* Flip */
7818         {
7819           image=FlipImage(image,exception);
7820           break;
7821         }
7822         case 14:  /* Flop */
7823         {
7824           image=FlopImage(image,exception);
7825           break;
7826         }
7827         case 15:  /* Frame */
7828         {
7829           CompositeOperator
7830             compose;
7831
7832           FrameInfo
7833             frame_info;
7834
7835           if (attribute_flag[0] != 0)
7836             {
7837               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7838                 &geometry,exception);
7839               frame_info.width=geometry.width;
7840               frame_info.height=geometry.height;
7841               frame_info.outer_bevel=geometry.x;
7842               frame_info.inner_bevel=geometry.y;
7843             }
7844           if (attribute_flag[1] != 0)
7845             frame_info.width=argument_list[1].integer_reference;
7846           if (attribute_flag[2] != 0)
7847             frame_info.height=argument_list[2].integer_reference;
7848           if (attribute_flag[3] != 0)
7849             frame_info.inner_bevel=argument_list[3].integer_reference;
7850           if (attribute_flag[4] != 0)
7851             frame_info.outer_bevel=argument_list[4].integer_reference;
7852           if (attribute_flag[5] != 0)
7853             QueryColorCompliance(argument_list[5].string_reference,
7854               AllCompliance,&fill_color,exception);
7855           if (attribute_flag[6] != 0)
7856             QueryColorCompliance(argument_list[6].string_reference,
7857               AllCompliance,&fill_color,exception);
7858           frame_info.x=(ssize_t) frame_info.width;
7859           frame_info.y=(ssize_t) frame_info.height;
7860           frame_info.width=image->columns+2*frame_info.x;
7861           frame_info.height=image->rows+2*frame_info.y;
7862           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7863             image->matte_color=fill_color;
7864           compose=image->compose;
7865           if (attribute_flag[7] != 0)
7866             compose=(CompositeOperator) argument_list[7].integer_reference;
7867           image=FrameImage(image,&frame_info,compose,exception);
7868           break;
7869         }
7870         case 16:  /* Implode */
7871         {
7872           PixelInterpolateMethod
7873             method;
7874
7875           if (attribute_flag[0] == 0)
7876             argument_list[0].real_reference=0.5;
7877           method=UndefinedInterpolatePixel;
7878           if (attribute_flag[1] != 0)
7879             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
7880           image=ImplodeImage(image,argument_list[0].real_reference,
7881             method,exception);
7882           break;
7883         }
7884         case 17:  /* Magnify */
7885         {
7886           image=MagnifyImage(image,exception);
7887           break;
7888         }
7889         case 18:  /* MedianFilter */
7890         {
7891           if (attribute_flag[0] != 0)
7892             {
7893               flags=ParseGeometry(argument_list[0].string_reference,
7894                 &geometry_info);
7895               if ((flags & SigmaValue) == 0)
7896                 geometry_info.sigma=geometry_info.rho;
7897             }
7898           if (attribute_flag[1] != 0)
7899             geometry_info.rho=argument_list[1].real_reference;
7900           if (attribute_flag[2] != 0)
7901             geometry_info.sigma=argument_list[2].real_reference;
7902           if (attribute_flag[3] != 0)
7903             channel=(ChannelType) argument_list[3].integer_reference;
7904           channel_mask=SetImageChannelMask(image,channel);
7905           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
7906             (size_t) geometry_info.sigma,exception);
7907           if (image != (Image *) NULL)
7908             (void) SetImageChannelMask(image,channel_mask);
7909           break;
7910         }
7911         case 19:  /* Minify */
7912         {
7913           image=MinifyImage(image,exception);
7914           break;
7915         }
7916         case 20:  /* OilPaint */
7917         {
7918           if (attribute_flag[0] == 0)
7919             argument_list[0].real_reference=0.0;
7920           if (attribute_flag[1] == 0)
7921             argument_list[1].real_reference=1.0;
7922           image=OilPaintImage(image,argument_list[0].real_reference,
7923             argument_list[1].real_reference,exception);
7924           break;
7925         }
7926         case 21:  /* ReduceNoise */
7927         {
7928           if (attribute_flag[0] != 0)
7929             {
7930               flags=ParseGeometry(argument_list[0].string_reference,
7931                 &geometry_info);
7932               if ((flags & SigmaValue) == 0)
7933                 geometry_info.sigma=1.0;
7934             }
7935           if (attribute_flag[1] != 0)
7936             geometry_info.rho=argument_list[1].real_reference;
7937           if (attribute_flag[2] != 0)
7938             geometry_info.sigma=argument_list[2].real_reference;
7939           if (attribute_flag[3] != 0)
7940             channel=(ChannelType) argument_list[3].integer_reference;
7941           channel_mask=SetImageChannelMask(image,channel);
7942           image=StatisticImage(image,NonpeakStatistic,(size_t)
7943             geometry_info.rho,(size_t) geometry_info.sigma,exception);
7944           if (image != (Image *) NULL)
7945             (void) SetImageChannelMask(image,channel_mask);
7946           break;
7947         }
7948         case 22:  /* Roll */
7949         {
7950           if (attribute_flag[0] != 0)
7951             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7952               &geometry,exception);
7953           if (attribute_flag[1] != 0)
7954             geometry.x=argument_list[1].integer_reference;
7955           if (attribute_flag[2] != 0)
7956             geometry.y=argument_list[2].integer_reference;
7957           image=RollImage(image,geometry.x,geometry.y,exception);
7958           break;
7959         }
7960         case 23:  /* Rotate */
7961         {
7962           if (attribute_flag[0] == 0)
7963             argument_list[0].real_reference=90.0;
7964           if (attribute_flag[1] != 0)
7965             {
7966               QueryColorCompliance(argument_list[1].string_reference,
7967                 AllCompliance,&image->background_color,exception);
7968               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
7969                   (image->alpha_trait != BlendPixelTrait))
7970                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
7971             }
7972           image=RotateImage(image,argument_list[0].real_reference,exception);
7973           break;
7974         }
7975         case 24:  /* Sample */
7976         {
7977           if (attribute_flag[0] != 0)
7978             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7979               &geometry,exception);
7980           if (attribute_flag[1] != 0)
7981             geometry.width=argument_list[1].integer_reference;
7982           if (attribute_flag[2] != 0)
7983             geometry.height=argument_list[2].integer_reference;
7984           image=SampleImage(image,geometry.width,geometry.height,exception);
7985           break;
7986         }
7987         case 25:  /* Scale */
7988         {
7989           if (attribute_flag[0] != 0)
7990             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7991               &geometry,exception);
7992           if (attribute_flag[1] != 0)
7993             geometry.width=argument_list[1].integer_reference;
7994           if (attribute_flag[2] != 0)
7995             geometry.height=argument_list[2].integer_reference;
7996           image=ScaleImage(image,geometry.width,geometry.height,exception);
7997           break;
7998         }
7999         case 26:  /* Shade */
8000         {
8001           if (attribute_flag[0] != 0)
8002             {
8003               flags=ParseGeometry(argument_list[0].string_reference,
8004                 &geometry_info);
8005               if ((flags & SigmaValue) == 0)
8006                 geometry_info.sigma=0.0;
8007             }
8008           if (attribute_flag[1] != 0)
8009             geometry_info.rho=argument_list[1].real_reference;
8010           if (attribute_flag[2] != 0)
8011             geometry_info.sigma=argument_list[2].real_reference;
8012           image=ShadeImage(image,
8013             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8014             geometry_info.rho,geometry_info.sigma,exception);
8015           break;
8016         }
8017         case 27:  /* Sharpen */
8018         {
8019           if (attribute_flag[0] != 0)
8020             {
8021               flags=ParseGeometry(argument_list[0].string_reference,
8022                 &geometry_info);
8023               if ((flags & SigmaValue) == 0)
8024                 geometry_info.sigma=1.0;
8025             }
8026           if (attribute_flag[1] != 0)
8027             geometry_info.rho=argument_list[1].real_reference;
8028           if (attribute_flag[2] != 0)
8029             geometry_info.sigma=argument_list[2].real_reference;
8030           if (attribute_flag[3] != 0)
8031             channel=(ChannelType) argument_list[3].integer_reference;
8032           channel_mask=SetImageChannelMask(image,channel);
8033           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8034             exception);
8035           if (image != (Image *) NULL)
8036             (void) SetImageChannelMask(image,channel_mask);
8037           break;
8038         }
8039         case 28:  /* Shear */
8040         {
8041           if (attribute_flag[0] != 0)
8042             {
8043               flags=ParseGeometry(argument_list[0].string_reference,
8044                 &geometry_info);
8045               if ((flags & SigmaValue) == 0)
8046                 geometry_info.sigma=geometry_info.rho;
8047             }
8048           if (attribute_flag[1] != 0)
8049             geometry_info.rho=argument_list[1].real_reference;
8050           if (attribute_flag[2] != 0)
8051             geometry_info.sigma=argument_list[2].real_reference;
8052           if (attribute_flag[3] != 0)
8053             QueryColorCompliance(argument_list[3].string_reference,
8054               AllCompliance,&image->background_color,exception);
8055           if (attribute_flag[4] != 0)
8056             QueryColorCompliance(argument_list[4].string_reference,
8057               AllCompliance,&image->background_color,exception);
8058           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8059             exception);
8060           break;
8061         }
8062         case 29:  /* Spread */
8063         {
8064           PixelInterpolateMethod
8065             method;
8066
8067           if (attribute_flag[0] == 0)
8068             argument_list[0].real_reference=1.0;
8069           method=UndefinedInterpolatePixel;
8070           if (attribute_flag[1] != 0)
8071             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8072           image=SpreadImage(image,argument_list[0].real_reference,method,
8073             exception);
8074           break;
8075         }
8076         case 30:  /* Swirl */
8077         {
8078           PixelInterpolateMethod
8079             method;
8080
8081           if (attribute_flag[0] == 0)
8082             argument_list[0].real_reference=50.0;
8083           method=UndefinedInterpolatePixel;
8084           if (attribute_flag[1] != 0)
8085             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8086           image=SwirlImage(image,argument_list[0].real_reference,
8087             method,exception);
8088           break;
8089         }
8090         case 31:  /* Resize */
8091         case 32:  /* Zoom */
8092         {
8093           if (attribute_flag[0] != 0)
8094             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8095               &geometry,exception);
8096           if (attribute_flag[1] != 0)
8097             geometry.width=argument_list[1].integer_reference;
8098           if (attribute_flag[2] != 0)
8099             geometry.height=argument_list[2].integer_reference;
8100           if (attribute_flag[3] == 0)
8101             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8102           if (attribute_flag[4] != 0)
8103             SetImageArtifact(image,"filter:support",
8104               argument_list[4].string_reference);
8105           image=ResizeImage(image,geometry.width,geometry.height,
8106             (FilterTypes) argument_list[3].integer_reference,
8107             exception);
8108           break;
8109         }
8110         case 33:  /* Annotate */
8111         {
8112           DrawInfo
8113             *draw_info;
8114
8115           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8116             (DrawInfo *) NULL);
8117           if (attribute_flag[0] != 0)
8118             {
8119               char
8120                 *text;
8121
8122               text=InterpretImageProperties(info ? info->image_info :
8123                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8124                 exception);
8125               (void) CloneString(&draw_info->text,text);
8126               text=DestroyString(text);
8127             }
8128           if (attribute_flag[1] != 0)
8129             (void) CloneString(&draw_info->font,
8130               argument_list[1].string_reference);
8131           if (attribute_flag[2] != 0)
8132             draw_info->pointsize=argument_list[2].real_reference;
8133           if (attribute_flag[3] != 0)
8134             (void) CloneString(&draw_info->density,
8135               argument_list[3].string_reference);
8136           if (attribute_flag[4] != 0)
8137             (void) QueryColorCompliance(argument_list[4].string_reference,
8138               AllCompliance,&draw_info->undercolor,exception);
8139           if (attribute_flag[5] != 0)
8140             {
8141               (void) QueryColorCompliance(argument_list[5].string_reference,
8142                 AllCompliance,&draw_info->stroke,exception);
8143               if (argument_list[5].image_reference != (Image *) NULL)
8144                 draw_info->stroke_pattern=CloneImage(
8145                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8146             }
8147           if (attribute_flag[6] != 0)
8148             {
8149               (void) QueryColorCompliance(argument_list[6].string_reference,
8150                 AllCompliance,&draw_info->fill,exception);
8151               if (argument_list[6].image_reference != (Image *) NULL)
8152                 draw_info->fill_pattern=CloneImage(
8153                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8154             }
8155           if (attribute_flag[7] != 0)
8156             {
8157               (void) CloneString(&draw_info->geometry,
8158                 argument_list[7].string_reference);
8159               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8160                 &geometry,exception);
8161               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8162                 geometry_info.sigma=geometry_info.xi;
8163             }
8164           if (attribute_flag[8] != 0)
8165             (void) QueryColorCompliance(argument_list[8].string_reference,
8166               AllCompliance,&draw_info->fill,exception);
8167           if (attribute_flag[11] != 0)
8168             draw_info->gravity=(GravityType)
8169               argument_list[11].integer_reference;
8170           if (attribute_flag[25] != 0)
8171             {
8172               AV
8173                 *av;
8174
8175               av=(AV *) argument_list[25].array_reference;
8176               if ((av_len(av) != 3) && (av_len(av) != 5))
8177                 {
8178                   ThrowPerlException(exception,OptionError,
8179                     "affine matrix must have 4 or 6 elements",PackageName);
8180                   goto PerlException;
8181                 }
8182               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8183               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8184               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8185               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8186               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8187                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8188                 {
8189                   ThrowPerlException(exception,OptionError,
8190                     "affine matrix is singular",PackageName);
8191                    goto PerlException;
8192                 }
8193               if (av_len(av) == 5)
8194                 {
8195                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8196                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8197                 }
8198             }
8199           for (j=12; j < 17; j++)
8200           {
8201             if (attribute_flag[j] == 0)
8202               continue;
8203             value=argument_list[j].string_reference;
8204             angle=argument_list[j].real_reference;
8205             current=draw_info->affine;
8206             GetAffineMatrix(&affine);
8207             switch (j)
8208             {
8209               case 12:
8210               {
8211                 /*
8212                   Translate.
8213                 */
8214                 flags=ParseGeometry(value,&geometry_info);
8215                 affine.tx=geometry_info.xi;
8216                 affine.ty=geometry_info.psi;
8217                 if ((flags & PsiValue) == 0)
8218                   affine.ty=affine.tx;
8219                 break;
8220               }
8221               case 13:
8222               {
8223                 /*
8224                   Scale.
8225                 */
8226                 flags=ParseGeometry(value,&geometry_info);
8227                 affine.sx=geometry_info.rho;
8228                 affine.sy=geometry_info.sigma;
8229                 if ((flags & SigmaValue) == 0)
8230                   affine.sy=affine.sx;
8231                 break;
8232               }
8233               case 14:
8234               {
8235                 /*
8236                   Rotate.
8237                 */
8238                 if (angle == 0.0)
8239                   break;
8240                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8241                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8242                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8243                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8244                 break;
8245               }
8246               case 15:
8247               {
8248                 /*
8249                   SkewX.
8250                 */
8251                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8252                 break;
8253               }
8254               case 16:
8255               {
8256                 /*
8257                   SkewY.
8258                 */
8259                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8260                 break;
8261               }
8262             }
8263             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8264             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8265             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8266             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8267             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8268               current.tx;
8269             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8270               current.ty;
8271           }
8272           if (attribute_flag[9] == 0)
8273             argument_list[9].real_reference=0.0;
8274           if (attribute_flag[10] == 0)
8275             argument_list[10].real_reference=0.0;
8276           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8277             {
8278               char
8279                 geometry[MaxTextExtent];
8280
8281               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8282                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8283                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8284               (void) CloneString(&draw_info->geometry,geometry);
8285             }
8286           if (attribute_flag[17] != 0)
8287             draw_info->stroke_width=argument_list[17].real_reference;
8288           if (attribute_flag[18] != 0)
8289             {
8290               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8291                 MagickTrue : MagickFalse;
8292               draw_info->stroke_antialias=draw_info->text_antialias;
8293             }
8294           if (attribute_flag[19] != 0)
8295             (void) CloneString(&draw_info->family,
8296               argument_list[19].string_reference);
8297           if (attribute_flag[20] != 0)
8298             draw_info->style=(StyleType) argument_list[20].integer_reference;
8299           if (attribute_flag[21] != 0)
8300             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8301           if (attribute_flag[22] != 0)
8302             draw_info->weight=argument_list[22].integer_reference;
8303           if (attribute_flag[23] != 0)
8304             draw_info->align=(AlignType) argument_list[23].integer_reference;
8305           if (attribute_flag[24] != 0)
8306             (void) CloneString(&draw_info->encoding,
8307               argument_list[24].string_reference);
8308           if (attribute_flag[25] != 0)
8309             draw_info->fill_pattern=CloneImage(
8310               argument_list[25].image_reference,0,0,MagickTrue,exception);
8311           if (attribute_flag[26] != 0)
8312             draw_info->fill_pattern=CloneImage(
8313               argument_list[26].image_reference,0,0,MagickTrue,exception);
8314           if (attribute_flag[27] != 0)
8315             draw_info->stroke_pattern=CloneImage(
8316               argument_list[27].image_reference,0,0,MagickTrue,exception);
8317           if (attribute_flag[29] != 0)
8318             draw_info->kerning=argument_list[29].real_reference;
8319           if (attribute_flag[30] != 0)
8320             draw_info->interline_spacing=argument_list[30].real_reference;
8321           if (attribute_flag[31] != 0)
8322             draw_info->interword_spacing=argument_list[31].real_reference;
8323           if (attribute_flag[32] != 0)
8324             draw_info->direction=(DirectionType)
8325               argument_list[32].integer_reference;
8326           (void) AnnotateImage(image,draw_info,exception);
8327           draw_info=DestroyDrawInfo(draw_info);
8328           break;
8329         }
8330         case 34:  /* ColorFloodfill */
8331         {
8332           DrawInfo
8333             *draw_info;
8334
8335           MagickBooleanType
8336             invert;
8337
8338           PixelInfo
8339             target;
8340
8341           draw_info=CloneDrawInfo(info ? info->image_info :
8342             (ImageInfo *) NULL,(DrawInfo *) NULL);
8343           if (attribute_flag[0] != 0)
8344             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8345               &geometry,exception);
8346           if (attribute_flag[1] != 0)
8347             geometry.x=argument_list[1].integer_reference;
8348           if (attribute_flag[2] != 0)
8349             geometry.y=argument_list[2].integer_reference;
8350           if (attribute_flag[3] != 0)
8351             (void) QueryColorCompliance(argument_list[3].string_reference,
8352               AllCompliance,&draw_info->fill,exception);
8353           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8354             geometry.x,geometry.y,&target,exception);
8355           invert=MagickFalse;
8356           if (attribute_flag[4] != 0)
8357             {
8358               QueryColorCompliance(argument_list[4].string_reference,
8359                 AllCompliance,&target,exception);
8360               invert=MagickTrue;
8361             }
8362           if (attribute_flag[5] != 0)
8363             image->fuzz=StringToDoubleInterval(
8364               argument_list[5].string_reference,(double) QuantumRange+1.0);
8365           if (attribute_flag[6] != 0)
8366             invert=(MagickBooleanType) argument_list[6].integer_reference;
8367           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8368             geometry.y,invert,exception);
8369           draw_info=DestroyDrawInfo(draw_info);
8370           break;
8371         }
8372         case 35:  /* Composite */
8373         {
8374           char
8375             composite_geometry[MaxTextExtent];
8376
8377           Image
8378             *composite_image,
8379             *rotate_image;
8380
8381           MagickBooleanType
8382             clip_to_self;
8383
8384           compose=OverCompositeOp;
8385           if (attribute_flag[0] != 0)
8386             composite_image=argument_list[0].image_reference;
8387           else
8388             {
8389               ThrowPerlException(exception,OptionError,
8390                 "CompositeImageRequired",PackageName);
8391               goto PerlException;
8392             }
8393           /*
8394             Parameter Handling used for BOTH normal and tiled composition.
8395           */
8396           if (attribute_flag[1] != 0) /* compose */
8397             compose=(CompositeOperator) argument_list[1].integer_reference;
8398           if (attribute_flag[6] != 0) /* opacity  */
8399             {
8400               if (compose != DissolveCompositeOp)
8401                 (void) SetImageAlpha(composite_image,(Quantum)
8402                   StringToDoubleInterval(argument_list[6].string_reference,
8403                   (double) QuantumRange+1.0),exception);
8404               else
8405                 {
8406                   CacheView
8407                     *composite_view;
8408
8409                   double
8410                     opacity;
8411
8412                   MagickBooleanType
8413                     sync;
8414
8415                   register ssize_t
8416                     x;
8417
8418                   register Quantum
8419                     *q;
8420
8421                   ssize_t
8422                     y;
8423
8424                   /*
8425                     Handle dissolve composite operator (patch by
8426                     Kevin A. McGrail).
8427                   */
8428                   (void) CloneString(&image->geometry,
8429                     argument_list[6].string_reference);
8430                   opacity=(Quantum) StringToDoubleInterval(
8431                     argument_list[6].string_reference,(double) QuantumRange+
8432                     1.0);
8433                   if (composite_image->alpha_trait == BlendPixelTrait)
8434                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8435                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8436                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8437                   {
8438                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8439                       composite_image->columns,1,exception);
8440                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8441                     {
8442                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8443                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8444                           q);
8445                       q+=GetPixelChannels(composite_image);
8446                     }
8447                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8448                     if (sync == MagickFalse)
8449                       break;
8450                   }
8451                   composite_view=DestroyCacheView(composite_view);
8452                 }
8453             }
8454           if (attribute_flag[9] != 0)    /* "color=>" */
8455             QueryColorCompliance(argument_list[9].string_reference,
8456               AllCompliance,&composite_image->background_color,exception);
8457           if (attribute_flag[12] != 0) /* "interpolate=>" */
8458             image->interpolate=(PixelInterpolateMethod)
8459               argument_list[12].integer_reference;
8460           if (attribute_flag[13] != 0)   /* "args=>" */
8461             (void) SetImageArtifact(composite_image,"compose:args",
8462               argument_list[13].string_reference);
8463           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8464             (void) SetImageArtifact(composite_image,"compose:args",
8465               argument_list[14].string_reference);
8466           clip_to_self=MagickTrue;
8467           if (attribute_flag[15] != 0)
8468             clip_to_self=(MagickBooleanType)
8469               argument_list[15].integer_reference;
8470           /*
8471             Tiling Composition (with orthogonal rotate).
8472           */
8473           rotate_image=(Image *) NULL;
8474           if (attribute_flag[8] != 0)   /* "rotate=>" */
8475             {
8476                /*
8477                  Rotate image.
8478                */
8479                rotate_image=RotateImage(composite_image,
8480                  argument_list[8].real_reference,exception);
8481                if (rotate_image == (Image *) NULL)
8482                  break;
8483             }
8484           if ((attribute_flag[7] != 0) &&
8485               (argument_list[7].integer_reference != 0)) /* tile */
8486             {
8487               ssize_t
8488                 x,
8489                 y;
8490
8491               /*
8492                 Tile the composite image.
8493               */
8494              if (attribute_flag[8] != 0)   /* "tile=>" */
8495                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8496                  "false");
8497              else
8498                (void) SetImageArtifact(composite_image,
8499                  "compose:outside-overlay","false");
8500              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8501                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8502                 {
8503                   if (attribute_flag[8] != 0) /* rotate */
8504                     (void) CompositeImage(image,rotate_image,compose,
8505                       MagickTrue,x,y,exception);
8506                   else
8507                     (void) CompositeImage(image,composite_image,compose,
8508                       MagickTrue,x,y,exception);
8509                 }
8510               if (attribute_flag[8] != 0) /* rotate */
8511                 rotate_image=DestroyImage(rotate_image);
8512               break;
8513             }
8514           /*
8515             Parameter Handling used used ONLY for normal composition.
8516           */
8517           if (attribute_flag[5] != 0) /* gravity */
8518             image->gravity=(GravityType) argument_list[5].integer_reference;
8519           if (attribute_flag[2] != 0) /* geometry offset */
8520             {
8521               SetGeometry(image,&geometry);
8522               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8523                 &geometry);
8524               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8525                 &geometry);
8526             }
8527           if (attribute_flag[3] != 0) /* x offset */
8528             geometry.x=argument_list[3].integer_reference;
8529           if (attribute_flag[4] != 0) /* y offset */
8530             geometry.y=argument_list[4].integer_reference;
8531           if (attribute_flag[10] != 0) /* mask */
8532             {
8533               if ((image->compose == DisplaceCompositeOp) ||
8534                   (image->compose == DistortCompositeOp))
8535                 {
8536                   /*
8537                     Merge Y displacement into X displacement image.
8538                   */
8539                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8540                     exception);
8541                   (void) CompositeImage(composite_image,
8542                     argument_list[10].image_reference,CopyGreenCompositeOp,
8543                     MagickTrue,0,0,exception);
8544                 }
8545               else
8546                 {
8547                   Image
8548                     *mask_image;
8549
8550                   /*
8551                     Set a blending mask for the composition.
8552                   */
8553                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8554                     MagickTrue,exception);
8555                   (void) NegateImage(mask_image,MagickFalse,exception);
8556                   (void) SetImageMask(composite_image,mask_image,exception);
8557                   mask_image=DestroyImage(mask_image);
8558                 }
8559             }
8560           if (attribute_flag[11] != 0) /* channel */
8561             channel=(ChannelType) argument_list[11].integer_reference;
8562           /*
8563             Composite two images (normal composition).
8564           */
8565           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8566             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8567             (double) composite_image->rows,(double) geometry.x,(double)
8568             geometry.y);
8569           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8570             exception);
8571           channel_mask=SetImageChannelMask(image,channel);
8572           if (attribute_flag[8] == 0) /* no rotate */
8573             CompositeImage(image,composite_image,compose,clip_to_self,
8574               geometry.x,geometry.y,exception);
8575           else
8576             {
8577               /*
8578                 Position adjust rotated image then composite.
8579               */
8580               geometry.x-=(ssize_t) (rotate_image->columns-
8581                 composite_image->columns)/2;
8582               geometry.y-=(ssize_t) (rotate_image->rows-
8583                 composite_image->rows)/2;
8584               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8585                 geometry.y,exception);
8586               rotate_image=DestroyImage(rotate_image);
8587             }
8588           if (attribute_flag[10] != 0) /* mask */
8589             {
8590               if ((image->compose == DisplaceCompositeOp) ||
8591                   (image->compose == DistortCompositeOp))
8592                 composite_image=DestroyImage(composite_image);
8593               else
8594                 (void) SetImageMask(image,(Image *) NULL,exception);
8595             }
8596           (void) SetImageChannelMask(image,channel_mask);
8597           break;
8598         }
8599         case 36:  /* Contrast */
8600         {
8601           if (attribute_flag[0] == 0)
8602             argument_list[0].integer_reference=0;
8603           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8604             MagickTrue : MagickFalse,exception);
8605           break;
8606         }
8607         case 37:  /* CycleColormap */
8608         {
8609           if (attribute_flag[0] == 0)
8610             argument_list[0].integer_reference=6;
8611           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8612             exception);
8613           break;
8614         }
8615         case 38:  /* Draw */
8616         {
8617           DrawInfo
8618             *draw_info;
8619
8620           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8621             (DrawInfo *) NULL);
8622           (void) CloneString(&draw_info->primitive,"point");
8623           if (attribute_flag[0] != 0)
8624             {
8625               if (argument_list[0].integer_reference < 0)
8626                 (void) CloneString(&draw_info->primitive,
8627                   argument_list[0].string_reference);
8628               else
8629                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8630                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8631             }
8632           if (attribute_flag[1] != 0)
8633             {
8634               if (LocaleCompare(draw_info->primitive,"path") == 0)
8635                 {
8636                   (void) ConcatenateString(&draw_info->primitive," '");
8637                   ConcatenateString(&draw_info->primitive,
8638                     argument_list[1].string_reference);
8639                   (void) ConcatenateString(&draw_info->primitive,"'");
8640                 }
8641               else
8642                 {
8643                   (void) ConcatenateString(&draw_info->primitive," ");
8644                   ConcatenateString(&draw_info->primitive,
8645                     argument_list[1].string_reference);
8646                 }
8647             }
8648           if (attribute_flag[2] != 0)
8649             {
8650               (void) ConcatenateString(&draw_info->primitive," ");
8651               (void) ConcatenateString(&draw_info->primitive,
8652                 CommandOptionToMnemonic(MagickMethodOptions,
8653                 argument_list[2].integer_reference));
8654             }
8655           if (attribute_flag[3] != 0)
8656             {
8657               (void) QueryColorCompliance(argument_list[3].string_reference,
8658                 AllCompliance,&draw_info->stroke,exception);
8659               if (argument_list[3].image_reference != (Image *) NULL)
8660                 draw_info->stroke_pattern=CloneImage(
8661                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8662             }
8663           if (attribute_flag[4] != 0)
8664             {
8665               (void) QueryColorCompliance(argument_list[4].string_reference,
8666                 AllCompliance,&draw_info->fill,exception);
8667               if (argument_list[4].image_reference != (Image *) NULL)
8668                 draw_info->fill_pattern=CloneImage(
8669                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8670             }
8671           if (attribute_flag[5] != 0)
8672             draw_info->stroke_width=argument_list[5].real_reference;
8673           if (attribute_flag[6] != 0)
8674             (void) CloneString(&draw_info->font,
8675               argument_list[6].string_reference);
8676           if (attribute_flag[7] != 0)
8677             (void) QueryColorCompliance(argument_list[7].string_reference,
8678               AllCompliance,&draw_info->border_color,exception);
8679           if (attribute_flag[8] != 0)
8680             draw_info->affine.tx=argument_list[8].real_reference;
8681           if (attribute_flag[9] != 0)
8682             draw_info->affine.ty=argument_list[9].real_reference;
8683           if (attribute_flag[20] != 0)
8684             {
8685               AV
8686                 *av;
8687
8688               av=(AV *) argument_list[20].array_reference;
8689               if ((av_len(av) != 3) && (av_len(av) != 5))
8690                 {
8691                   ThrowPerlException(exception,OptionError,
8692                     "affine matrix must have 4 or 6 elements",PackageName);
8693                   goto PerlException;
8694                 }
8695               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8696               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8697               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8698               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8699               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8700                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8701                 {
8702                   ThrowPerlException(exception,OptionError,
8703                     "affine matrix is singular",PackageName);
8704                    goto PerlException;
8705                 }
8706               if (av_len(av) == 5)
8707                 {
8708                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8709                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8710                 }
8711             }
8712           for (j=10; j < 15; j++)
8713           {
8714             if (attribute_flag[j] == 0)
8715               continue;
8716             value=argument_list[j].string_reference;
8717             angle=argument_list[j].real_reference;
8718             current=draw_info->affine;
8719             GetAffineMatrix(&affine);
8720             switch (j)
8721             {
8722               case 10:
8723               {
8724                 /*
8725                   Translate.
8726                 */
8727                 flags=ParseGeometry(value,&geometry_info);
8728                 affine.tx=geometry_info.xi;
8729                 affine.ty=geometry_info.psi;
8730                 if ((flags & PsiValue) == 0)
8731                   affine.ty=affine.tx;
8732                 break;
8733               }
8734               case 11:
8735               {
8736                 /*
8737                   Scale.
8738                 */
8739                 flags=ParseGeometry(value,&geometry_info);
8740                 affine.sx=geometry_info.rho;
8741                 affine.sy=geometry_info.sigma;
8742                 if ((flags & SigmaValue) == 0)
8743                   affine.sy=affine.sx;
8744                 break;
8745               }
8746               case 12:
8747               {
8748                 /*
8749                   Rotate.
8750                 */
8751                 if (angle == 0.0)
8752                   break;
8753                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8754                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8755                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8756                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8757                 break;
8758               }
8759               case 13:
8760               {
8761                 /*
8762                   SkewX.
8763                 */
8764                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8765                 break;
8766               }
8767               case 14:
8768               {
8769                 /*
8770                   SkewY.
8771                 */
8772                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8773                 break;
8774               }
8775             }
8776             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8777             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8778             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8779             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8780             draw_info->affine.tx=
8781               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8782             draw_info->affine.ty=
8783               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8784           }
8785           if (attribute_flag[15] != 0)
8786             draw_info->fill_pattern=CloneImage(
8787               argument_list[15].image_reference,0,0,MagickTrue,exception);
8788           if (attribute_flag[16] != 0)
8789             draw_info->pointsize=argument_list[16].real_reference;
8790           if (attribute_flag[17] != 0)
8791             {
8792               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8793                 ? MagickTrue : MagickFalse;
8794               draw_info->text_antialias=draw_info->stroke_antialias;
8795             }
8796           if (attribute_flag[18] != 0)
8797             (void) CloneString(&draw_info->density,
8798               argument_list[18].string_reference);
8799           if (attribute_flag[19] != 0)
8800             draw_info->stroke_width=argument_list[19].real_reference;
8801           if (attribute_flag[21] != 0)
8802             draw_info->dash_offset=argument_list[21].real_reference;
8803           if (attribute_flag[22] != 0)
8804             {
8805               AV
8806                 *av;
8807
8808               av=(AV *) argument_list[22].array_reference;
8809               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8810                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8811               if (draw_info->dash_pattern != (double *) NULL)
8812                 {
8813                   for (i=0; i <= av_len(av); i++)
8814                     draw_info->dash_pattern[i]=(double)
8815                       SvNV(*(av_fetch(av,i,0)));
8816                   draw_info->dash_pattern[i]=0.0;
8817                 }
8818             }
8819           if (attribute_flag[23] != 0)
8820             image->interpolate=(PixelInterpolateMethod)
8821               argument_list[23].integer_reference;
8822           if ((attribute_flag[24] != 0) &&
8823               (draw_info->fill_pattern != (Image *) NULL))
8824             flags=ParsePageGeometry(draw_info->fill_pattern,
8825               argument_list[24].string_reference,
8826               &draw_info->fill_pattern->tile_offset,exception);
8827           if (attribute_flag[25] != 0)
8828             {
8829               (void) ConcatenateString(&draw_info->primitive," '");
8830               (void) ConcatenateString(&draw_info->primitive,
8831                 argument_list[25].string_reference);
8832               (void) ConcatenateString(&draw_info->primitive,"'");
8833             }
8834           if (attribute_flag[26] != 0)
8835             draw_info->fill_pattern=CloneImage(
8836               argument_list[26].image_reference,0,0,MagickTrue,exception);
8837           if (attribute_flag[27] != 0)
8838             draw_info->stroke_pattern=CloneImage(
8839               argument_list[27].image_reference,0,0,MagickTrue,exception);
8840           if (attribute_flag[28] != 0)
8841             (void) CloneString(&draw_info->primitive,
8842               argument_list[28].string_reference);
8843           if (attribute_flag[29] != 0)
8844             draw_info->kerning=argument_list[29].real_reference;
8845           if (attribute_flag[30] != 0)
8846             draw_info->interline_spacing=argument_list[30].real_reference;
8847           if (attribute_flag[31] != 0)
8848             draw_info->interword_spacing=argument_list[31].real_reference;
8849           if (attribute_flag[32] != 0)
8850             draw_info->direction=(DirectionType)
8851               argument_list[32].integer_reference;
8852           DrawImage(image,draw_info,exception);
8853           draw_info=DestroyDrawInfo(draw_info);
8854           break;
8855         }
8856         case 39:  /* Equalize */
8857         {
8858           if (attribute_flag[0] != 0)
8859             channel=(ChannelType) argument_list[0].integer_reference;
8860           channel_mask=SetImageChannelMask(image,channel);
8861           EqualizeImage(image,exception);
8862           (void) SetImageChannelMask(image,channel_mask);
8863           break;
8864         }
8865         case 40:  /* Gamma */
8866         {
8867           if (attribute_flag[1] != 0)
8868             channel=(ChannelType) argument_list[1].integer_reference;
8869           if (attribute_flag[2] == 0)
8870             argument_list[2].real_reference=1.0;
8871           if (attribute_flag[3] == 0)
8872             argument_list[3].real_reference=1.0;
8873           if (attribute_flag[4] == 0)
8874             argument_list[4].real_reference=1.0;
8875           if (attribute_flag[0] == 0)
8876             {
8877               (void) FormatLocaleString(message,MaxTextExtent,
8878                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8879                 (double) argument_list[3].real_reference,
8880                 (double) argument_list[4].real_reference);
8881               argument_list[0].string_reference=message;
8882             }
8883           (void) GammaImage(image,StringToDouble(
8884             argument_list[0].string_reference,(char **) NULL),exception);
8885           break;
8886         }
8887         case 41:  /* Map */
8888         {
8889           QuantizeInfo
8890             *quantize_info;
8891
8892           if (attribute_flag[0] == 0)
8893             {
8894               ThrowPerlException(exception,OptionError,"MapImageRequired",
8895                 PackageName);
8896               goto PerlException;
8897             }
8898           quantize_info=AcquireQuantizeInfo(info->image_info);
8899           if (attribute_flag[1] != 0)
8900             quantize_info->dither_method=(DitherMethod)
8901               argument_list[1].integer_reference;
8902           (void) RemapImages(quantize_info,image,
8903             argument_list[0].image_reference,exception);
8904           quantize_info=DestroyQuantizeInfo(quantize_info);
8905           break;
8906         }
8907         case 42:  /* MatteFloodfill */
8908         {
8909           DrawInfo
8910             *draw_info;
8911
8912           MagickBooleanType
8913             invert;
8914
8915           PixelInfo
8916             target;
8917
8918           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8919             (DrawInfo *) NULL);
8920           if (attribute_flag[0] != 0)
8921             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8922               &geometry,exception);
8923           if (attribute_flag[1] != 0)
8924             geometry.x=argument_list[1].integer_reference;
8925           if (attribute_flag[2] != 0)
8926             geometry.y=argument_list[2].integer_reference;
8927           if (image->alpha_trait != BlendPixelTrait)
8928             (void) SetImageAlpha(image,OpaqueAlpha,exception);
8929           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8930             geometry.x,geometry.y,&target,exception);
8931           if (attribute_flag[4] != 0)
8932             QueryColorCompliance(argument_list[4].string_reference,
8933               AllCompliance,&target,exception);
8934           if (attribute_flag[3] != 0)
8935             target.alpha=StringToDoubleInterval(
8936               argument_list[3].string_reference,(double) (double) QuantumRange+
8937               1.0);
8938           if (attribute_flag[5] != 0)
8939             image->fuzz=StringToDoubleInterval(
8940               argument_list[5].string_reference,(double) QuantumRange+1.0);
8941           invert=MagickFalse;
8942           if (attribute_flag[6] != 0)
8943             invert=(MagickBooleanType) argument_list[6].integer_reference;
8944           channel_mask=SetImageChannelMask(image,AlphaChannel);
8945           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8946             geometry.y,invert,exception);
8947           (void) SetImageChannelMask(image,channel_mask);
8948           draw_info=DestroyDrawInfo(draw_info);
8949           break;
8950         }
8951         case 43:  /* Modulate */
8952         {
8953           char
8954             modulate[MaxTextExtent];
8955
8956           geometry_info.rho=100.0;
8957           geometry_info.sigma=100.0;
8958           geometry_info.xi=100.0;
8959           if (attribute_flag[0] != 0)
8960             (void)ParseGeometry(argument_list[0].string_reference,
8961               &geometry_info);
8962           if (attribute_flag[1] != 0)
8963             geometry_info.xi=argument_list[1].real_reference;
8964           if (attribute_flag[2] != 0)
8965             geometry_info.sigma=argument_list[2].real_reference;
8966           if (attribute_flag[3] != 0)
8967             {
8968               geometry_info.sigma=argument_list[3].real_reference;
8969               SetImageArtifact(image,"modulate:colorspace","HWB");
8970             }
8971           if (attribute_flag[4] != 0)
8972             {
8973               geometry_info.rho=argument_list[4].real_reference;
8974               SetImageArtifact(image,"modulate:colorspace","HSB");
8975             }
8976           if (attribute_flag[5] != 0)
8977             {
8978               geometry_info.sigma=argument_list[5].real_reference;
8979               SetImageArtifact(image,"modulate:colorspace","HSL");
8980             }
8981           if (attribute_flag[6] != 0)
8982             {
8983               geometry_info.rho=argument_list[6].real_reference;
8984               SetImageArtifact(image,"modulate:colorspace","HWB");
8985             }
8986           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8987             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8988           (void) ModulateImage(image,modulate,exception);
8989           break;
8990         }
8991         case 44:  /* Negate */
8992         {
8993           if (attribute_flag[0] == 0)
8994             argument_list[0].integer_reference=0;
8995           if (attribute_flag[1] != 0)
8996             channel=(ChannelType) argument_list[1].integer_reference;
8997           channel_mask=SetImageChannelMask(image,channel);
8998           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
8999             MagickTrue : MagickFalse,exception);
9000           (void) SetImageChannelMask(image,channel_mask);
9001           break;
9002         }
9003         case 45:  /* Normalize */
9004         {
9005           if (attribute_flag[0] != 0)
9006             channel=(ChannelType) argument_list[0].integer_reference;
9007           channel_mask=SetImageChannelMask(image,channel);
9008           NormalizeImage(image,exception);
9009           (void) SetImageChannelMask(image,channel_mask);
9010           break;
9011         }
9012         case 46:  /* NumberColors */
9013           break;
9014         case 47:  /* Opaque */
9015         {
9016           MagickBooleanType
9017             invert;
9018
9019           PixelInfo
9020             fill_color,
9021             target;
9022
9023           (void) QueryColorCompliance("none",AllCompliance,&target,
9024              exception);
9025           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9026             exception);
9027           if (attribute_flag[0] != 0)
9028             (void) QueryColorCompliance(argument_list[0].string_reference,
9029               AllCompliance,&target,exception);
9030           if (attribute_flag[1] != 0)
9031             (void) QueryColorCompliance(argument_list[1].string_reference,
9032               AllCompliance,&fill_color,exception);
9033           if (attribute_flag[2] != 0)
9034             image->fuzz=StringToDoubleInterval(
9035               argument_list[2].string_reference,(double) QuantumRange+1.0);
9036           if (attribute_flag[3] != 0)
9037             channel=(ChannelType) argument_list[3].integer_reference;
9038           invert=MagickFalse;
9039           if (attribute_flag[4] != 0)
9040             invert=(MagickBooleanType) argument_list[4].integer_reference;
9041           channel_mask=SetImageChannelMask(image,channel);
9042           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9043           (void) SetImageChannelMask(image,channel_mask);
9044           break;
9045         }
9046         case 48:  /* Quantize */
9047         {
9048           QuantizeInfo
9049             *quantize_info;
9050
9051           quantize_info=AcquireQuantizeInfo(info->image_info);
9052           if (attribute_flag[0] != 0)
9053             quantize_info->number_colors=(size_t)
9054               argument_list[0].integer_reference;
9055           if (attribute_flag[1] != 0)
9056             quantize_info->tree_depth=(size_t)
9057               argument_list[1].integer_reference;
9058           if (attribute_flag[2] != 0)
9059             quantize_info->colorspace=(ColorspaceType)
9060               argument_list[2].integer_reference;
9061           if (attribute_flag[3] != 0)
9062             quantize_info->dither_method=(DitherMethod)
9063               argument_list[3].integer_reference;
9064           if (attribute_flag[4] != 0)
9065             quantize_info->measure_error=argument_list[4].integer_reference !=
9066               0 ? MagickTrue : MagickFalse;
9067           if (attribute_flag[5] != 0)
9068             (void) QueryColorCompliance(argument_list[5].string_reference,
9069               AllCompliance,&image->transparent_color,exception);
9070           if (attribute_flag[5] && argument_list[5].integer_reference)
9071             {
9072               (void) QuantizeImages(quantize_info,image,exception);
9073               goto PerlException;
9074             }
9075           if (attribute_flag[6] != 0)
9076             quantize_info->dither_method=(DitherMethod)
9077               argument_list[6].integer_reference;
9078           if ((image->storage_class == DirectClass) ||
9079               (image->colors > quantize_info->number_colors) ||
9080               (quantize_info->colorspace == GRAYColorspace))
9081             (void) QuantizeImage(quantize_info,image,exception);
9082           else
9083             CompressImageColormap(image,exception);
9084           quantize_info=DestroyQuantizeInfo(quantize_info);
9085           break;
9086         }
9087         case 49:  /* Raise */
9088         {
9089           if (attribute_flag[0] != 0)
9090             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9091               &geometry,exception);
9092           if (attribute_flag[1] != 0)
9093             geometry.width=argument_list[1].integer_reference;
9094           if (attribute_flag[2] != 0)
9095             geometry.height=argument_list[2].integer_reference;
9096           if (attribute_flag[3] == 0)
9097             argument_list[3].integer_reference=1;
9098           (void) RaiseImage(image,&geometry,
9099             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9100             exception);
9101           break;
9102         }
9103         case 50:  /* Segment */
9104         {
9105           ColorspaceType
9106             colorspace;
9107
9108           double
9109             cluster_threshold,
9110             smoothing_threshold;
9111
9112           MagickBooleanType
9113             verbose;
9114
9115           cluster_threshold=1.0;
9116           smoothing_threshold=1.5;
9117           colorspace=sRGBColorspace;
9118           verbose=MagickFalse;
9119           if (attribute_flag[0] != 0)
9120             {
9121               flags=ParseGeometry(argument_list[0].string_reference,
9122                 &geometry_info);
9123               cluster_threshold=geometry_info.rho;
9124               if (flags & SigmaValue)
9125                 smoothing_threshold=geometry_info.sigma;
9126             }
9127           if (attribute_flag[1] != 0)
9128             cluster_threshold=argument_list[1].real_reference;
9129           if (attribute_flag[2] != 0)
9130             smoothing_threshold=argument_list[2].real_reference;
9131           if (attribute_flag[3] != 0)
9132             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9133           if (attribute_flag[4] != 0)
9134             verbose=argument_list[4].integer_reference != 0 ?
9135               MagickTrue : MagickFalse;
9136           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9137             smoothing_threshold,exception);
9138           break;
9139         }
9140         case 51:  /* Signature */
9141         {
9142           (void) SignatureImage(image,exception);
9143           break;
9144         }
9145         case 52:  /* Solarize */
9146         {
9147           geometry_info.rho=QuantumRange/2.0;
9148           if (attribute_flag[0] != 0)
9149             flags=ParseGeometry(argument_list[0].string_reference,
9150               &geometry_info);
9151           if (attribute_flag[1] != 0)
9152             geometry_info.rho=StringToDoubleInterval(
9153               argument_list[1].string_reference,(double) QuantumRange+1.0);
9154           (void) SolarizeImage(image,geometry_info.rho,exception);
9155           break;
9156         }
9157         case 53:  /* Sync */
9158         {
9159           (void) SyncImage(image,exception);
9160           break;
9161         }
9162         case 54:  /* Texture */
9163         {
9164           if (attribute_flag[0] == 0)
9165             break;
9166           TextureImage(image,argument_list[0].image_reference,exception);
9167           break;
9168         }
9169         case 55:  /* Evalute */
9170         {
9171           MagickEvaluateOperator
9172             op;
9173
9174           op=SetEvaluateOperator;
9175           if (attribute_flag[0] == MagickFalse)
9176             argument_list[0].real_reference=0.0;
9177           if (attribute_flag[1] != MagickFalse)
9178             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9179           if (attribute_flag[2] != MagickFalse)
9180             channel=(ChannelType) argument_list[2].integer_reference;
9181           channel_mask=SetImageChannelMask(image,channel);
9182           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9183             exception);
9184           (void) SetImageChannelMask(image,channel_mask);
9185           break;
9186         }
9187         case 56:  /* Transparent */
9188         {
9189           double
9190             opacity;
9191
9192           MagickBooleanType
9193             invert;
9194
9195           PixelInfo
9196             target;
9197
9198           (void) QueryColorCompliance("none",AllCompliance,&target,
9199             exception);
9200           if (attribute_flag[0] != 0)
9201             (void) QueryColorCompliance(argument_list[0].string_reference,
9202               AllCompliance,&target,exception);
9203           opacity=TransparentAlpha;
9204           if (attribute_flag[1] != 0)
9205             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9206               (double) QuantumRange+1.0);
9207           if (attribute_flag[2] != 0)
9208             image->fuzz=StringToDoubleInterval(
9209               argument_list[2].string_reference,(double) QuantumRange+1.0);
9210           if (attribute_flag[3] == 0)
9211             argument_list[3].integer_reference=0;
9212           invert=MagickFalse;
9213           if (attribute_flag[3] != 0)
9214             invert=(MagickBooleanType) argument_list[3].integer_reference;
9215           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9216             invert,exception);
9217           break;
9218         }
9219         case 57:  /* Threshold */
9220         {
9221           double
9222             threshold;
9223
9224           if (attribute_flag[0] == 0)
9225             argument_list[0].string_reference="50%";
9226           if (attribute_flag[1] != 0)
9227             channel=(ChannelType) argument_list[1].integer_reference;
9228           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9229             (double) QuantumRange+1.0);
9230           channel_mask=SetImageChannelMask(image,channel);
9231           (void) BilevelImage(image,threshold,exception);
9232           (void) SetImageChannelMask(image,channel_mask);
9233           break;
9234         }
9235         case 58:  /* Charcoal */
9236         {
9237           if (attribute_flag[0] != 0)
9238             {
9239               flags=ParseGeometry(argument_list[0].string_reference,
9240                 &geometry_info);
9241               if ((flags & SigmaValue) == 0)
9242                 geometry_info.sigma=1.0;
9243             }
9244           if (attribute_flag[1] != 0)
9245             geometry_info.rho=argument_list[1].real_reference;
9246           if (attribute_flag[2] != 0)
9247             geometry_info.sigma=argument_list[2].real_reference;
9248           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9249             exception);
9250           break;
9251         }
9252         case 59:  /* Trim */
9253         {
9254           if (attribute_flag[0] != 0)
9255             image->fuzz=StringToDoubleInterval(
9256               argument_list[0].string_reference,(double) QuantumRange+1.0);
9257           image=TrimImage(image,exception);
9258           break;
9259         }
9260         case 60:  /* Wave */
9261         {
9262           PixelInterpolateMethod
9263             method;
9264
9265           if (attribute_flag[0] != 0)
9266             {
9267               flags=ParseGeometry(argument_list[0].string_reference,
9268                 &geometry_info);
9269               if ((flags & SigmaValue) == 0)
9270                 geometry_info.sigma=1.0;
9271             }
9272           if (attribute_flag[1] != 0)
9273             geometry_info.rho=argument_list[1].real_reference;
9274           if (attribute_flag[2] != 0)
9275             geometry_info.sigma=argument_list[2].real_reference;
9276           method=UndefinedInterpolatePixel;
9277           if (attribute_flag[3] != 0)
9278             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9279           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9280             method,exception);
9281           break;
9282         }
9283         case 61:  /* Separate */
9284         {
9285           if (attribute_flag[0] != 0)
9286             channel=(ChannelType) argument_list[0].integer_reference;
9287           image=SeparateImage(image,channel,exception);
9288           break;
9289         }
9290         case 63:  /* Stereo */
9291         {
9292           if (attribute_flag[0] == 0)
9293             {
9294               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9295                 PackageName);
9296               goto PerlException;
9297             }
9298           if (attribute_flag[1] != 0)
9299             geometry.x=argument_list[1].integer_reference;
9300           if (attribute_flag[2] != 0)
9301             geometry.y=argument_list[2].integer_reference;
9302           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9303             geometry.x,geometry.y,exception);
9304           break;
9305         }
9306         case 64:  /* Stegano */
9307         {
9308           if (attribute_flag[0] == 0)
9309             {
9310               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9311                 PackageName);
9312               goto PerlException;
9313             }
9314           if (attribute_flag[1] == 0)
9315             argument_list[1].integer_reference=0;
9316           image->offset=argument_list[1].integer_reference;
9317           image=SteganoImage(image,argument_list[0].image_reference,exception);
9318           break;
9319         }
9320         case 65:  /* Deconstruct */
9321         {
9322           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9323           break;
9324         }
9325         case 66:  /* GaussianBlur */
9326         {
9327           if (attribute_flag[0] != 0)
9328             {
9329               flags=ParseGeometry(argument_list[0].string_reference,
9330                 &geometry_info);
9331               if ((flags & SigmaValue) == 0)
9332                 geometry_info.sigma=1.0;
9333             }
9334           if (attribute_flag[1] != 0)
9335             geometry_info.rho=argument_list[1].real_reference;
9336           if (attribute_flag[2] != 0)
9337             geometry_info.sigma=argument_list[2].real_reference;
9338           if (attribute_flag[3] != 0)
9339             channel=(ChannelType) argument_list[3].integer_reference;
9340           channel_mask=SetImageChannelMask(image,channel);
9341           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9342             exception);
9343           if (image != (Image *) NULL)
9344             (void) SetImageChannelMask(image,channel_mask);
9345           break;
9346         }
9347         case 67:  /* Convolve */
9348         {
9349           KernelInfo
9350             *kernel;
9351
9352           kernel=(KernelInfo *) NULL;
9353           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9354             break;
9355           if (attribute_flag[0] != 0)
9356             {
9357               AV
9358                 *av;
9359
9360               size_t
9361                 order;
9362
9363               kernel=AcquireKernelInfo((const char *) NULL);
9364               if (kernel == (KernelInfo *) NULL)
9365                 break;
9366               av=(AV *) argument_list[0].array_reference;
9367               order=(size_t) sqrt(av_len(av)+1);
9368               kernel->width=order;
9369               kernel->height=order;
9370               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9371                 order*sizeof(*kernel->values));
9372               if (kernel->values == (MagickRealType *) NULL)
9373                 {
9374                   kernel=DestroyKernelInfo(kernel);
9375                   ThrowPerlException(exception,ResourceLimitFatalError,
9376                     "MemoryAllocationFailed",PackageName);
9377                   goto PerlException;
9378                 }
9379               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9380                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9381               for ( ; j < (ssize_t) (order*order); j++)
9382                 kernel->values[j]=0.0;
9383             }
9384           if (attribute_flag[1] != 0)
9385             channel=(ChannelType) argument_list[1].integer_reference;
9386           if (attribute_flag[2] != 0)
9387             SetImageArtifact(image,"filter:blur",
9388               argument_list[2].string_reference);
9389           if (attribute_flag[3] != 0)
9390             {
9391               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9392               if (kernel == (KernelInfo *) NULL)
9393                 break;
9394             }
9395           channel_mask=SetImageChannelMask(image,channel);
9396           image=ConvolveImage(image,kernel,exception);
9397           if (image != (Image *) NULL)
9398             (void) SetImageChannelMask(image,channel_mask);
9399           kernel=DestroyKernelInfo(kernel);
9400           break;
9401         }
9402         case 68:  /* Profile */
9403         {
9404           const char
9405             *name;
9406
9407           Image
9408             *profile_image;
9409
9410           ImageInfo
9411             *profile_info;
9412
9413           StringInfo
9414             *profile;
9415
9416           name="*";
9417           if (attribute_flag[0] != 0)
9418             name=argument_list[0].string_reference;
9419           if (attribute_flag[2] != 0)
9420             image->rendering_intent=(RenderingIntent)
9421               argument_list[2].integer_reference;
9422           if (attribute_flag[3] != 0)
9423             image->black_point_compensation=
9424               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9425           if (attribute_flag[1] != 0)
9426             {
9427               if (argument_list[1].length == 0)
9428                 {
9429                   /*
9430                     Remove a profile from the image.
9431                   */
9432                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9433                     exception);
9434                   break;
9435                 }
9436               /*
9437                 Associate user supplied profile with the image.
9438               */
9439               profile=AcquireStringInfo(argument_list[1].length);
9440               SetStringInfoDatum(profile,(const unsigned char *)
9441                 argument_list[1].string_reference);
9442               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9443                 (size_t) GetStringInfoLength(profile),exception);
9444               profile=DestroyStringInfo(profile);
9445               break;
9446             }
9447           /*
9448             Associate a profile with the image.
9449           */
9450           profile_info=CloneImageInfo(info ? info->image_info :
9451             (ImageInfo *) NULL);
9452           profile_image=ReadImages(profile_info,name,exception);
9453           if (profile_image == (Image *) NULL)
9454             break;
9455           ResetImageProfileIterator(profile_image);
9456           name=GetNextImageProfile(profile_image);
9457           while (name != (const char *) NULL)
9458           {
9459             const StringInfo
9460               *profile;
9461
9462             profile=GetImageProfile(profile_image,name);
9463             if (profile != (const StringInfo *) NULL)
9464               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9465                 (size_t) GetStringInfoLength(profile),exception);
9466             name=GetNextImageProfile(profile_image);
9467           }
9468           profile_image=DestroyImage(profile_image);
9469           profile_info=DestroyImageInfo(profile_info);
9470           break;
9471         }
9472         case 69:  /* UnsharpMask */
9473         {
9474           if (attribute_flag[0] != 0)
9475             {
9476               flags=ParseGeometry(argument_list[0].string_reference,
9477                 &geometry_info);
9478               if ((flags & SigmaValue) == 0)
9479                 geometry_info.sigma=1.0;
9480               if ((flags & XiValue) == 0)
9481                 geometry_info.xi=1.0;
9482               if ((flags & PsiValue) == 0)
9483                 geometry_info.psi=0.5;
9484             }
9485           if (attribute_flag[1] != 0)
9486             geometry_info.rho=argument_list[1].real_reference;
9487           if (attribute_flag[2] != 0)
9488             geometry_info.sigma=argument_list[2].real_reference;
9489           if (attribute_flag[3] != 0)
9490             geometry_info.xi=argument_list[3].real_reference;
9491           if (attribute_flag[4] != 0)
9492             geometry_info.psi=argument_list[4].real_reference;
9493           if (attribute_flag[5] != 0)
9494             channel=(ChannelType) argument_list[5].integer_reference;
9495           channel_mask=SetImageChannelMask(image,channel);
9496           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9497             geometry_info.xi,geometry_info.psi,exception);
9498           if (image != (Image *) NULL)
9499             (void) SetImageChannelMask(image,channel_mask);
9500           break;
9501         }
9502         case 70:  /* MotionBlur */
9503         {
9504           if (attribute_flag[0] != 0)
9505             {
9506               flags=ParseGeometry(argument_list[0].string_reference,
9507                 &geometry_info);
9508               if ((flags & SigmaValue) == 0)
9509                 geometry_info.sigma=1.0;
9510               if ((flags & XiValue) == 0)
9511                 geometry_info.xi=1.0;
9512             }
9513           if (attribute_flag[1] != 0)
9514             geometry_info.rho=argument_list[1].real_reference;
9515           if (attribute_flag[2] != 0)
9516             geometry_info.sigma=argument_list[2].real_reference;
9517           if (attribute_flag[3] != 0)
9518             geometry_info.xi=argument_list[3].real_reference;
9519           if (attribute_flag[4] != 0)
9520             channel=(ChannelType) argument_list[4].integer_reference;
9521           channel_mask=SetImageChannelMask(image,channel);
9522           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9523             geometry_info.xi,exception);
9524           if (image != (Image *) NULL)
9525             (void) SetImageChannelMask(image,channel_mask);
9526           break;
9527         }
9528         case 71:  /* OrderedDither */
9529         {
9530           if (attribute_flag[0] == 0)
9531             argument_list[0].string_reference="o8x8";
9532           if (attribute_flag[1] != 0)
9533             channel=(ChannelType) argument_list[1].integer_reference;
9534           channel_mask=SetImageChannelMask(image,channel);
9535           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9536             exception);
9537           (void) SetImageChannelMask(image,channel_mask);
9538           break;
9539         }
9540         case 72:  /* Shave */
9541         {
9542           if (attribute_flag[0] != 0)
9543             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9544               &geometry,exception);
9545           if (attribute_flag[1] != 0)
9546             geometry.width=argument_list[1].integer_reference;
9547           if (attribute_flag[2] != 0)
9548             geometry.height=argument_list[2].integer_reference;
9549           image=ShaveImage(image,&geometry,exception);
9550           break;
9551         }
9552         case 73:  /* Level */
9553         {
9554           double
9555             black_point,
9556             gamma,
9557             white_point;
9558
9559           black_point=0.0;
9560           white_point=(double) image->columns*image->rows;
9561           gamma=1.0;
9562           if (attribute_flag[0] != 0)
9563             {
9564               flags=ParseGeometry(argument_list[0].string_reference,
9565                 &geometry_info);
9566               black_point=geometry_info.rho;
9567               if ((flags & SigmaValue) != 0)
9568                 white_point=geometry_info.sigma;
9569               if ((flags & XiValue) != 0)
9570                 gamma=geometry_info.xi;
9571               if ((flags & PercentValue) != 0)
9572                 {
9573                   black_point*=(double) (QuantumRange/100.0);
9574                   white_point*=(double) (QuantumRange/100.0);
9575                 }
9576               if ((flags & SigmaValue) == 0)
9577                 white_point=(double) QuantumRange-black_point;
9578             }
9579           if (attribute_flag[1] != 0)
9580             black_point=argument_list[1].real_reference;
9581           if (attribute_flag[2] != 0)
9582             white_point=argument_list[2].real_reference;
9583           if (attribute_flag[3] != 0)
9584             gamma=argument_list[3].real_reference;
9585           if (attribute_flag[4] != 0)
9586             channel=(ChannelType) argument_list[4].integer_reference;
9587           if (attribute_flag[5] != 0)
9588             {
9589               argument_list[0].real_reference=argument_list[5].real_reference;
9590               attribute_flag[0]=attribute_flag[5];
9591             }
9592           channel_mask=SetImageChannelMask(image,channel);
9593           (void) LevelImage(image,black_point,white_point,gamma,exception);
9594           (void) SetImageChannelMask(image,channel_mask);
9595           break;
9596         }
9597         case 74:  /* Clip */
9598         {
9599           if (attribute_flag[0] == 0)
9600             argument_list[0].string_reference="#1";
9601           if (attribute_flag[1] == 0)
9602             argument_list[1].integer_reference=MagickTrue;
9603           (void) ClipImagePath(image,argument_list[0].string_reference,
9604             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9605             exception);
9606           break;
9607         }
9608         case 75:  /* AffineTransform */
9609         {
9610           DrawInfo
9611             *draw_info;
9612
9613           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9614             (DrawInfo *) NULL);
9615           if (attribute_flag[0] != 0)
9616             {
9617               AV
9618                 *av;
9619
9620               av=(AV *) argument_list[0].array_reference;
9621               if ((av_len(av) != 3) && (av_len(av) != 5))
9622                 {
9623                   ThrowPerlException(exception,OptionError,
9624                     "affine matrix must have 4 or 6 elements",PackageName);
9625                   goto PerlException;
9626                 }
9627               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9628               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9629               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9630               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9631               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9632                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9633                 {
9634                   ThrowPerlException(exception,OptionError,
9635                     "affine matrix is singular",PackageName);
9636                    goto PerlException;
9637                 }
9638               if (av_len(av) == 5)
9639                 {
9640                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9641                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9642                 }
9643             }
9644           for (j=1; j < 6; j++)
9645           {
9646             if (attribute_flag[j] == 0)
9647               continue;
9648             value=argument_list[j].string_reference;
9649             angle=argument_list[j].real_reference;
9650             current=draw_info->affine;
9651             GetAffineMatrix(&affine);
9652             switch (j)
9653             {
9654               case 1:
9655               {
9656                 /*
9657                   Translate.
9658                 */
9659                 flags=ParseGeometry(value,&geometry_info);
9660                 affine.tx=geometry_info.xi;
9661                 affine.ty=geometry_info.psi;
9662                 if ((flags & PsiValue) == 0)
9663                   affine.ty=affine.tx;
9664                 break;
9665               }
9666               case 2:
9667               {
9668                 /*
9669                   Scale.
9670                 */
9671                 flags=ParseGeometry(value,&geometry_info);
9672                 affine.sx=geometry_info.rho;
9673                 affine.sy=geometry_info.sigma;
9674                 if ((flags & SigmaValue) == 0)
9675                   affine.sy=affine.sx;
9676                 break;
9677               }
9678               case 3:
9679               {
9680                 /*
9681                   Rotate.
9682                 */
9683                 if (angle == 0.0)
9684                   break;
9685                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9686                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9687                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9688                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9689                 break;
9690               }
9691               case 4:
9692               {
9693                 /*
9694                   SkewX.
9695                 */
9696                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9697                 break;
9698               }
9699               case 5:
9700               {
9701                 /*
9702                   SkewY.
9703                 */
9704                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9705                 break;
9706               }
9707             }
9708             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9709             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9710             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9711             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9712             draw_info->affine.tx=
9713               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9714             draw_info->affine.ty=
9715               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9716           }
9717           if (attribute_flag[6] != 0)
9718             image->interpolate=(PixelInterpolateMethod)
9719               argument_list[6].integer_reference;
9720           if (attribute_flag[7] != 0)
9721             QueryColorCompliance(argument_list[7].string_reference,
9722               AllCompliance,&image->background_color,exception);
9723           image=AffineTransformImage(image,&draw_info->affine,exception);
9724           draw_info=DestroyDrawInfo(draw_info);
9725           break;
9726         }
9727         case 76:  /* Difference */
9728         {
9729           if (attribute_flag[0] == 0)
9730             {
9731               ThrowPerlException(exception,OptionError,
9732                 "ReferenceImageRequired",PackageName);
9733               goto PerlException;
9734             }
9735           if (attribute_flag[1] != 0)
9736             image->fuzz=StringToDoubleInterval(
9737               argument_list[1].string_reference,(double) QuantumRange+1.0);
9738           (void) IsImagesEqual(image,argument_list[0].image_reference,
9739             exception);
9740           break;
9741         }
9742         case 77:  /* AdaptiveThreshold */
9743         {
9744           if (attribute_flag[0] != 0)
9745             {
9746               flags=ParseGeometry(argument_list[0].string_reference,
9747                 &geometry_info);
9748               if ((flags & PercentValue) != 0)
9749                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9750             }
9751           if (attribute_flag[1] != 0)
9752             geometry_info.rho=argument_list[1].integer_reference;
9753           if (attribute_flag[2] != 0)
9754             geometry_info.sigma=argument_list[2].integer_reference;
9755           if (attribute_flag[3] != 0)
9756             geometry_info.xi=argument_list[3].integer_reference;;
9757           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9758             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9759           break;
9760         }
9761         case 78:  /* Resample */
9762         {
9763           size_t
9764             height,
9765             width;
9766
9767           if (attribute_flag[0] != 0)
9768             {
9769               flags=ParseGeometry(argument_list[0].string_reference,
9770                 &geometry_info);
9771               if ((flags & SigmaValue) == 0)
9772                 geometry_info.sigma=geometry_info.rho;
9773             }
9774           if (attribute_flag[1] != 0)
9775             geometry_info.rho=argument_list[1].real_reference;
9776           if (attribute_flag[2] != 0)
9777             geometry_info.sigma=argument_list[2].real_reference;
9778           if (attribute_flag[3] == 0)
9779             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9780           if (attribute_flag[4] == 0)
9781             SetImageArtifact(image,"filter:support",
9782               argument_list[4].string_reference);
9783           width=(size_t) (geometry_info.rho*image->columns/
9784             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9785           height=(size_t) (geometry_info.sigma*image->rows/
9786             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9787           image=ResizeImage(image,width,height,(FilterTypes)
9788             argument_list[3].integer_reference,exception);
9789           if (image != (Image *) NULL)
9790             {
9791               image->resolution.x=geometry_info.rho;
9792               image->resolution.y=geometry_info.sigma;
9793             }
9794           break;
9795         }
9796         case 79:  /* Describe */
9797         {
9798           if (attribute_flag[0] == 0)
9799             argument_list[0].file_reference=(FILE *) NULL;
9800           if (attribute_flag[1] != 0)
9801             (void) SetImageArtifact(image,"identify:features",
9802               argument_list[1].string_reference);
9803           (void) IdentifyImage(image,argument_list[0].file_reference,
9804             MagickTrue,exception);
9805           break;
9806         }
9807         case 80:  /* BlackThreshold */
9808         {
9809           if (attribute_flag[0] == 0)
9810             argument_list[0].string_reference="50%";
9811           if (attribute_flag[2] != 0)
9812             channel=(ChannelType) argument_list[2].integer_reference;
9813           channel_mask=SetImageChannelMask(image,channel);
9814           BlackThresholdImage(image,argument_list[0].string_reference,
9815             exception);
9816           (void) SetImageChannelMask(image,channel_mask);
9817           break;
9818         }
9819         case 81:  /* WhiteThreshold */
9820         {
9821           if (attribute_flag[0] == 0)
9822             argument_list[0].string_reference="50%";
9823           if (attribute_flag[2] != 0)
9824             channel=(ChannelType) argument_list[2].integer_reference;
9825           channel_mask=SetImageChannelMask(image,channel);
9826           WhiteThresholdImage(image,argument_list[0].string_reference,
9827             exception);
9828           (void) SetImageChannelMask(image,channel_mask);
9829           break;
9830         }
9831         case 82:  /* RadialBlur */
9832         {
9833           if (attribute_flag[0] != 0)
9834             {
9835               flags=ParseGeometry(argument_list[0].string_reference,
9836                 &geometry_info);
9837             }
9838           if (attribute_flag[1] != 0)
9839             geometry_info.rho=argument_list[1].real_reference;
9840           if (attribute_flag[2] != 0)
9841             channel=(ChannelType) argument_list[2].integer_reference;
9842           channel_mask=SetImageChannelMask(image,channel);
9843           image=RadialBlurImage(image,geometry_info.rho,exception);
9844           if (image != (Image *) NULL)
9845             (void) SetImageChannelMask(image,channel_mask);
9846           break;
9847         }
9848         case 83:  /* Thumbnail */
9849         {
9850           if (attribute_flag[0] != 0)
9851             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9852               &geometry,exception);
9853           if (attribute_flag[1] != 0)
9854             geometry.width=argument_list[1].integer_reference;
9855           if (attribute_flag[2] != 0)
9856             geometry.height=argument_list[2].integer_reference;
9857           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9858           break;
9859         }
9860         case 84:  /* Strip */
9861         {
9862           (void) StripImage(image,exception);
9863           break;
9864         }
9865         case 85:  /* Tint */
9866         {
9867           PixelInfo
9868             tint;
9869
9870           GetPixelInfo(image,&tint);
9871           if (attribute_flag[0] != 0)
9872             (void) QueryColorCompliance(argument_list[0].string_reference,
9873               AllCompliance,&tint,exception);
9874           if (attribute_flag[1] == 0)
9875             argument_list[1].string_reference="100";
9876           image=TintImage(image,argument_list[1].string_reference,&tint,
9877             exception);
9878           break;
9879         }
9880         case 86:  /* Channel */
9881         {
9882           if (attribute_flag[0] != 0)
9883             channel=(ChannelType) argument_list[0].integer_reference;
9884           image=SeparateImage(image,channel,exception);
9885           break;
9886         }
9887         case 87:  /* Splice */
9888         {
9889           if (attribute_flag[0] != 0)
9890             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9891               &geometry,exception);
9892           if (attribute_flag[1] != 0)
9893             geometry.width=argument_list[1].integer_reference;
9894           if (attribute_flag[2] != 0)
9895             geometry.height=argument_list[2].integer_reference;
9896           if (attribute_flag[3] != 0)
9897             geometry.x=argument_list[3].integer_reference;
9898           if (attribute_flag[4] != 0)
9899             geometry.y=argument_list[4].integer_reference;
9900           if (attribute_flag[5] != 0)
9901             image->fuzz=StringToDoubleInterval(
9902               argument_list[5].string_reference,(double) QuantumRange+1.0);
9903           if (attribute_flag[6] != 0)
9904             (void) QueryColorCompliance(argument_list[6].string_reference,
9905               AllCompliance,&image->background_color,exception);
9906           if (attribute_flag[7] != 0)
9907             image->gravity=(GravityType) argument_list[7].integer_reference;
9908           image=SpliceImage(image,&geometry,exception);
9909           break;
9910         }
9911         case 88:  /* Posterize */
9912         {
9913           if (attribute_flag[0] == 0)
9914             argument_list[0].integer_reference=3;
9915           if (attribute_flag[1] == 0)
9916             argument_list[1].integer_reference=0;
9917           (void) PosterizeImage(image,argument_list[0].integer_reference,
9918             argument_list[1].integer_reference ? RiemersmaDitherMethod :
9919             NoDitherMethod,exception);
9920           break;
9921         }
9922         case 89:  /* Shadow */
9923         {
9924           if (attribute_flag[0] != 0)
9925             {
9926               flags=ParseGeometry(argument_list[0].string_reference,
9927                 &geometry_info);
9928               if ((flags & SigmaValue) == 0)
9929                 geometry_info.sigma=1.0;
9930               if ((flags & XiValue) == 0)
9931                 geometry_info.xi=4.0;
9932               if ((flags & PsiValue) == 0)
9933                 geometry_info.psi=4.0;
9934             }
9935           if (attribute_flag[1] != 0)
9936             geometry_info.rho=argument_list[1].real_reference;
9937           if (attribute_flag[2] != 0)
9938             geometry_info.sigma=argument_list[2].real_reference;
9939           if (attribute_flag[3] != 0)
9940             geometry_info.xi=argument_list[3].integer_reference;
9941           if (attribute_flag[4] != 0)
9942             geometry_info.psi=argument_list[4].integer_reference;
9943           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9944             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
9945             ceil(geometry_info.psi-0.5),exception);
9946           break;
9947         }
9948         case 90:  /* Identify */
9949         {
9950           if (attribute_flag[0] == 0)
9951             argument_list[0].file_reference=(FILE *) NULL;
9952           if (attribute_flag[1] != 0)
9953             (void) SetImageArtifact(image,"identify:features",
9954               argument_list[1].string_reference);
9955           if ((attribute_flag[2] != 0) &&
9956               (argument_list[2].integer_reference != 0))
9957             (void) SetImageArtifact(image,"identify:unique","true");
9958           (void) IdentifyImage(image,argument_list[0].file_reference,
9959             MagickTrue,exception);
9960           break;
9961         }
9962         case 91:  /* SepiaTone */
9963         {
9964           if (attribute_flag[0] == 0)
9965             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9966           image=SepiaToneImage(image,argument_list[0].real_reference,
9967             exception);
9968           break;
9969         }
9970         case 92:  /* SigmoidalContrast */
9971         {
9972           MagickBooleanType
9973             sharpen;
9974
9975           if (attribute_flag[0] != 0)
9976             {
9977               flags=ParseGeometry(argument_list[0].string_reference,
9978                 &geometry_info);
9979               if ((flags & SigmaValue) == 0)
9980                 geometry_info.sigma=QuantumRange/2.0;
9981               if ((flags & PercentValue) != 0)
9982                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9983             }
9984           if (attribute_flag[1] != 0)
9985             geometry_info.rho=argument_list[1].real_reference;
9986           if (attribute_flag[2] != 0)
9987             geometry_info.sigma=argument_list[2].real_reference;
9988           if (attribute_flag[3] != 0)
9989             channel=(ChannelType) argument_list[3].integer_reference;
9990           sharpen=MagickTrue;
9991           if (attribute_flag[4] != 0)
9992             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9993               MagickFalse;
9994           channel_mask=SetImageChannelMask(image,channel);
9995           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
9996             geometry_info.sigma,exception);
9997           (void) SetImageChannelMask(image,channel_mask);
9998           break;
9999         }
10000         case 93:  /* Extent */
10001         {
10002           if (attribute_flag[7] != 0)
10003             image->gravity=(GravityType) argument_list[7].integer_reference;
10004           if (attribute_flag[0] != 0)
10005             {
10006               int
10007                 flags;
10008
10009               flags=ParseGravityGeometry(image,
10010                 argument_list[0].string_reference,&geometry,exception);
10011               (void) flags;
10012               if (geometry.width == 0)
10013                 geometry.width=image->columns;
10014               if (geometry.height == 0)
10015                 geometry.height=image->rows;
10016             }
10017           if (attribute_flag[1] != 0)
10018             geometry.width=argument_list[1].integer_reference;
10019           if (attribute_flag[2] != 0)
10020             geometry.height=argument_list[2].integer_reference;
10021           if (attribute_flag[3] != 0)
10022             geometry.x=argument_list[3].integer_reference;
10023           if (attribute_flag[4] != 0)
10024             geometry.y=argument_list[4].integer_reference;
10025           if (attribute_flag[5] != 0)
10026             image->fuzz=StringToDoubleInterval(
10027               argument_list[5].string_reference,(double) QuantumRange+1.0);
10028           if (attribute_flag[6] != 0)
10029             (void) QueryColorCompliance(argument_list[6].string_reference,
10030               AllCompliance,&image->background_color,exception);
10031           image=ExtentImage(image,&geometry,exception);
10032           break;
10033         }
10034         case 94:  /* Vignette */
10035         {
10036           if (attribute_flag[0] != 0)
10037             {
10038               flags=ParseGeometry(argument_list[0].string_reference,
10039                 &geometry_info);
10040               if ((flags & SigmaValue) == 0)
10041                 geometry_info.sigma=1.0;
10042               if ((flags & XiValue) == 0)
10043                 geometry_info.xi=0.1*image->columns;
10044               if ((flags & PsiValue) == 0)
10045                 geometry_info.psi=0.1*image->rows;
10046             }
10047           if (attribute_flag[1] != 0)
10048             geometry_info.rho=argument_list[1].real_reference;
10049           if (attribute_flag[2] != 0)
10050             geometry_info.sigma=argument_list[2].real_reference;
10051           if (attribute_flag[3] != 0)
10052             geometry_info.xi=argument_list[3].integer_reference;
10053           if (attribute_flag[4] != 0)
10054             geometry_info.psi=argument_list[4].integer_reference;
10055           if (attribute_flag[5] != 0)
10056             (void) QueryColorCompliance(argument_list[5].string_reference,
10057               AllCompliance,&image->background_color,exception);
10058           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10059             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10060             ceil(geometry_info.psi-0.5),exception);
10061           break;
10062         }
10063         case 95:  /* ContrastStretch */
10064         {
10065           double
10066             black_point,
10067             white_point;
10068
10069           black_point=0.0;
10070           white_point=(double) image->columns*image->rows;
10071           if (attribute_flag[0] != 0)
10072             {
10073               flags=ParseGeometry(argument_list[0].string_reference,
10074                 &geometry_info);
10075               black_point=geometry_info.rho;
10076               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10077                 black_point;
10078               if ((flags & PercentValue) != 0)
10079                 {
10080                   black_point*=(double) image->columns*image->rows/100.0;
10081                   white_point*=(double) image->columns*image->rows/100.0;
10082                 }
10083               white_point=(double) image->columns*image->rows-
10084                 white_point;
10085             }
10086           if (attribute_flag[1] != 0)
10087             black_point=argument_list[1].real_reference;
10088           if (attribute_flag[2] != 0)
10089             white_point=argument_list[2].real_reference;
10090           if (attribute_flag[4] != 0)
10091             channel=(ChannelType) argument_list[4].integer_reference;
10092           channel_mask=SetImageChannelMask(image,channel);
10093           (void) ContrastStretchImage(image,black_point,white_point,exception);
10094           (void) SetImageChannelMask(image,channel_mask);
10095           break;
10096         }
10097         case 96:  /* Sans0 */
10098         {
10099           break;
10100         }
10101         case 97:  /* Sans1 */
10102         {
10103           break;
10104         }
10105         case 98:  /* AdaptiveSharpen */
10106         {
10107           if (attribute_flag[0] != 0)
10108             {
10109               flags=ParseGeometry(argument_list[0].string_reference,
10110                 &geometry_info);
10111               if ((flags & SigmaValue) == 0)
10112                 geometry_info.sigma=1.0;
10113               if ((flags & XiValue) == 0)
10114                 geometry_info.xi=0.0;
10115             }
10116           if (attribute_flag[1] != 0)
10117             geometry_info.rho=argument_list[1].real_reference;
10118           if (attribute_flag[2] != 0)
10119             geometry_info.sigma=argument_list[2].real_reference;
10120           if (attribute_flag[3] != 0)
10121             geometry_info.xi=argument_list[3].real_reference;
10122           if (attribute_flag[4] != 0)
10123             channel=(ChannelType) argument_list[4].integer_reference;
10124           channel_mask=SetImageChannelMask(image,channel);
10125           image=AdaptiveSharpenImage(image,geometry_info.rho,
10126             geometry_info.sigma,exception);
10127           if (image != (Image *) NULL)
10128             (void) SetImageChannelMask(image,channel_mask);
10129           break;
10130         }
10131         case 99:  /* Transpose */
10132         {
10133           image=TransposeImage(image,exception);
10134           break;
10135         }
10136         case 100:  /* Tranverse */
10137         {
10138           image=TransverseImage(image,exception);
10139           break;
10140         }
10141         case 101:  /* AutoOrient */
10142         {
10143           image=AutoOrientImage(image,image->orientation,exception);
10144           break;
10145         }
10146         case 102:  /* AdaptiveBlur */
10147         {
10148           if (attribute_flag[0] != 0)
10149             {
10150               flags=ParseGeometry(argument_list[0].string_reference,
10151                 &geometry_info);
10152               if ((flags & SigmaValue) == 0)
10153                 geometry_info.sigma=1.0;
10154               if ((flags & XiValue) == 0)
10155                 geometry_info.xi=0.0;
10156             }
10157           if (attribute_flag[1] != 0)
10158             geometry_info.rho=argument_list[1].real_reference;
10159           if (attribute_flag[2] != 0)
10160             geometry_info.sigma=argument_list[2].real_reference;
10161           if (attribute_flag[3] != 0)
10162             channel=(ChannelType) argument_list[3].integer_reference;
10163           channel_mask=SetImageChannelMask(image,channel);
10164           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10165             exception);
10166           if (image != (Image *) NULL)
10167             (void) SetImageChannelMask(image,channel_mask);
10168           break;
10169         }
10170         case 103:  /* Sketch */
10171         {
10172           if (attribute_flag[0] != 0)
10173             {
10174               flags=ParseGeometry(argument_list[0].string_reference,
10175                 &geometry_info);
10176               if ((flags & SigmaValue) == 0)
10177                 geometry_info.sigma=1.0;
10178               if ((flags & XiValue) == 0)
10179                 geometry_info.xi=1.0;
10180             }
10181           if (attribute_flag[1] != 0)
10182             geometry_info.rho=argument_list[1].real_reference;
10183           if (attribute_flag[2] != 0)
10184             geometry_info.sigma=argument_list[2].real_reference;
10185           if (attribute_flag[3] != 0)
10186             geometry_info.xi=argument_list[3].real_reference;
10187           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10188             geometry_info.xi,exception);
10189           break;
10190         }
10191         case 104:  /* UniqueColors */
10192         {
10193           image=UniqueImageColors(image,exception);
10194           break;
10195         }
10196         case 105:  /* AdaptiveResize */
10197         {
10198           if (attribute_flag[0] != 0)
10199             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10200               &geometry,exception);
10201           if (attribute_flag[1] != 0)
10202             geometry.width=argument_list[1].integer_reference;
10203           if (attribute_flag[2] != 0)
10204             geometry.height=argument_list[2].integer_reference;
10205           if (attribute_flag[3] != 0)
10206             image->filter=(FilterTypes) argument_list[4].integer_reference;
10207           if (attribute_flag[4] != 0)
10208             SetImageArtifact(image,"filter:support",
10209               argument_list[4].string_reference);
10210           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10211             exception);
10212           break;
10213         }
10214         case 106:  /* ClipMask */
10215         {
10216           Image
10217             *mask_image;
10218
10219           if (attribute_flag[0] == 0)
10220             {
10221               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10222                 PackageName);
10223               goto PerlException;
10224             }
10225           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10226             exception);
10227           (void) NegateImage(mask_image,MagickFalse,exception);
10228           (void) SetImageMask(image,mask_image,exception);
10229           mask_image=DestroyImage(mask_image);
10230           break;
10231         }
10232         case 107:  /* LinearStretch */
10233         {
10234            double
10235              black_point,
10236              white_point;
10237
10238            black_point=0.0;
10239            white_point=(double) image->columns*image->rows;
10240            if (attribute_flag[0] != 0)
10241              {
10242                flags=ParseGeometry(argument_list[0].string_reference,
10243                  &geometry_info);
10244                if ((flags & SigmaValue) != 0)
10245                   white_point=geometry_info.sigma;
10246                if ((flags & PercentValue) != 0)
10247                  {
10248                    black_point*=(double) image->columns*image->rows/100.0;
10249                    white_point*=(double) image->columns*image->rows/100.0;
10250                  }
10251                if ((flags & SigmaValue) == 0)
10252                  white_point=(double) image->columns*image->rows-black_point;
10253              }
10254           if (attribute_flag[1] != 0)
10255             black_point=argument_list[1].real_reference;
10256           if (attribute_flag[2] != 0)
10257             white_point=argument_list[2].real_reference;
10258           (void) LinearStretchImage(image,black_point,white_point,exception);
10259           break;
10260         }
10261         case 108:  /* ColorMatrix */
10262         {
10263           AV
10264             *av;
10265
10266           double
10267             *color_matrix;
10268
10269           KernelInfo
10270             *kernel_info;
10271
10272           size_t
10273             order;
10274
10275           if (attribute_flag[0] == 0)
10276             break;
10277           av=(AV *) argument_list[0].array_reference;
10278           order=(size_t) sqrt(av_len(av)+1);
10279           color_matrix=(double *) AcquireQuantumMemory(order,order*
10280             sizeof(*color_matrix));
10281           if (color_matrix == (double *) NULL)
10282             {
10283               ThrowPerlException(exception,ResourceLimitFatalError,
10284                 "MemoryAllocationFailed",PackageName);
10285               goto PerlException;
10286            }
10287           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10288             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10289           for ( ; j < (ssize_t) (order*order); j++)
10290             color_matrix[j]=0.0;
10291           kernel_info=AcquireKernelInfo((const char *) NULL);
10292           if (kernel_info == (KernelInfo *) NULL)
10293             break;
10294           kernel_info->width=order;
10295           kernel_info->height=order;
10296           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10297             order*sizeof(*kernel_info->values));
10298           if (kernel_info->values != (MagickRealType *) NULL)
10299             {
10300               for (i=0; i < (ssize_t) (order*order); i++)
10301                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10302               image=ColorMatrixImage(image,kernel_info,exception);
10303             }
10304           kernel_info=DestroyKernelInfo(kernel_info);
10305           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10306           break;
10307         }
10308         case 109:  /* Mask */
10309         {
10310           Image
10311             *mask_image;
10312
10313           if (attribute_flag[0] == 0)
10314             {
10315               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10316                 PackageName);
10317               goto PerlException;
10318             }
10319           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10320             MagickTrue,exception);
10321           (void) NegateImage(mask_image,MagickFalse,exception);
10322           (void) SetImageMask(image,mask_image,exception);
10323           mask_image=DestroyImage(mask_image);
10324           break;
10325         }
10326         case 110:  /* Polaroid */
10327         {
10328           char
10329             *caption;
10330
10331           DrawInfo
10332             *draw_info;
10333
10334           double
10335             angle;
10336
10337           PixelInterpolateMethod
10338             method;
10339
10340           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10341             (DrawInfo *) NULL);
10342           caption=(char *) NULL;
10343           if (attribute_flag[0] != 0)
10344             caption=InterpretImageProperties(info ? info->image_info :
10345               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10346               exception);
10347           angle=0.0;
10348           if (attribute_flag[1] != 0)
10349             angle=argument_list[1].real_reference;
10350           if (attribute_flag[2] != 0)
10351             (void) CloneString(&draw_info->font,
10352               argument_list[2].string_reference);
10353           if (attribute_flag[3] != 0)
10354             (void) QueryColorCompliance(argument_list[3].string_reference,
10355               AllCompliance,&draw_info->stroke,exception);
10356           if (attribute_flag[4] != 0)
10357             (void) QueryColorCompliance(argument_list[4].string_reference,
10358               AllCompliance,&draw_info->fill,exception);
10359           if (attribute_flag[5] != 0)
10360             draw_info->stroke_width=argument_list[5].real_reference;
10361           if (attribute_flag[6] != 0)
10362             draw_info->pointsize=argument_list[6].real_reference;
10363           if (attribute_flag[7] != 0)
10364             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10365           if (attribute_flag[8] != 0)
10366             (void) QueryColorCompliance(argument_list[8].string_reference,
10367               AllCompliance,&image->background_color,exception);
10368           method=UndefinedInterpolatePixel;
10369           if (attribute_flag[9] != 0)
10370             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10371           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10372           draw_info=DestroyDrawInfo(draw_info);
10373           if (caption != (char *) NULL)
10374             caption=DestroyString(caption);
10375           break;
10376         }
10377         case 111:  /* FloodfillPaint */
10378         {
10379           DrawInfo
10380             *draw_info;
10381
10382           MagickBooleanType
10383             invert;
10384
10385           PixelInfo
10386             target;
10387
10388           draw_info=CloneDrawInfo(info ? info->image_info :
10389             (ImageInfo *) NULL,(DrawInfo *) NULL);
10390           if (attribute_flag[0] != 0)
10391             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10392               &geometry,exception);
10393           if (attribute_flag[1] != 0)
10394             geometry.x=argument_list[1].integer_reference;
10395           if (attribute_flag[2] != 0)
10396             geometry.y=argument_list[2].integer_reference;
10397           if (attribute_flag[3] != 0)
10398             (void) QueryColorCompliance(argument_list[3].string_reference,
10399               AllCompliance,&draw_info->fill,exception);
10400           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10401             geometry.x,geometry.y,&target,exception);
10402           if (attribute_flag[4] != 0)
10403             QueryColorCompliance(argument_list[4].string_reference,
10404               AllCompliance,&target,exception);
10405           if (attribute_flag[5] != 0)
10406             image->fuzz=StringToDoubleInterval(
10407               argument_list[5].string_reference,(double) QuantumRange+1.0);
10408           if (attribute_flag[6] != 0)
10409             channel=(ChannelType) argument_list[6].integer_reference;
10410           invert=MagickFalse;
10411           if (attribute_flag[7] != 0)
10412             invert=(MagickBooleanType) argument_list[7].integer_reference;
10413           channel_mask=SetImageChannelMask(image,channel);
10414           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10415             geometry.y,invert,exception);
10416           (void) SetImageChannelMask(image,channel_mask);
10417           draw_info=DestroyDrawInfo(draw_info);
10418           break;
10419         }
10420         case 112:  /* Distort */
10421         {
10422           AV
10423             *av;
10424
10425           double
10426             *coordinates;
10427
10428           DistortImageMethod
10429             method;
10430
10431           size_t
10432             number_coordinates;
10433
10434           VirtualPixelMethod
10435             virtual_pixel;
10436
10437           if (attribute_flag[0] == 0)
10438             break;
10439           method=UndefinedDistortion;
10440           if (attribute_flag[1] != 0)
10441             method=(DistortImageMethod) argument_list[1].integer_reference;
10442           av=(AV *) argument_list[0].array_reference;
10443           number_coordinates=(size_t) av_len(av)+1;
10444           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10445             sizeof(*coordinates));
10446           if (coordinates == (double *) NULL)
10447             {
10448               ThrowPerlException(exception,ResourceLimitFatalError,
10449                 "MemoryAllocationFailed",PackageName);
10450               goto PerlException;
10451             }
10452           for (j=0; j < (ssize_t) number_coordinates; j++)
10453             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10454           virtual_pixel=UndefinedVirtualPixelMethod;
10455           if (attribute_flag[2] != 0)
10456             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10457               argument_list[2].integer_reference,exception);
10458           image=DistortImage(image,method,number_coordinates,coordinates,
10459             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10460             exception);
10461           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10462             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10463               exception);
10464           coordinates=(double *) RelinquishMagickMemory(coordinates);
10465           break;
10466         }
10467         case 113:  /* Clut */
10468         {
10469           PixelInterpolateMethod
10470             method;
10471
10472           if (attribute_flag[0] == 0)
10473             {
10474               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10475                 PackageName);
10476               goto PerlException;
10477             }
10478           method=UndefinedInterpolatePixel;
10479           if (attribute_flag[1] != 0)
10480             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10481           if (attribute_flag[2] != 0)
10482             channel=(ChannelType) argument_list[2].integer_reference;
10483           channel_mask=SetImageChannelMask(image,channel);
10484           (void) ClutImage(image,argument_list[0].image_reference,method,
10485             exception);
10486           (void) SetImageChannelMask(image,channel_mask);
10487           break;
10488         }
10489         case 114:  /* LiquidRescale */
10490         {
10491           if (attribute_flag[0] != 0)
10492             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10493               &geometry,exception);
10494           if (attribute_flag[1] != 0)
10495             geometry.width=argument_list[1].integer_reference;
10496           if (attribute_flag[2] != 0)
10497             geometry.height=argument_list[2].integer_reference;
10498           if (attribute_flag[3] == 0)
10499             argument_list[3].real_reference=1.0;
10500           if (attribute_flag[4] == 0)
10501             argument_list[4].real_reference=0.0;
10502           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10503             argument_list[3].real_reference,argument_list[4].real_reference,
10504             exception);
10505           break;
10506         }
10507         case 115:  /* EncipherImage */
10508         {
10509           (void) EncipherImage(image,argument_list[0].string_reference,
10510             exception);
10511           break;
10512         }
10513         case 116:  /* DecipherImage */
10514         {
10515           (void) DecipherImage(image,argument_list[0].string_reference,
10516             exception);
10517           break;
10518         }
10519         case 117:  /* Deskew */
10520         {
10521           geometry_info.rho=QuantumRange/2.0;
10522           if (attribute_flag[0] != 0)
10523             flags=ParseGeometry(argument_list[0].string_reference,
10524               &geometry_info);
10525           if (attribute_flag[1] != 0)
10526             geometry_info.rho=StringToDoubleInterval(
10527               argument_list[1].string_reference,(double) QuantumRange+1.0);
10528           image=DeskewImage(image,geometry_info.rho,exception);
10529           break;
10530         }
10531         case 118:  /* Remap */
10532         {
10533           QuantizeInfo
10534             *quantize_info;
10535
10536           if (attribute_flag[0] == 0)
10537             {
10538               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10539                 PackageName);
10540               goto PerlException;
10541             }
10542           quantize_info=AcquireQuantizeInfo(info->image_info);
10543           if (attribute_flag[1] != 0)
10544             quantize_info->dither_method=(DitherMethod)
10545               argument_list[1].integer_reference;
10546           (void) RemapImages(quantize_info,image,
10547             argument_list[0].image_reference,exception);
10548           quantize_info=DestroyQuantizeInfo(quantize_info);
10549           break;
10550         }
10551         case 119:  /* SparseColor */
10552         {
10553           AV
10554             *av;
10555
10556           double
10557             *coordinates;
10558
10559           SparseColorMethod
10560             method;
10561
10562           size_t
10563             number_coordinates;
10564
10565           VirtualPixelMethod
10566             virtual_pixel;
10567
10568           if (attribute_flag[0] == 0)
10569             break;
10570           method=UndefinedColorInterpolate;
10571           if (attribute_flag[1] != 0)
10572             method=(SparseColorMethod) argument_list[1].integer_reference;
10573           av=(AV *) argument_list[0].array_reference;
10574           number_coordinates=(size_t) av_len(av)+1;
10575           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10576             sizeof(*coordinates));
10577           if (coordinates == (double *) NULL)
10578             {
10579               ThrowPerlException(exception,ResourceLimitFatalError,
10580                 "MemoryAllocationFailed",PackageName);
10581               goto PerlException;
10582             }
10583           for (j=0; j < (ssize_t) number_coordinates; j++)
10584             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10585           virtual_pixel=UndefinedVirtualPixelMethod;
10586           if (attribute_flag[2] != 0)
10587             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10588               argument_list[2].integer_reference,exception);
10589           if (attribute_flag[3] != 0)
10590             channel=(ChannelType) argument_list[3].integer_reference;
10591           channel_mask=SetImageChannelMask(image,channel);
10592           image=SparseColorImage(image,method,number_coordinates,coordinates,
10593             exception);
10594           if (image != (Image *) NULL)
10595             (void) SetImageChannelMask(image,channel_mask);
10596           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10597             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10598               exception);
10599           coordinates=(double *) RelinquishMagickMemory(coordinates);
10600           break;
10601         }
10602         case 120:  /* Function */
10603         {
10604           AV
10605             *av;
10606
10607           double
10608             *parameters;
10609
10610           MagickFunction
10611             function;
10612
10613           size_t
10614             number_parameters;
10615
10616           VirtualPixelMethod
10617             virtual_pixel;
10618
10619           if (attribute_flag[0] == 0)
10620             break;
10621           function=UndefinedFunction;
10622           if (attribute_flag[1] != 0)
10623             function=(MagickFunction) argument_list[1].integer_reference;
10624           av=(AV *) argument_list[0].array_reference;
10625           number_parameters=(size_t) av_len(av)+1;
10626           parameters=(double *) AcquireQuantumMemory(number_parameters,
10627             sizeof(*parameters));
10628           if (parameters == (double *) NULL)
10629             {
10630               ThrowPerlException(exception,ResourceLimitFatalError,
10631                 "MemoryAllocationFailed",PackageName);
10632               goto PerlException;
10633             }
10634           for (j=0; j < (ssize_t) number_parameters; j++)
10635             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10636           virtual_pixel=UndefinedVirtualPixelMethod;
10637           if (attribute_flag[2] != 0)
10638             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10639               argument_list[2].integer_reference,exception);
10640           (void) FunctionImage(image,function,number_parameters,parameters,
10641             exception);
10642           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10643             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10644               exception);
10645           parameters=(double *) RelinquishMagickMemory(parameters);
10646           break;
10647         }
10648         case 121:  /* SelectiveBlur */
10649         {
10650           if (attribute_flag[0] != 0)
10651             {
10652               flags=ParseGeometry(argument_list[0].string_reference,
10653                 &geometry_info);
10654               if ((flags & SigmaValue) == 0)
10655                 geometry_info.sigma=1.0;
10656               if ((flags & PercentValue) != 0)
10657                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10658             }
10659           if (attribute_flag[1] != 0)
10660             geometry_info.rho=argument_list[1].real_reference;
10661           if (attribute_flag[2] != 0)
10662             geometry_info.sigma=argument_list[2].real_reference;
10663           if (attribute_flag[3] != 0)
10664             geometry_info.xi=argument_list[3].integer_reference;;
10665           if (attribute_flag[5] != 0)
10666             channel=(ChannelType) argument_list[5].integer_reference;
10667           channel_mask=SetImageChannelMask(image,channel);
10668           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10669             geometry_info.xi,exception);
10670           if (image != (Image *) NULL)
10671             (void) SetImageChannelMask(image,channel_mask);
10672           break;
10673         }
10674         case 122:  /* HaldClut */
10675         {
10676           if (attribute_flag[0] == 0)
10677             {
10678               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10679                 PackageName);
10680               goto PerlException;
10681             }
10682           if (attribute_flag[1] != 0)
10683             channel=(ChannelType) argument_list[1].integer_reference;
10684           channel_mask=SetImageChannelMask(image,channel);
10685           (void) HaldClutImage(image,argument_list[0].image_reference,
10686             exception);
10687           (void) SetImageChannelMask(image,channel_mask);
10688           break;
10689         }
10690         case 123:  /* BlueShift */
10691         {
10692           if (attribute_flag[0] != 0)
10693             (void) ParseGeometry(argument_list[0].string_reference,
10694               &geometry_info);
10695           image=BlueShiftImage(image,geometry_info.rho,exception);
10696           break;
10697         }
10698         case 124:  /* ForwardFourierTransformImage */
10699         {
10700           image=ForwardFourierTransformImage(image,
10701             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10702             exception);
10703           break;
10704         }
10705         case 125:  /* InverseFourierTransformImage */
10706         {
10707           image=InverseFourierTransformImage(image,image->next,
10708             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10709             exception);
10710           break;
10711         }
10712         case 126:  /* ColorDecisionList */
10713         {
10714           if (attribute_flag[0] == 0)
10715             argument_list[0].string_reference=(char *) NULL;
10716           (void) ColorDecisionListImage(image,
10717             argument_list[0].string_reference,exception);
10718           break;
10719         }
10720         case 127:  /* AutoGamma */
10721         {
10722           if (attribute_flag[0] != 0)
10723             channel=(ChannelType) argument_list[0].integer_reference;
10724           channel_mask=SetImageChannelMask(image,channel);
10725           (void) AutoGammaImage(image,exception);
10726           (void) SetImageChannelMask(image,channel_mask);
10727           break;
10728         }
10729         case 128:  /* AutoLevel */
10730         {
10731           if (attribute_flag[0] != 0)
10732             channel=(ChannelType) argument_list[0].integer_reference;
10733           channel_mask=SetImageChannelMask(image,channel);
10734           (void) AutoLevelImage(image,exception);
10735           (void) SetImageChannelMask(image,channel_mask);
10736           break;
10737         }
10738         case 129:  /* LevelColors */
10739         {
10740           PixelInfo
10741             black_point,
10742             white_point;
10743
10744           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10745             exception);
10746           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10747             exception);
10748           if (attribute_flag[1] != 0)
10749              (void) QueryColorCompliance(
10750                argument_list[1].string_reference,AllCompliance,&black_point,
10751                exception);
10752           if (attribute_flag[2] != 0)
10753              (void) QueryColorCompliance(
10754                argument_list[2].string_reference,AllCompliance,&white_point,
10755                exception);
10756           if (attribute_flag[3] != 0)
10757             channel=(ChannelType) argument_list[3].integer_reference;
10758           channel_mask=SetImageChannelMask(image,channel);
10759           (void) LevelImageColors(image,&black_point,&white_point,
10760             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10761             exception);
10762           (void) SetImageChannelMask(image,channel_mask);
10763           break;
10764         }
10765         case 130:  /* Clamp */
10766         {
10767           if (attribute_flag[0] != 0)
10768             channel=(ChannelType) argument_list[0].integer_reference;
10769           channel_mask=SetImageChannelMask(image,channel);
10770           (void) ClampImage(image,exception);
10771           (void) SetImageChannelMask(image,channel_mask);
10772           break;
10773         }
10774         case 131:  /* BrightnessContrast */
10775         {
10776           double
10777             brightness,
10778             contrast;
10779
10780           brightness=0.0;
10781           contrast=0.0;
10782           if (attribute_flag[0] != 0)
10783             {
10784               flags=ParseGeometry(argument_list[0].string_reference,
10785                 &geometry_info);
10786               brightness=geometry_info.rho;
10787               if ((flags & SigmaValue) == 0)
10788                 contrast=geometry_info.sigma;
10789             }
10790           if (attribute_flag[1] != 0)
10791             brightness=argument_list[1].real_reference;
10792           if (attribute_flag[2] != 0)
10793             contrast=argument_list[2].real_reference;
10794           if (attribute_flag[4] != 0)
10795             channel=(ChannelType) argument_list[4].integer_reference;
10796           channel_mask=SetImageChannelMask(image,channel);
10797           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10798           (void) SetImageChannelMask(image,channel_mask);
10799           break;
10800         }
10801         case 132:  /* Morphology */
10802         {
10803           KernelInfo
10804             *kernel;
10805
10806           MorphologyMethod
10807             method;
10808
10809           ssize_t
10810             iterations;
10811
10812           if (attribute_flag[0] == 0)
10813             break;
10814           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10815           if (kernel == (KernelInfo *) NULL)
10816             break;
10817           if (attribute_flag[1] != 0)
10818             channel=(ChannelType) argument_list[1].integer_reference;
10819           method=UndefinedMorphology;
10820           if (attribute_flag[2] != 0)
10821             method=argument_list[2].integer_reference;
10822           iterations=1;
10823           if (attribute_flag[3] != 0)
10824             iterations=argument_list[3].integer_reference;
10825           channel_mask=SetImageChannelMask(image,channel);
10826           image=MorphologyImage(image,method,iterations,kernel,exception);
10827           if (image != (Image *) NULL)
10828             (void) SetImageChannelMask(image,channel_mask);
10829           kernel=DestroyKernelInfo(kernel);
10830           break;
10831         }
10832         case 133:  /* Mode */
10833         {
10834           if (attribute_flag[0] != 0)
10835             {
10836               flags=ParseGeometry(argument_list[0].string_reference,
10837                 &geometry_info);
10838               if ((flags & SigmaValue) == 0)
10839                 geometry_info.sigma=1.0;
10840             }
10841           if (attribute_flag[1] != 0)
10842             geometry_info.rho=argument_list[1].real_reference;
10843           if (attribute_flag[2] != 0)
10844             geometry_info.sigma=argument_list[2].real_reference;
10845           if (attribute_flag[3] != 0)
10846             channel=(ChannelType) argument_list[3].integer_reference;
10847           channel_mask=SetImageChannelMask(image,channel);
10848           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
10849             (size_t) geometry_info.sigma,exception);
10850           if (image != (Image *) NULL)
10851             (void) SetImageChannelMask(image,channel_mask);
10852           break;
10853         }
10854         case 134:  /* Statistic */
10855         {
10856           StatisticType
10857             statistic;
10858
10859           statistic=UndefinedStatistic;
10860           if (attribute_flag[0] != 0)
10861             {
10862               flags=ParseGeometry(argument_list[0].string_reference,
10863                 &geometry_info);
10864               if ((flags & SigmaValue) == 0)
10865                 geometry_info.sigma=1.0;
10866             }
10867           if (attribute_flag[1] != 0)
10868             geometry_info.rho=argument_list[1].real_reference;
10869           if (attribute_flag[2] != 0)
10870             geometry_info.sigma=argument_list[2].real_reference;
10871           if (attribute_flag[3] != 0)
10872             channel=(ChannelType) argument_list[3].integer_reference;
10873           if (attribute_flag[4] != 0)
10874             statistic=(StatisticType) argument_list[4].integer_reference;
10875           channel_mask=SetImageChannelMask(image,channel);
10876           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
10877             (size_t) geometry_info.sigma,exception);
10878           if (image != (Image *) NULL)
10879             (void) SetImageChannelMask(image,channel_mask);
10880           break;
10881         }
10882         case 135:  /* Perceptible */
10883         {
10884           double
10885             epsilon;
10886
10887           epsilon=MagickEpsilon;
10888           if (attribute_flag[0] != 0)
10889             epsilon=argument_list[0].real_reference;
10890           if (attribute_flag[1] != 0)
10891             channel=(ChannelType) argument_list[1].integer_reference;
10892           channel_mask=SetImageChannelMask(image,channel);
10893           (void) PerceptibleImage(image,epsilon,exception);
10894           (void) SetImageChannelMask(image,channel_mask);
10895           break;
10896         }
10897         case 136:  /* Poly */
10898         {
10899           AV
10900             *av;
10901
10902           double
10903             *terms;
10904
10905           size_t
10906             number_terms;
10907
10908           if (attribute_flag[0] == 0)
10909             break;
10910           if (attribute_flag[1] != 0)
10911             channel=(ChannelType) argument_list[1].integer_reference;
10912           av=(AV *) argument_list[0].array_reference;
10913           number_terms=(size_t) av_len(av);
10914           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
10915           if (terms == (double *) NULL)
10916             {
10917               ThrowPerlException(exception,ResourceLimitFatalError,
10918                 "MemoryAllocationFailed",PackageName);
10919               goto PerlException;
10920             }
10921           for (j=0; j < av_len(av); j++)
10922             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
10923           image=PolynomialImage(image,number_terms >> 1,terms,exception);
10924           terms=(double *) RelinquishMagickMemory(terms);
10925           break;
10926         }
10927       }
10928       if (next != (Image *) NULL)
10929         (void) CatchImageException(next);
10930       if (region_image != (Image *) NULL)
10931         {
10932           /*
10933             Composite region.
10934           */ 
10935           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
10936             region_info.x,region_info.y,exception);
10937           (void) status;
10938           (void) CatchImageException(region_image);
10939           image=DestroyImage(image);
10940           image=region_image;
10941         }
10942       if (image != (Image *) NULL)
10943         {
10944           number_images++;
10945           if (next && (next != image))
10946             {
10947               image->next=next->next;
10948               if (image->next != (Image *) NULL)
10949                 image->next->previous=image;
10950               DeleteImageFromRegistry(*pv,next);
10951             }
10952           sv_setiv(*pv,PTR2IV(image));
10953           next=image;
10954         }
10955       if (*pv)
10956         pv++;
10957     }
10958
10959   PerlException:
10960     if (reference_vector)
10961       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10962     InheritPerlException(exception,perl_exception);
10963     exception=DestroyExceptionInfo(exception);
10964     sv_setiv(perl_exception,(IV) number_images);
10965     SvPOK_on(perl_exception);
10966     ST(0)=sv_2mortal(perl_exception);
10967     XSRETURN(1);
10968   }
10969 \f
10970 #
10971 ###############################################################################
10972 #                                                                             #
10973 #                                                                             #
10974 #                                                                             #
10975 #   M o n t a g e                                                             #
10976 #                                                                             #
10977 #                                                                             #
10978 #                                                                             #
10979 ###############################################################################
10980 #
10981 #
10982 void
10983 Montage(ref,...)
10984   Image::Magick ref=NO_INIT
10985   ALIAS:
10986     MontageImage  = 1
10987     montage       = 2
10988     montageimage  = 3
10989   PPCODE:
10990   {
10991     AV
10992       *av;
10993
10994     char
10995       *attribute;
10996
10997     ExceptionInfo
10998       *exception;
10999
11000     HV
11001       *hv;
11002
11003     Image
11004       *image,
11005       *next;
11006
11007     PixelInfo
11008       transparent_color;
11009
11010     MontageInfo
11011       *montage_info;
11012
11013     register ssize_t
11014       i;
11015
11016     ssize_t
11017       sp;
11018
11019     struct PackageInfo
11020       *info;
11021
11022     SV
11023       *av_reference,
11024       *perl_exception,
11025       *reference,
11026       *rv,
11027       *sv;
11028
11029     PERL_UNUSED_VAR(ref);
11030     PERL_UNUSED_VAR(ix);
11031     exception=AcquireExceptionInfo();
11032     perl_exception=newSVpv("",0);
11033     sv=NULL;
11034     attribute=NULL;
11035     if (sv_isobject(ST(0)) == 0)
11036       {
11037         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11038           PackageName);
11039         goto PerlException;
11040       }
11041     reference=SvRV(ST(0));
11042     hv=SvSTASH(reference);
11043     av=newAV();
11044     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11045     SvREFCNT_dec(av);
11046     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11047     if (image == (Image *) NULL)
11048       {
11049         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11050           PackageName);
11051         goto PerlException;
11052       }
11053     /*
11054       Get options.
11055     */
11056     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11057     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11058     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11059       exception);
11060     for (i=2; i < items; i+=2)
11061     {
11062       attribute=(char *) SvPV(ST(i-1),na);
11063       switch (*attribute)
11064       {
11065         case 'B':
11066         case 'b':
11067         {
11068           if (LocaleCompare(attribute,"background") == 0)
11069             {
11070               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11071                 &montage_info->background_color,exception);
11072               for (next=image; next; next=next->next)
11073                 next->background_color=montage_info->background_color;
11074               break;
11075             }
11076           if (LocaleCompare(attribute,"border") == 0)
11077             {
11078               montage_info->border_width=SvIV(ST(i));
11079               break;
11080             }
11081           if (LocaleCompare(attribute,"bordercolor") == 0)
11082             {
11083               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11084                 &montage_info->border_color,exception);
11085               for (next=image; next; next=next->next)
11086                 next->border_color=montage_info->border_color;
11087               break;
11088             }
11089           if (LocaleCompare(attribute,"borderwidth") == 0)
11090             {
11091               montage_info->border_width=SvIV(ST(i));
11092               break;
11093             }
11094           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11095             attribute);
11096           break;
11097         }
11098         case 'C':
11099         case 'c':
11100         {
11101           if (LocaleCompare(attribute,"compose") == 0)
11102             {
11103               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11104                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11105               if (sp < 0)
11106                 {
11107                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11108                     SvPV(ST(i),na));
11109                   break;
11110                 }
11111               for (next=image; next; next=next->next)
11112                 next->compose=(CompositeOperator) sp;
11113               break;
11114             }
11115           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11116             attribute);
11117           break;
11118         }
11119         case 'F':
11120         case 'f':
11121         {
11122           if (LocaleCompare(attribute,"fill") == 0)
11123             {
11124               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11125                 &montage_info->fill,exception);
11126               break;
11127             }
11128           if (LocaleCompare(attribute,"font") == 0)
11129             {
11130               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11131               break;
11132             }
11133           if (LocaleCompare(attribute,"frame") == 0)
11134             {
11135               char
11136                 *p;
11137
11138               p=SvPV(ST(i),na);
11139               if (IsGeometry(p) == MagickFalse)
11140                 {
11141                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11142                     p);
11143                   break;
11144                 }
11145               (void) CloneString(&montage_info->frame,p);
11146               if (*p == '\0')
11147                 montage_info->frame=(char *) NULL;
11148               break;
11149             }
11150           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11151             attribute);
11152           break;
11153         }
11154         case 'G':
11155         case 'g':
11156         {
11157           if (LocaleCompare(attribute,"geometry") == 0)
11158             {
11159               char
11160                 *p;
11161
11162               p=SvPV(ST(i),na);
11163               if (IsGeometry(p) == MagickFalse)
11164                 {
11165                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11166                     p);
11167                   break;
11168                 }
11169              (void) CloneString(&montage_info->geometry,p);
11170              if (*p == '\0')
11171                montage_info->geometry=(char *) NULL;
11172              break;
11173            }
11174          if (LocaleCompare(attribute,"gravity") == 0)
11175            {
11176              ssize_t
11177                in;
11178
11179              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11180                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11181              if (in < 0)
11182                {
11183                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11184                    SvPV(ST(i),na));
11185                  return;
11186                }
11187              montage_info->gravity=(GravityType) in;
11188              for (next=image; next; next=next->next)
11189                next->gravity=(GravityType) in;
11190              break;
11191            }
11192           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11193             attribute);
11194           break;
11195         }
11196         case 'L':
11197         case 'l':
11198         {
11199           if (LocaleCompare(attribute,"label") == 0)
11200             {
11201               for (next=image; next; next=next->next)
11202                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11203                   info ? info->image_info : (ImageInfo *) NULL,next,
11204                   SvPV(ST(i),na),exception),exception);
11205               break;
11206             }
11207           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11208             attribute);
11209           break;
11210         }
11211         case 'M':
11212         case 'm':
11213         {
11214           if (LocaleCompare(attribute,"mattecolor") == 0)
11215             {
11216               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11217                 &montage_info->matte_color,exception);
11218               for (next=image; next; next=next->next)
11219                 next->matte_color=montage_info->matte_color;
11220               break;
11221             }
11222           if (LocaleCompare(attribute,"mode") == 0)
11223             {
11224               ssize_t
11225                 in;
11226
11227               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11228                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11229               switch (in)
11230               {
11231                 default:
11232                 {
11233                   ThrowPerlException(exception,OptionError,
11234                     "UnrecognizedModeType",SvPV(ST(i),na));
11235                   break;
11236                 }
11237                 case FrameMode:
11238                 {
11239                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11240                   montage_info->shadow=MagickTrue;
11241                   break;
11242                 }
11243                 case UnframeMode:
11244                 {
11245                   montage_info->frame=(char *) NULL;
11246                   montage_info->shadow=MagickFalse;
11247                   montage_info->border_width=0;
11248                   break;
11249                 }
11250                 case ConcatenateMode:
11251                 {
11252                   montage_info->frame=(char *) NULL;
11253                   montage_info->shadow=MagickFalse;
11254                   (void) CloneString(&montage_info->geometry,"+0+0");
11255                   montage_info->border_width=0;
11256                 }
11257               }
11258               break;
11259             }
11260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11261             attribute);
11262           break;
11263         }
11264         case 'P':
11265         case 'p':
11266         {
11267           if (LocaleCompare(attribute,"pointsize") == 0)
11268             {
11269               montage_info->pointsize=SvIV(ST(i));
11270               break;
11271             }
11272           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11273             attribute);
11274           break;
11275         }
11276         case 'S':
11277         case 's':
11278         {
11279           if (LocaleCompare(attribute,"shadow") == 0)
11280             {
11281               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11282                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11283               if (sp < 0)
11284                 {
11285                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11286                     SvPV(ST(i),na));
11287                   break;
11288                 }
11289              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11290              break;
11291             }
11292           if (LocaleCompare(attribute,"stroke") == 0)
11293             {
11294               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11295                 &montage_info->stroke,exception);
11296               break;
11297             }
11298           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11299             attribute);
11300           break;
11301         }
11302         case 'T':
11303         case 't':
11304         {
11305           if (LocaleCompare(attribute,"texture") == 0)
11306             {
11307               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11308               break;
11309             }
11310           if (LocaleCompare(attribute,"tile") == 0)
11311             {
11312               char *p=SvPV(ST(i),na);
11313               if (IsGeometry(p) == MagickFalse)
11314                 {
11315                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11316                     p);
11317                   break;
11318                 }
11319               (void) CloneString(&montage_info->tile,p);
11320               if (*p == '\0')
11321                 montage_info->tile=(char *) NULL;
11322               break;
11323             }
11324           if (LocaleCompare(attribute,"title") == 0)
11325             {
11326               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11327               break;
11328             }
11329           if (LocaleCompare(attribute,"transparent") == 0)
11330             {
11331               PixelInfo
11332                 transparent_color;
11333
11334               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11335                 &transparent_color,exception);
11336               for (next=image; next; next=next->next)
11337                 (void) TransparentPaintImage(next,&transparent_color,
11338                   TransparentAlpha,MagickFalse,exception);
11339               break;
11340             }
11341           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11342             attribute);
11343           break;
11344         }
11345         default:
11346         {
11347           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11348             attribute);
11349           break;
11350         }
11351       }
11352     }
11353     image=MontageImageList(info->image_info,montage_info,image,exception);
11354     montage_info=DestroyMontageInfo(montage_info);
11355     if (image == (Image *) NULL)
11356       goto PerlException;
11357     if (transparent_color.alpha != TransparentAlpha)
11358       for (next=image; next; next=next->next)
11359         (void) TransparentPaintImage(next,&transparent_color,
11360           TransparentAlpha,MagickFalse,exception);
11361     for (  ; image; image=image->next)
11362     {
11363       AddImageToRegistry(sv,image);
11364       rv=newRV(sv);
11365       av_push(av,sv_bless(rv,hv));
11366       SvREFCNT_dec(sv);
11367     }
11368     exception=DestroyExceptionInfo(exception);
11369     ST(0)=av_reference;
11370     SvREFCNT_dec(perl_exception);
11371     XSRETURN(1);
11372
11373   PerlException:
11374     InheritPerlException(exception,perl_exception);
11375     exception=DestroyExceptionInfo(exception);
11376     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11377     SvPOK_on(perl_exception);
11378     ST(0)=sv_2mortal(perl_exception);
11379     XSRETURN(1);
11380   }
11381 \f
11382 #
11383 ###############################################################################
11384 #                                                                             #
11385 #                                                                             #
11386 #                                                                             #
11387 #   M o r p h                                                                 #
11388 #                                                                             #
11389 #                                                                             #
11390 #                                                                             #
11391 ###############################################################################
11392 #
11393 #
11394 void
11395 Morph(ref,...)
11396   Image::Magick ref=NO_INIT
11397   ALIAS:
11398     MorphImage  = 1
11399     morph       = 2
11400     morphimage  = 3
11401   PPCODE:
11402   {
11403     AV
11404       *av;
11405
11406     char
11407       *attribute;
11408
11409     ExceptionInfo
11410       *exception;
11411
11412     HV
11413       *hv;
11414
11415     Image
11416       *image;
11417
11418     register ssize_t
11419       i;
11420
11421     ssize_t
11422       number_frames;
11423
11424     struct PackageInfo
11425       *info;
11426
11427     SV
11428       *av_reference,
11429       *perl_exception,
11430       *reference,
11431       *rv,
11432       *sv;
11433
11434     PERL_UNUSED_VAR(ref);
11435     PERL_UNUSED_VAR(ix);
11436     exception=AcquireExceptionInfo();
11437     perl_exception=newSVpv("",0);
11438     sv=NULL;
11439     av=NULL;
11440     attribute=NULL;
11441     if (sv_isobject(ST(0)) == 0)
11442       {
11443         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11444           PackageName);
11445         goto PerlException;
11446       }
11447     reference=SvRV(ST(0));
11448     hv=SvSTASH(reference);
11449     av=newAV();
11450     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11451     SvREFCNT_dec(av);
11452     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11453     if (image == (Image *) NULL)
11454       {
11455         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11456           PackageName);
11457         goto PerlException;
11458       }
11459     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11460     /*
11461       Get attribute.
11462     */
11463     number_frames=30;
11464     for (i=2; i < items; i+=2)
11465     {
11466       attribute=(char *) SvPV(ST(i-1),na);
11467       switch (*attribute)
11468       {
11469         case 'F':
11470         case 'f':
11471         {
11472           if (LocaleCompare(attribute,"frames") == 0)
11473             {
11474               number_frames=SvIV(ST(i));
11475               break;
11476             }
11477           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11478             attribute);
11479           break;
11480         }
11481         default:
11482         {
11483           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11484             attribute);
11485           break;
11486         }
11487       }
11488     }
11489     image=MorphImages(image,number_frames,exception);
11490     if (image == (Image *) NULL)
11491       goto PerlException;
11492     for ( ; image; image=image->next)
11493     {
11494       AddImageToRegistry(sv,image);
11495       rv=newRV(sv);
11496       av_push(av,sv_bless(rv,hv));
11497       SvREFCNT_dec(sv);
11498     }
11499     exception=DestroyExceptionInfo(exception);
11500     ST(0)=av_reference;
11501     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11502     XSRETURN(1);
11503
11504   PerlException:
11505     InheritPerlException(exception,perl_exception);
11506     exception=DestroyExceptionInfo(exception);
11507     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11508     SvPOK_on(perl_exception);
11509     ST(0)=sv_2mortal(perl_exception);
11510     XSRETURN(1);
11511   }
11512 \f
11513 #
11514 ###############################################################################
11515 #                                                                             #
11516 #                                                                             #
11517 #                                                                             #
11518 #   M o s a i c                                                               #
11519 #                                                                             #
11520 #                                                                             #
11521 #                                                                             #
11522 ###############################################################################
11523 #
11524 #
11525 void
11526 Mosaic(ref)
11527   Image::Magick ref=NO_INIT
11528   ALIAS:
11529     MosaicImage   = 1
11530     mosaic        = 2
11531     mosaicimage   = 3
11532   PPCODE:
11533   {
11534     AV
11535       *av;
11536
11537     ExceptionInfo
11538       *exception;
11539
11540     HV
11541       *hv;
11542
11543     Image
11544       *image;
11545
11546     struct PackageInfo
11547       *info;
11548
11549     SV
11550       *perl_exception,
11551       *reference,
11552       *rv,
11553       *sv;
11554
11555     PERL_UNUSED_VAR(ref);
11556     PERL_UNUSED_VAR(ix);
11557     exception=AcquireExceptionInfo();
11558     perl_exception=newSVpv("",0);
11559     sv=NULL;
11560     if (sv_isobject(ST(0)) == 0)
11561       {
11562         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11563           PackageName);
11564         goto PerlException;
11565       }
11566     reference=SvRV(ST(0));
11567     hv=SvSTASH(reference);
11568     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11569     if (image == (Image *) NULL)
11570       {
11571         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11572           PackageName);
11573         goto PerlException;
11574       }
11575     image=MergeImageLayers(image,MosaicLayer,exception);
11576     /*
11577       Create blessed Perl array for the returned image.
11578     */
11579     av=newAV();
11580     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11581     SvREFCNT_dec(av);
11582     AddImageToRegistry(sv,image);
11583     rv=newRV(sv);
11584     av_push(av,sv_bless(rv,hv));
11585     SvREFCNT_dec(sv);
11586     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11587     (void) CopyMagickString(info->image_info->filename,image->filename,
11588       MaxTextExtent);
11589     SetImageInfo(info->image_info,0,exception);
11590     exception=DestroyExceptionInfo(exception);
11591     SvREFCNT_dec(perl_exception);
11592     XSRETURN(1);
11593
11594   PerlException:
11595     InheritPerlException(exception,perl_exception);
11596     exception=DestroyExceptionInfo(exception);
11597     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11598     SvPOK_on(perl_exception);  /* return messages in string context */
11599     ST(0)=sv_2mortal(perl_exception);
11600     XSRETURN(1);
11601   }
11602 \f
11603 #
11604 ###############################################################################
11605 #                                                                             #
11606 #                                                                             #
11607 #                                                                             #
11608 #   P i n g                                                                   #
11609 #                                                                             #
11610 #                                                                             #
11611 #                                                                             #
11612 ###############################################################################
11613 #
11614 #
11615 void
11616 Ping(ref,...)
11617   Image::Magick ref=NO_INIT
11618   ALIAS:
11619     PingImage  = 1
11620     ping       = 2
11621     pingimage  = 3
11622   PPCODE:
11623   {
11624     AV
11625       *av;
11626
11627     char
11628       **keep,
11629       **list;
11630
11631     ExceptionInfo
11632       *exception;
11633
11634     Image
11635       *image,
11636       *next;
11637
11638     int
11639       n;
11640
11641     MagickBooleanType
11642       status;
11643
11644     register char
11645       **p;
11646
11647     register ssize_t
11648       i;
11649
11650     ssize_t
11651       ac;
11652
11653     STRLEN
11654       *length;
11655
11656     struct PackageInfo
11657       *info,
11658       *package_info;
11659
11660     SV
11661       *perl_exception,
11662       *reference;
11663
11664     size_t
11665       count;
11666
11667     PERL_UNUSED_VAR(ref);
11668     PERL_UNUSED_VAR(ix);
11669     exception=AcquireExceptionInfo();
11670     perl_exception=newSVpv("",0);
11671     package_info=(struct PackageInfo *) NULL;
11672     ac=(items < 2) ? 1 : items-1;
11673     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11674     keep=list;
11675     length=(STRLEN *) NULL;
11676     if (list == (char **) NULL)
11677       {
11678         ThrowPerlException(exception,ResourceLimitError,
11679           "MemoryAllocationFailed",PackageName);
11680         goto PerlException;
11681       }
11682     keep=list;
11683     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11684     if (length == (STRLEN *) NULL)
11685       {
11686         ThrowPerlException(exception,ResourceLimitError,
11687           "MemoryAllocationFailed",PackageName);
11688         goto PerlException;
11689       }
11690     if (sv_isobject(ST(0)) == 0)
11691       {
11692         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11693           PackageName);
11694         goto PerlException;
11695       }
11696     reference=SvRV(ST(0));
11697     if (SvTYPE(reference) != SVt_PVAV)
11698       {
11699         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11700           PackageName);
11701         goto PerlException;
11702       }
11703     av=(AV *) reference;
11704     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11705       exception);
11706     package_info=ClonePackageInfo(info,exception);
11707     n=1;
11708     if (items <= 1)
11709       *list=(char *) (*package_info->image_info->filename ?
11710         package_info->image_info->filename : "XC:black");
11711     else
11712       for (n=0, i=0; i < ac; i++)
11713       {
11714         list[n]=(char *) SvPV(ST(i+1),length[n]);
11715         if ((items >= 3) && strEQcase(list[n],"blob"))
11716           {
11717             void
11718               *blob;
11719
11720             i++;
11721             blob=(void *) (SvPV(ST(i+1),length[n]));
11722             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11723           }
11724         if ((items >= 3) && strEQcase(list[n],"filename"))
11725           continue;
11726         if ((items >= 3) && strEQcase(list[n],"file"))
11727           {
11728             FILE
11729               *file;
11730
11731             PerlIO
11732               *io_info;
11733
11734             i++;
11735             io_info=IoIFP(sv_2io(ST(i+1)));
11736             if (io_info == (PerlIO *) NULL)
11737               {
11738                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11739                   PackageName);
11740                 continue;
11741               }
11742             file=PerlIO_findFILE(io_info);
11743             if (file == (FILE *) NULL)
11744               {
11745                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11746                   PackageName);
11747                 continue;
11748               }
11749             SetImageInfoFile(package_info->image_info,file);
11750           }
11751         if ((items >= 3) && strEQcase(list[n],"magick"))
11752           continue;
11753         n++;
11754       }
11755     list[n]=(char *) NULL;
11756     keep=list;
11757     status=ExpandFilenames(&n,&list);
11758     if (status == MagickFalse)
11759       {
11760         ThrowPerlException(exception,ResourceLimitError,
11761           "MemoryAllocationFailed",PackageName);
11762         goto PerlException;
11763       }
11764     count=0;
11765     for (i=0; i < n; i++)
11766     {
11767       (void) CopyMagickString(package_info->image_info->filename,list[i],
11768         MaxTextExtent);
11769       image=PingImage(package_info->image_info,exception);
11770       if (image == (Image *) NULL)
11771         break;
11772       if ((package_info->image_info->file != (FILE *) NULL) ||
11773           (package_info->image_info->blob != (void *) NULL))
11774         DisassociateImageStream(image);
11775       count+=GetImageListLength(image);
11776       EXTEND(sp,4*count);
11777       for (next=image; next; next=next->next)
11778       {
11779         PUSHs(sv_2mortal(newSViv(next->columns)));
11780         PUSHs(sv_2mortal(newSViv(next->rows)));
11781         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11782         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11783       }
11784       image=DestroyImageList(image);
11785     }
11786     /*
11787       Free resources.
11788     */
11789     for (i=0; i < n; i++)
11790       if (list[i] != (char *) NULL)
11791         for (p=keep; list[i] != *p++; )
11792           if (*p == NULL)
11793             {
11794               list[i]=(char *) RelinquishMagickMemory(list[i]);
11795               break;
11796             }
11797
11798   PerlException:
11799     if (package_info != (struct PackageInfo *) NULL)
11800       DestroyPackageInfo(package_info);
11801     if (list && (list != keep))
11802       list=(char **) RelinquishMagickMemory(list);
11803     if (keep)
11804       keep=(char **) RelinquishMagickMemory(keep);
11805     if (length)
11806       length=(STRLEN *) RelinquishMagickMemory(length);
11807     InheritPerlException(exception,perl_exception);
11808     exception=DestroyExceptionInfo(exception);
11809     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11810   }
11811 \f
11812 #
11813 ###############################################################################
11814 #                                                                             #
11815 #                                                                             #
11816 #                                                                             #
11817 #   P r e v i e w                                                             #
11818 #                                                                             #
11819 #                                                                             #
11820 #                                                                             #
11821 ###############################################################################
11822 #
11823 #
11824 void
11825 Preview(ref,...)
11826   Image::Magick ref=NO_INIT
11827   ALIAS:
11828     PreviewImage = 1
11829     preview      = 2
11830     previewimage = 3
11831   PPCODE:
11832   {
11833     AV
11834       *av;
11835
11836     ExceptionInfo
11837       *exception;
11838
11839     HV
11840       *hv;
11841
11842     Image
11843       *image,
11844       *preview_image;
11845
11846     PreviewType
11847       preview_type;
11848
11849     struct PackageInfo
11850       *info;
11851
11852     SV
11853       *av_reference,
11854       *perl_exception,
11855       *reference,
11856       *rv,
11857       *sv;
11858
11859     PERL_UNUSED_VAR(ref);
11860     PERL_UNUSED_VAR(ix);
11861     exception=AcquireExceptionInfo();
11862     perl_exception=newSVpv("",0);
11863     sv=NULL;
11864     av=NULL;
11865     if (sv_isobject(ST(0)) == 0)
11866       {
11867         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11868           PackageName);
11869         goto PerlException;
11870       }
11871     reference=SvRV(ST(0));
11872     hv=SvSTASH(reference);
11873     av=newAV();
11874     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11875     SvREFCNT_dec(av);
11876     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11877     if (image == (Image *) NULL)
11878       {
11879         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11880           PackageName);
11881         goto PerlException;
11882       }
11883     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11884     preview_type=GammaPreview;
11885     if (items > 1)
11886       preview_type=(PreviewType)
11887         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11888     for ( ; image; image=image->next)
11889     {
11890       preview_image=PreviewImage(image,preview_type,exception);
11891       if (preview_image == (Image *) NULL)
11892         goto PerlException;
11893       AddImageToRegistry(sv,preview_image);
11894       rv=newRV(sv);
11895       av_push(av,sv_bless(rv,hv));
11896       SvREFCNT_dec(sv);
11897     }
11898     exception=DestroyExceptionInfo(exception);
11899     ST(0)=av_reference;
11900     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11901     XSRETURN(1);
11902
11903   PerlException:
11904     InheritPerlException(exception,perl_exception);
11905     exception=DestroyExceptionInfo(exception);
11906     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11907     SvPOK_on(perl_exception);
11908     ST(0)=sv_2mortal(perl_exception);
11909     XSRETURN(1);
11910   }
11911 \f
11912 #
11913 ###############################################################################
11914 #                                                                             #
11915 #                                                                             #
11916 #                                                                             #
11917 #   Q u e r y C o l o r                                                       #
11918 #                                                                             #
11919 #                                                                             #
11920 #                                                                             #
11921 ###############################################################################
11922 #
11923 #
11924 void
11925 QueryColor(ref,...)
11926   Image::Magick ref=NO_INIT
11927   ALIAS:
11928     querycolor = 1
11929   PPCODE:
11930   {
11931     char
11932       *name;
11933
11934     ExceptionInfo
11935       *exception;
11936
11937     PixelInfo
11938       color;
11939
11940     register ssize_t
11941       i;
11942
11943     SV
11944       *perl_exception;
11945
11946     PERL_UNUSED_VAR(ref);
11947     PERL_UNUSED_VAR(ix);
11948     exception=AcquireExceptionInfo();
11949     perl_exception=newSVpv("",0);
11950     if (items == 1)
11951       {
11952         const ColorInfo
11953           **colorlist;
11954
11955         size_t
11956           colors;
11957
11958         colorlist=GetColorInfoList("*",&colors,exception);
11959         EXTEND(sp,colors);
11960         for (i=0; i < (ssize_t) colors; i++)
11961         {
11962           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11963         }
11964         colorlist=(const ColorInfo **)
11965           RelinquishMagickMemory((ColorInfo **) colorlist);
11966         goto PerlException;
11967       }
11968     EXTEND(sp,5*items);
11969     for (i=1; i < items; i++)
11970     {
11971       name=(char *) SvPV(ST(i),na);
11972       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
11973         {
11974           PUSHs(&sv_undef);
11975           continue;
11976         }
11977       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11978       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11979       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11980       if (color.colorspace == CMYKColorspace)
11981         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11982       if (color.alpha_trait == BlendPixelTrait)
11983         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11984     }
11985
11986   PerlException:
11987     InheritPerlException(exception,perl_exception);
11988     exception=DestroyExceptionInfo(exception);
11989     SvREFCNT_dec(perl_exception);
11990   }
11991 \f
11992 #
11993 ###############################################################################
11994 #                                                                             #
11995 #                                                                             #
11996 #                                                                             #
11997 #   Q u e r y C o l o r N a m e                                               #
11998 #                                                                             #
11999 #                                                                             #
12000 #                                                                             #
12001 ###############################################################################
12002 #
12003 #
12004 void
12005 QueryColorname(ref,...)
12006   Image::Magick ref=NO_INIT
12007   ALIAS:
12008     querycolorname = 1
12009   PPCODE:
12010   {
12011     AV
12012       *av;
12013
12014     char
12015       message[MaxTextExtent];
12016
12017     ExceptionInfo
12018       *exception;
12019
12020     Image
12021       *image;
12022
12023     PixelInfo
12024       target_color;
12025
12026     register ssize_t
12027       i;
12028
12029     struct PackageInfo
12030       *info;
12031
12032     SV
12033       *perl_exception,
12034       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12035
12036     PERL_UNUSED_VAR(ref);
12037     PERL_UNUSED_VAR(ix);
12038     exception=AcquireExceptionInfo();
12039     perl_exception=newSVpv("",0);
12040     reference=SvRV(ST(0));
12041     av=(AV *) reference;
12042     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12043       exception);
12044     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12045     if (image == (Image *) NULL)
12046       {
12047         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12048           PackageName);
12049         goto PerlException;
12050       }
12051     EXTEND(sp,items);
12052     for (i=1; i < items; i++)
12053     {
12054       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12055         exception);
12056       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12057         exception);
12058       PUSHs(sv_2mortal(newSVpv(message,0)));
12059     }
12060
12061   PerlException:
12062     InheritPerlException(exception,perl_exception);
12063     exception=DestroyExceptionInfo(exception);
12064     SvREFCNT_dec(perl_exception);
12065   }
12066 \f
12067 #
12068 ###############################################################################
12069 #                                                                             #
12070 #                                                                             #
12071 #                                                                             #
12072 #   Q u e r y F o n t                                                         #
12073 #                                                                             #
12074 #                                                                             #
12075 #                                                                             #
12076 ###############################################################################
12077 #
12078 #
12079 void
12080 QueryFont(ref,...)
12081   Image::Magick ref=NO_INIT
12082   ALIAS:
12083     queryfont = 1
12084   PPCODE:
12085   {
12086     char
12087       *name,
12088       message[MaxTextExtent];
12089
12090     ExceptionInfo
12091       *exception;
12092
12093     register ssize_t
12094       i;
12095
12096     SV
12097       *perl_exception;
12098
12099     volatile const TypeInfo
12100       *type_info;
12101
12102     PERL_UNUSED_VAR(ref);
12103     PERL_UNUSED_VAR(ix);
12104     exception=AcquireExceptionInfo();
12105     perl_exception=newSVpv("",0);
12106     if (items == 1)
12107       {
12108         const TypeInfo
12109           **typelist;
12110
12111         size_t
12112           types;
12113
12114         typelist=GetTypeInfoList("*",&types,exception);
12115         EXTEND(sp,types);
12116         for (i=0; i < (ssize_t) types; i++)
12117         {
12118           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12119         }
12120         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12121           typelist);
12122         goto PerlException;
12123       }
12124     EXTEND(sp,10*items);
12125     for (i=1; i < items; i++)
12126     {
12127       name=(char *) SvPV(ST(i),na);
12128       type_info=GetTypeInfo(name,exception);
12129       if (type_info == (TypeInfo *) NULL)
12130         {
12131           PUSHs(&sv_undef);
12132           continue;
12133         }
12134       if (type_info->name == (char *) NULL)
12135         PUSHs(&sv_undef);
12136       else
12137         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12138       if (type_info->description == (char *) NULL)
12139         PUSHs(&sv_undef);
12140       else
12141         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12142       if (type_info->family == (char *) NULL)
12143         PUSHs(&sv_undef);
12144       else
12145         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12146       if (type_info->style == UndefinedStyle)
12147         PUSHs(&sv_undef);
12148       else
12149         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12150           type_info->style),0)));
12151       if (type_info->stretch == UndefinedStretch)
12152         PUSHs(&sv_undef);
12153       else
12154         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12155           type_info->stretch),0)));
12156       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12157         type_info->weight);
12158       PUSHs(sv_2mortal(newSVpv(message,0)));
12159       if (type_info->encoding == (char *) NULL)
12160         PUSHs(&sv_undef);
12161       else
12162         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12163       if (type_info->foundry == (char *) NULL)
12164         PUSHs(&sv_undef);
12165       else
12166         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12167       if (type_info->format == (char *) NULL)
12168         PUSHs(&sv_undef);
12169       else
12170         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12171       if (type_info->metrics == (char *) NULL)
12172         PUSHs(&sv_undef);
12173       else
12174         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12175       if (type_info->glyphs == (char *) NULL)
12176         PUSHs(&sv_undef);
12177       else
12178         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12179     }
12180
12181   PerlException:
12182     InheritPerlException(exception,perl_exception);
12183     exception=DestroyExceptionInfo(exception);
12184     SvREFCNT_dec(perl_exception);
12185   }
12186 \f
12187 #
12188 ###############################################################################
12189 #                                                                             #
12190 #                                                                             #
12191 #                                                                             #
12192 #   Q u e r y F o n t M e t r i c s                                           #
12193 #                                                                             #
12194 #                                                                             #
12195 #                                                                             #
12196 ###############################################################################
12197 #
12198 #
12199 void
12200 QueryFontMetrics(ref,...)
12201   Image::Magick ref=NO_INIT
12202   ALIAS:
12203     queryfontmetrics = 1
12204   PPCODE:
12205   {
12206     AffineMatrix
12207       affine,
12208       current;
12209
12210     AV
12211       *av;
12212
12213     char
12214       *attribute;
12215
12216     double
12217       x,
12218       y;
12219
12220     DrawInfo
12221       *draw_info;
12222
12223     ExceptionInfo
12224       *exception;
12225
12226     GeometryInfo
12227       geometry_info;
12228
12229     Image
12230       *image;
12231
12232     MagickBooleanType
12233       status;
12234
12235     MagickStatusType
12236       flags;
12237
12238     register ssize_t
12239       i;
12240
12241     ssize_t
12242       type;
12243
12244     struct PackageInfo
12245       *info,
12246       *package_info;
12247
12248     SV
12249       *perl_exception,
12250       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12251
12252     TypeMetric
12253       metrics;
12254
12255     PERL_UNUSED_VAR(ref);
12256     PERL_UNUSED_VAR(ix);
12257     exception=AcquireExceptionInfo();
12258     package_info=(struct PackageInfo *) NULL;
12259     perl_exception=newSVpv("",0);
12260     reference=SvRV(ST(0));
12261     av=(AV *) reference;
12262     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12263       exception);
12264     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12265     if (image == (Image *) NULL)
12266       {
12267         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12268           PackageName);
12269         goto PerlException;
12270       }
12271     package_info=ClonePackageInfo(info,exception);
12272     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12273     CloneString(&draw_info->text,"");
12274     current=draw_info->affine;
12275     GetAffineMatrix(&affine);
12276     x=0.0;
12277     y=0.0;
12278     EXTEND(sp,7*items);
12279     for (i=2; i < items; i+=2)
12280     {
12281       attribute=(char *) SvPV(ST(i-1),na);
12282       switch (*attribute)
12283       {
12284         case 'A':
12285         case 'a':
12286         {
12287           if (LocaleCompare(attribute,"antialias") == 0)
12288             {
12289               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12290                 SvPV(ST(i),na));
12291               if (type < 0)
12292                 {
12293                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12294                     SvPV(ST(i),na));
12295                   break;
12296                 }
12297               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12298               break;
12299             }
12300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12301             attribute);
12302           break;
12303         }
12304         case 'd':
12305         case 'D':
12306         {
12307           if (LocaleCompare(attribute,"density") == 0)
12308             {
12309               CloneString(&draw_info->density,SvPV(ST(i),na));
12310               break;
12311             }
12312           if (LocaleCompare(attribute,"direction") == 0)
12313             {
12314               draw_info->direction=(DirectionType) ParseCommandOption(
12315                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12316               break;
12317             }
12318           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12319             attribute);
12320           break;
12321         }
12322         case 'e':
12323         case 'E':
12324         {
12325           if (LocaleCompare(attribute,"encoding") == 0)
12326             {
12327               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12328               break;
12329             }
12330           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12331             attribute);
12332           break;
12333         }
12334         case 'f':
12335         case 'F':
12336         {
12337           if (LocaleCompare(attribute,"family") == 0)
12338             {
12339               CloneString(&draw_info->family,SvPV(ST(i),na));
12340               break;
12341             }
12342           if (LocaleCompare(attribute,"fill") == 0)
12343             {
12344               if (info)
12345                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12346                   &draw_info->fill,exception);
12347               break;
12348             }
12349           if (LocaleCompare(attribute,"font") == 0)
12350             {
12351               CloneString(&draw_info->font,SvPV(ST(i),na));
12352               break;
12353             }
12354           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12355             attribute);
12356           break;
12357         }
12358         case 'g':
12359         case 'G':
12360         {
12361           if (LocaleCompare(attribute,"geometry") == 0)
12362             {
12363               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12364               break;
12365             }
12366           if (LocaleCompare(attribute,"gravity") == 0)
12367             {
12368               draw_info->gravity=(GravityType) ParseCommandOption(
12369                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12370               break;
12371             }
12372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12373             attribute);
12374           break;
12375         }
12376         case 'i':
12377         case 'I':
12378         {
12379           if (LocaleCompare(attribute,"interline-spacing") == 0)
12380             {
12381               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12382               draw_info->interline_spacing=geometry_info.rho;
12383               break;
12384             }
12385           if (LocaleCompare(attribute,"interword-spacing") == 0)
12386             {
12387               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12388               draw_info->interword_spacing=geometry_info.rho;
12389               break;
12390             }
12391           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12392             attribute);
12393           break;
12394         }
12395         case 'k':
12396         case 'K':
12397         {
12398           if (LocaleCompare(attribute,"kerning") == 0)
12399             {
12400               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12401               draw_info->kerning=geometry_info.rho;
12402               break;
12403             }
12404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12405             attribute);
12406           break;
12407         }
12408         case 'p':
12409         case 'P':
12410         {
12411           if (LocaleCompare(attribute,"pointsize") == 0)
12412             {
12413               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12414               draw_info->pointsize=geometry_info.rho;
12415               break;
12416             }
12417           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12418             attribute);
12419           break;
12420         }
12421         case 'r':
12422         case 'R':
12423         {
12424           if (LocaleCompare(attribute,"rotate") == 0)
12425             {
12426               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12427               affine.rx=geometry_info.rho;
12428               affine.ry=geometry_info.sigma;
12429               if ((flags & SigmaValue) == 0)
12430                 affine.ry=affine.rx;
12431               break;
12432             }
12433           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12434             attribute);
12435           break;
12436         }
12437         case 's':
12438         case 'S':
12439         {
12440           if (LocaleCompare(attribute,"scale") == 0)
12441             {
12442               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12443               affine.sx=geometry_info.rho;
12444               affine.sy=geometry_info.sigma;
12445               if ((flags & SigmaValue) == 0)
12446                 affine.sy=affine.sx;
12447               break;
12448             }
12449           if (LocaleCompare(attribute,"skew") == 0)
12450             {
12451               double
12452                 x_angle,
12453                 y_angle;
12454
12455               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12456               x_angle=geometry_info.rho;
12457               y_angle=geometry_info.sigma;
12458               if ((flags & SigmaValue) == 0)
12459                 y_angle=x_angle;
12460               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12461               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12462               break;
12463             }
12464           if (LocaleCompare(attribute,"stroke") == 0)
12465             {
12466               if (info)
12467                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12468                   &draw_info->stroke,exception);
12469               break;
12470             }
12471           if (LocaleCompare(attribute,"style") == 0)
12472             {
12473               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12474                 SvPV(ST(i),na));
12475               if (type < 0)
12476                 {
12477                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12478                     SvPV(ST(i),na));
12479                   break;
12480                 }
12481               draw_info->style=(StyleType) type;
12482               break;
12483             }
12484           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12485             attribute);
12486           break;
12487         }
12488         case 't':
12489         case 'T':
12490         {
12491           if (LocaleCompare(attribute,"text") == 0)
12492             {
12493               CloneString(&draw_info->text,SvPV(ST(i),na));
12494               break;
12495             }
12496           if (LocaleCompare(attribute,"translate") == 0)
12497             {
12498               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12499               affine.tx=geometry_info.rho;
12500               affine.ty=geometry_info.sigma;
12501               if ((flags & SigmaValue) == 0)
12502                 affine.ty=affine.tx;
12503               break;
12504             }
12505           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12506             attribute);
12507           break;
12508         }
12509         case 'w':
12510         case 'W':
12511         {
12512           if (LocaleCompare(attribute,"weight") == 0)
12513             {
12514               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12515               draw_info->weight=(size_t) geometry_info.rho;
12516               break;
12517             }
12518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12519             attribute);
12520           break;
12521         }
12522         case 'x':
12523         case 'X':
12524         {
12525           if (LocaleCompare(attribute,"x") == 0)
12526             {
12527               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12528               x=geometry_info.rho;
12529               break;
12530             }
12531           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12532             attribute);
12533           break;
12534         }
12535         case 'y':
12536         case 'Y':
12537         {
12538           if (LocaleCompare(attribute,"y") == 0)
12539             {
12540               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12541               y=geometry_info.rho;
12542               break;
12543             }
12544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12545             attribute);
12546           break;
12547         }
12548         default:
12549         {
12550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12551             attribute);
12552           break;
12553         }
12554       }
12555     }
12556     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12557     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12558     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12559     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12560     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12561     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12562     if (draw_info->geometry == (char *) NULL)
12563       {
12564         draw_info->geometry=AcquireString((char *) NULL);
12565         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12566           "%.15g,%.15g",x,y);
12567       }
12568     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12569     (void) CatchImageException(image);
12570     if (status == MagickFalse)
12571       PUSHs(&sv_undef);
12572     else
12573       {
12574         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12575         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12576         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12577         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12578         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12579         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12580         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12581         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12582         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12583         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12584         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12585         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12586         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12587       }
12588     draw_info=DestroyDrawInfo(draw_info);
12589
12590   PerlException:
12591     if (package_info != (struct PackageInfo *) NULL)
12592       DestroyPackageInfo(package_info);
12593     InheritPerlException(exception,perl_exception);
12594     exception=DestroyExceptionInfo(exception);
12595     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12596   }
12597 \f
12598 #
12599 ###############################################################################
12600 #                                                                             #
12601 #                                                                             #
12602 #                                                                             #
12603 #   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                         #
12604 #                                                                             #
12605 #                                                                             #
12606 #                                                                             #
12607 ###############################################################################
12608 #
12609 #
12610 void
12611 QueryMultilineFontMetrics(ref,...)
12612   Image::Magick ref=NO_INIT
12613   ALIAS:
12614     querymultilinefontmetrics = 1
12615   PPCODE:
12616   {
12617     AffineMatrix
12618       affine,
12619       current;
12620
12621     AV
12622       *av;
12623
12624     char
12625       *attribute;
12626
12627     double
12628       x,
12629       y;
12630
12631     DrawInfo
12632       *draw_info;
12633
12634     ExceptionInfo
12635       *exception;
12636
12637     GeometryInfo
12638       geometry_info;
12639
12640     Image
12641       *image;
12642
12643     MagickBooleanType
12644       status;
12645
12646     MagickStatusType
12647       flags;
12648
12649     register ssize_t
12650       i;
12651
12652     ssize_t
12653       type;
12654
12655     struct PackageInfo
12656       *info,
12657       *package_info;
12658
12659     SV
12660       *perl_exception,
12661       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12662
12663     TypeMetric
12664       metrics;
12665
12666     PERL_UNUSED_VAR(ref);
12667     PERL_UNUSED_VAR(ix);
12668     exception=AcquireExceptionInfo();
12669     package_info=(struct PackageInfo *) NULL;
12670     perl_exception=newSVpv("",0);
12671     reference=SvRV(ST(0));
12672     av=(AV *) reference;
12673     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12674       exception);
12675     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12676     if (image == (Image *) NULL)
12677       {
12678         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12679           PackageName);
12680         goto PerlException;
12681       }
12682     package_info=ClonePackageInfo(info,exception);
12683     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12684     CloneString(&draw_info->text,"");
12685     current=draw_info->affine;
12686     GetAffineMatrix(&affine);
12687     x=0.0;
12688     y=0.0;
12689     EXTEND(sp,7*items);
12690     for (i=2; i < items; i+=2)
12691     {
12692       attribute=(char *) SvPV(ST(i-1),na);
12693       switch (*attribute)
12694       {
12695         case 'A':
12696         case 'a':
12697         {
12698           if (LocaleCompare(attribute,"antialias") == 0)
12699             {
12700               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12701                 SvPV(ST(i),na));
12702               if (type < 0)
12703                 {
12704                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12705                     SvPV(ST(i),na));
12706                   break;
12707                 }
12708               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12709               break;
12710             }
12711           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12712             attribute);
12713           break;
12714         }
12715         case 'd':
12716         case 'D':
12717         {
12718           if (LocaleCompare(attribute,"density") == 0)
12719             {
12720               CloneString(&draw_info->density,SvPV(ST(i),na));
12721               break;
12722             }
12723           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12724             attribute);
12725           break;
12726         }
12727         case 'e':
12728         case 'E':
12729         {
12730           if (LocaleCompare(attribute,"encoding") == 0)
12731             {
12732               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12733               break;
12734             }
12735           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12736             attribute);
12737           break;
12738         }
12739         case 'f':
12740         case 'F':
12741         {
12742           if (LocaleCompare(attribute,"family") == 0)
12743             {
12744               CloneString(&draw_info->family,SvPV(ST(i),na));
12745               break;
12746             }
12747           if (LocaleCompare(attribute,"fill") == 0)
12748             {
12749               if (info)
12750                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12751                   &draw_info->fill,exception);
12752               break;
12753             }
12754           if (LocaleCompare(attribute,"font") == 0)
12755             {
12756               CloneString(&draw_info->font,SvPV(ST(i),na));
12757               break;
12758             }
12759           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12760             attribute);
12761           break;
12762         }
12763         case 'g':
12764         case 'G':
12765         {
12766           if (LocaleCompare(attribute,"geometry") == 0)
12767             {
12768               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12769               break;
12770             }
12771           if (LocaleCompare(attribute,"gravity") == 0)
12772             {
12773               draw_info->gravity=(GravityType) ParseCommandOption(
12774                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12775               break;
12776             }
12777           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12778             attribute);
12779           break;
12780         }
12781         case 'p':
12782         case 'P':
12783         {
12784           if (LocaleCompare(attribute,"pointsize") == 0)
12785             {
12786               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12787               draw_info->pointsize=geometry_info.rho;
12788               break;
12789             }
12790           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12791             attribute);
12792           break;
12793         }
12794         case 'r':
12795         case 'R':
12796         {
12797           if (LocaleCompare(attribute,"rotate") == 0)
12798             {
12799               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12800               affine.rx=geometry_info.rho;
12801               affine.ry=geometry_info.sigma;
12802               if ((flags & SigmaValue) == 0)
12803                 affine.ry=affine.rx;
12804               break;
12805             }
12806           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12807             attribute);
12808           break;
12809         }
12810         case 's':
12811         case 'S':
12812         {
12813           if (LocaleCompare(attribute,"scale") == 0)
12814             {
12815               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12816               affine.sx=geometry_info.rho;
12817               affine.sy=geometry_info.sigma;
12818               if ((flags & SigmaValue) == 0)
12819                 affine.sy=affine.sx;
12820               break;
12821             }
12822           if (LocaleCompare(attribute,"skew") == 0)
12823             {
12824               double
12825                 x_angle,
12826                 y_angle;
12827
12828               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12829               x_angle=geometry_info.rho;
12830               y_angle=geometry_info.sigma;
12831               if ((flags & SigmaValue) == 0)
12832                 y_angle=x_angle;
12833               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12834               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12835               break;
12836             }
12837           if (LocaleCompare(attribute,"stroke") == 0)
12838             {
12839               if (info)
12840                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12841                   &draw_info->stroke,exception);
12842               break;
12843             }
12844           if (LocaleCompare(attribute,"style") == 0)
12845             {
12846               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12847                 SvPV(ST(i),na));
12848               if (type < 0)
12849                 {
12850                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12851                     SvPV(ST(i),na));
12852                   break;
12853                 }
12854               draw_info->style=(StyleType) type;
12855               break;
12856             }
12857           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12858             attribute);
12859           break;
12860         }
12861         case 't':
12862         case 'T':
12863         {
12864           if (LocaleCompare(attribute,"text") == 0)
12865             {
12866               CloneString(&draw_info->text,SvPV(ST(i),na));
12867               break;
12868             }
12869           if (LocaleCompare(attribute,"translate") == 0)
12870             {
12871               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12872               affine.tx=geometry_info.rho;
12873               affine.ty=geometry_info.sigma;
12874               if ((flags & SigmaValue) == 0)
12875                 affine.ty=affine.tx;
12876               break;
12877             }
12878           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12879             attribute);
12880           break;
12881         }
12882         case 'w':
12883         case 'W':
12884         {
12885           if (LocaleCompare(attribute,"weight") == 0)
12886             {
12887               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12888               draw_info->weight=(size_t) geometry_info.rho;
12889               break;
12890             }
12891           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12892             attribute);
12893           break;
12894         }
12895         case 'x':
12896         case 'X':
12897         {
12898           if (LocaleCompare(attribute,"x") == 0)
12899             {
12900               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12901               x=geometry_info.rho;
12902               break;
12903             }
12904           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12905             attribute);
12906           break;
12907         }
12908         case 'y':
12909         case 'Y':
12910         {
12911           if (LocaleCompare(attribute,"y") == 0)
12912             {
12913               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12914               y=geometry_info.rho;
12915               break;
12916             }
12917           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12918             attribute);
12919           break;
12920         }
12921         default:
12922         {
12923           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12924             attribute);
12925           break;
12926         }
12927       }
12928     }
12929     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12930     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12931     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12932     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12933     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12934     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12935     if (draw_info->geometry == (char *) NULL)
12936       {
12937         draw_info->geometry=AcquireString((char *) NULL);
12938         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12939           "%.15g,%.15g",x,y);
12940       }
12941     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
12942     (void) CatchException(exception);
12943     if (status == MagickFalse)
12944       PUSHs(&sv_undef);
12945     else
12946       {
12947         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12948         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12949         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12950         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12951         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12952         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12953         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12954         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12955         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12956         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12957         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12958         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12959         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12960       }
12961     draw_info=DestroyDrawInfo(draw_info);
12962
12963   PerlException:
12964     if (package_info != (struct PackageInfo *) NULL)
12965       DestroyPackageInfo(package_info);
12966     InheritPerlException(exception,perl_exception);
12967     exception=DestroyExceptionInfo(exception);
12968     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12969   }
12970 \f
12971 #
12972 ###############################################################################
12973 #                                                                             #
12974 #                                                                             #
12975 #                                                                             #
12976 #   Q u e r y F o r m a t                                                     #
12977 #                                                                             #
12978 #                                                                             #
12979 #                                                                             #
12980 ###############################################################################
12981 #
12982 #
12983 void
12984 QueryFormat(ref,...)
12985   Image::Magick ref=NO_INIT
12986   ALIAS:
12987     queryformat = 1
12988   PPCODE:
12989   {
12990     char
12991       *name;
12992
12993     ExceptionInfo
12994       *exception;
12995
12996     register ssize_t
12997       i;
12998
12999     SV
13000       *perl_exception;
13001
13002     volatile const MagickInfo
13003       *magick_info;
13004
13005     PERL_UNUSED_VAR(ref);
13006     PERL_UNUSED_VAR(ix);
13007     exception=AcquireExceptionInfo();
13008     perl_exception=newSVpv("",0);
13009     if (items == 1)
13010       {
13011         char
13012           format[MaxTextExtent];
13013
13014         const MagickInfo
13015           **format_list;
13016
13017         size_t
13018           types;
13019
13020         format_list=GetMagickInfoList("*",&types,exception);
13021         EXTEND(sp,types);
13022         for (i=0; i < (ssize_t) types; i++)
13023         {
13024           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13025           LocaleLower(format);
13026           PUSHs(sv_2mortal(newSVpv(format,0)));
13027         }
13028         format_list=(const MagickInfo **)
13029           RelinquishMagickMemory((MagickInfo *) format_list);
13030         goto PerlException;
13031       }
13032     EXTEND(sp,8*items);
13033     for (i=1; i < items; i++)
13034     {
13035       name=(char *) SvPV(ST(i),na);
13036       magick_info=GetMagickInfo(name,exception);
13037       if (magick_info == (const MagickInfo *) NULL)
13038         {
13039           PUSHs(&sv_undef);
13040           continue;
13041         }
13042       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13043       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13044       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13045       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13046       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13047       if (magick_info->description == (char *) NULL)
13048         PUSHs(&sv_undef);
13049       else
13050         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13051       if (magick_info->module == (char *) NULL)
13052         PUSHs(&sv_undef);
13053       else
13054         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13055     }
13056
13057   PerlException:
13058     InheritPerlException(exception,perl_exception);
13059     exception=DestroyExceptionInfo(exception);
13060     SvREFCNT_dec(perl_exception);
13061   }
13062 \f
13063 #
13064 ###############################################################################
13065 #                                                                             #
13066 #                                                                             #
13067 #                                                                             #
13068 #   Q u e r y O p t i o n                                                     #
13069 #                                                                             #
13070 #                                                                             #
13071 #                                                                             #
13072 ###############################################################################
13073 #
13074 #
13075 void
13076 QueryOption(ref,...)
13077   Image::Magick ref=NO_INIT
13078   ALIAS:
13079     queryoption = 1
13080   PPCODE:
13081   {
13082     char
13083       **options;
13084
13085     ExceptionInfo
13086       *exception;
13087
13088     register ssize_t
13089       i;
13090
13091     ssize_t
13092       j,
13093       option;
13094
13095     SV
13096       *perl_exception;
13097
13098     PERL_UNUSED_VAR(ref);
13099     PERL_UNUSED_VAR(ix);
13100     exception=AcquireExceptionInfo();
13101     perl_exception=newSVpv("",0);
13102     EXTEND(sp,8*items);
13103     for (i=1; i < items; i++)
13104     {
13105       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13106         SvPV(ST(i),na));
13107       options=GetCommandOptions((CommandOption) option);
13108       if (options == (char **) NULL)
13109         PUSHs(&sv_undef);
13110       else
13111         {
13112           for (j=0; options[j] != (char *) NULL; j++)
13113             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13114           options=DestroyStringList(options);
13115         }
13116     }
13117
13118     InheritPerlException(exception,perl_exception);
13119     exception=DestroyExceptionInfo(exception);
13120     SvREFCNT_dec(perl_exception);
13121   }
13122 \f
13123 #
13124 ###############################################################################
13125 #                                                                             #
13126 #                                                                             #
13127 #                                                                             #
13128 #   R e a d                                                                   #
13129 #                                                                             #
13130 #                                                                             #
13131 #                                                                             #
13132 ###############################################################################
13133 #
13134 #
13135 void
13136 Read(ref,...)
13137   Image::Magick ref=NO_INIT
13138   ALIAS:
13139     ReadImage  = 1
13140     read       = 2
13141     readimage  = 3
13142   PPCODE:
13143   {
13144     AV
13145       *av;
13146
13147     char
13148       **keep,
13149       **list;
13150
13151     ExceptionInfo
13152       *exception;
13153
13154     HV
13155       *hv;
13156
13157     Image
13158       *image;
13159
13160     int
13161       n;
13162
13163     MagickBooleanType
13164       status;
13165
13166     register char
13167       **p;
13168
13169     register ssize_t
13170       i;
13171
13172     ssize_t
13173       ac,
13174       number_images;
13175
13176     STRLEN
13177       *length;
13178
13179     struct PackageInfo
13180       *info,
13181       *package_info;
13182
13183     SV
13184       *perl_exception,  /* Perl variable for storing messages */
13185       *reference,
13186       *rv,
13187       *sv;
13188
13189     PERL_UNUSED_VAR(ref);
13190     PERL_UNUSED_VAR(ix);
13191     exception=AcquireExceptionInfo();
13192     perl_exception=newSVpv("",0);
13193     sv=NULL;
13194     package_info=(struct PackageInfo *) NULL;
13195     number_images=0;
13196     ac=(items < 2) ? 1 : items-1;
13197     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13198     keep=list;
13199     length=(STRLEN *) NULL;
13200     if (list == (char **) NULL)
13201       {
13202         ThrowPerlException(exception,ResourceLimitError,
13203           "MemoryAllocationFailed",PackageName);
13204         goto PerlException;
13205       }
13206     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13207     if (length == (STRLEN *) NULL)
13208       {
13209         ThrowPerlException(exception,ResourceLimitError,
13210           "MemoryAllocationFailed",PackageName);
13211         goto PerlException;
13212       }
13213     if (sv_isobject(ST(0)) == 0)
13214       {
13215         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13216           PackageName);
13217         goto PerlException;
13218       }
13219     reference=SvRV(ST(0));
13220     hv=SvSTASH(reference);
13221     if (SvTYPE(reference) != SVt_PVAV)
13222       {
13223         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13224           PackageName);
13225         goto PerlException;
13226       }
13227     av=(AV *) reference;
13228     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13229       exception);
13230     package_info=ClonePackageInfo(info,exception);
13231     n=1;
13232     if (items <= 1)
13233       *list=(char *) (*package_info->image_info->filename ?
13234         package_info->image_info->filename : "XC:black");
13235     else
13236       for (n=0, i=0; i < ac; i++)
13237       {
13238         list[n]=(char *) SvPV(ST(i+1),length[n]);
13239         if ((items >= 3) && strEQcase(list[n],"blob"))
13240           {
13241             void
13242               *blob;
13243
13244             i++;
13245             blob=(void *) (SvPV(ST(i+1),length[n]));
13246             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13247           }
13248         if ((items >= 3) && strEQcase(list[n],"filename"))
13249           continue;
13250         if ((items >= 3) && strEQcase(list[n],"file"))
13251           {
13252             FILE
13253               *file;
13254
13255             PerlIO
13256               *io_info;
13257
13258             i++;
13259             io_info=IoIFP(sv_2io(ST(i+1)));
13260             if (io_info == (PerlIO *) NULL)
13261               {
13262                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13263                   PackageName);
13264                 continue;
13265               }
13266             file=PerlIO_findFILE(io_info);
13267             if (file == (FILE *) NULL)
13268               {
13269                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13270                   PackageName);
13271                 continue;
13272               }
13273             SetImageInfoFile(package_info->image_info,file);
13274           }
13275         if ((items >= 3) && strEQcase(list[n],"magick"))
13276           continue;
13277         n++;
13278       }
13279     list[n]=(char *) NULL;
13280     keep=list;
13281     status=ExpandFilenames(&n,&list);
13282     if (status == MagickFalse)
13283       {
13284         ThrowPerlException(exception,ResourceLimitError,
13285           "MemoryAllocationFailed",PackageName);
13286         goto PerlException;
13287       }
13288     number_images=0;
13289     for (i=0; i < n; i++)
13290     {
13291       if ((package_info->image_info->file == (FILE *) NULL) &&
13292           (package_info->image_info->blob == (void *) NULL))
13293         image=ReadImages(package_info->image_info,list[i],exception);
13294       else
13295         {
13296           image=ReadImages(package_info->image_info,
13297             package_info->image_info->filename,exception);
13298           if (image != (Image *) NULL)
13299             DisassociateImageStream(image);
13300         }
13301       if (image == (Image *) NULL)
13302         break;
13303       for ( ; image; image=image->next)
13304       {
13305         AddImageToRegistry(sv,image);
13306         rv=newRV(sv);
13307         av_push(av,sv_bless(rv,hv));
13308         SvREFCNT_dec(sv);
13309         number_images++;
13310       }
13311     }
13312     /*
13313       Free resources.
13314     */
13315     for (i=0; i < n; i++)
13316       if (list[i] != (char *) NULL)
13317         for (p=keep; list[i] != *p++; )
13318           if (*p == (char *) NULL)
13319             {
13320               list[i]=(char *) RelinquishMagickMemory(list[i]);
13321               break;
13322             }
13323
13324   PerlException:
13325     if (package_info != (struct PackageInfo *) NULL)
13326       DestroyPackageInfo(package_info);
13327     if (list && (list != keep))
13328       list=(char **) RelinquishMagickMemory(list);
13329     if (keep)
13330       keep=(char **) RelinquishMagickMemory(keep);
13331     if (length)
13332       length=(STRLEN *) RelinquishMagickMemory(length);
13333     InheritPerlException(exception,perl_exception);
13334     exception=DestroyExceptionInfo(exception);
13335     sv_setiv(perl_exception,(IV) number_images);
13336     SvPOK_on(perl_exception);
13337     ST(0)=sv_2mortal(perl_exception);
13338     XSRETURN(1);
13339   }
13340 \f
13341 #
13342 ###############################################################################
13343 #                                                                             #
13344 #                                                                             #
13345 #                                                                             #
13346 #   R e m o t e                                                               #
13347 #                                                                             #
13348 #                                                                             #
13349 #                                                                             #
13350 ###############################################################################
13351 #
13352 #
13353 void
13354 Remote(ref,...)
13355   Image::Magick ref=NO_INIT
13356   ALIAS:
13357     RemoteCommand  = 1
13358     remote         = 2
13359     remoteCommand  = 3
13360   PPCODE:
13361   {
13362     AV
13363       *av;
13364
13365     ExceptionInfo
13366       *exception;
13367
13368     register ssize_t
13369       i;
13370
13371     SV
13372       *perl_exception,
13373       *reference;
13374
13375     struct PackageInfo
13376       *info;
13377
13378     PERL_UNUSED_VAR(ref);
13379     PERL_UNUSED_VAR(ix);
13380     exception=AcquireExceptionInfo();
13381     perl_exception=newSVpv("",0);
13382     reference=SvRV(ST(0));
13383     av=(AV *) reference;
13384     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13385       exception);
13386     for (i=1; i < items; i++)
13387       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13388         SvPV(ST(i),na),exception);
13389     InheritPerlException(exception,perl_exception);
13390     exception=DestroyExceptionInfo(exception);
13391     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13392   }
13393 \f
13394 #
13395 ###############################################################################
13396 #                                                                             #
13397 #                                                                             #
13398 #                                                                             #
13399 #   S e t                                                                     #
13400 #                                                                             #
13401 #                                                                             #
13402 #                                                                             #
13403 ###############################################################################
13404 #
13405 #
13406 void
13407 Set(ref,...)
13408   Image::Magick ref=NO_INIT
13409   ALIAS:
13410     SetAttributes  = 1
13411     SetAttribute   = 2
13412     set            = 3
13413     setattributes  = 4
13414     setattribute   = 5
13415   PPCODE:
13416   {
13417     ExceptionInfo
13418       *exception;
13419
13420     Image
13421       *image;
13422
13423     register ssize_t
13424       i;
13425
13426     struct PackageInfo
13427       *info;
13428
13429     SV
13430       *perl_exception,
13431       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13432
13433     PERL_UNUSED_VAR(ref);
13434     PERL_UNUSED_VAR(ix);
13435     exception=AcquireExceptionInfo();
13436     perl_exception=newSVpv("",0);
13437     if (sv_isobject(ST(0)) == 0)
13438       {
13439         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13440           PackageName);
13441         goto PerlException;
13442       }
13443     reference=SvRV(ST(0));
13444     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13445     if (items == 2)
13446       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13447     else
13448       for (i=2; i < items; i+=2)
13449         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13450
13451   PerlException:
13452     InheritPerlException(exception,perl_exception);
13453     exception=DestroyExceptionInfo(exception);
13454     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13455     SvPOK_on(perl_exception);
13456     ST(0)=sv_2mortal(perl_exception);
13457     XSRETURN(1);
13458   }
13459 \f
13460 #
13461 ###############################################################################
13462 #                                                                             #
13463 #                                                                             #
13464 #                                                                             #
13465 #   S e t P i x e l                                                           #
13466 #                                                                             #
13467 #                                                                             #
13468 #                                                                             #
13469 ###############################################################################
13470 #
13471 #
13472 void
13473 SetPixel(ref,...)
13474   Image::Magick ref=NO_INIT
13475   ALIAS:
13476     setpixel = 1
13477     setPixel = 2
13478   PPCODE:
13479   {
13480     AV
13481       *av;
13482
13483     char
13484       *attribute;
13485
13486     ChannelType
13487       channel,
13488       channel_mask;
13489
13490     ExceptionInfo
13491       *exception;
13492
13493     Image
13494       *image;
13495
13496     MagickBooleanType
13497       normalize;
13498
13499     RectangleInfo
13500       region;
13501
13502     register ssize_t
13503       i;
13504
13505     register Quantum
13506       *q;
13507
13508     ssize_t
13509       option;
13510
13511     struct PackageInfo
13512       *info;
13513
13514     SV
13515       *perl_exception,
13516       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13517
13518     PERL_UNUSED_VAR(ref);
13519     PERL_UNUSED_VAR(ix);
13520     exception=AcquireExceptionInfo();
13521     perl_exception=newSVpv("",0);
13522     reference=SvRV(ST(0));
13523     av=(AV *) reference;
13524     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13525       exception);
13526     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13527     if (image == (Image *) NULL)
13528       {
13529         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13530           PackageName);
13531         goto PerlException;
13532       }
13533     av=(AV *) NULL;
13534     normalize=MagickTrue;
13535     region.x=0;
13536     region.y=0;
13537     region.width=image->columns;
13538     region.height=1;
13539     if (items == 1)
13540       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13541     channel=DefaultChannels;
13542     for (i=2; i < items; i+=2)
13543     {
13544       attribute=(char *) SvPV(ST(i-1),na);
13545       switch (*attribute)
13546       {
13547         case 'C':
13548         case 'c':
13549         {
13550           if (LocaleCompare(attribute,"channel") == 0)
13551             {
13552               ssize_t
13553                 option;
13554
13555               option=ParseChannelOption(SvPV(ST(i),na));
13556               if (option < 0)
13557                 {
13558                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13559                     SvPV(ST(i),na));
13560                   return;
13561                 }
13562               channel=(ChannelType) option;
13563               break;
13564             }
13565           if (LocaleCompare(attribute,"color") == 0)
13566             {
13567               if (SvTYPE(ST(i)) != SVt_RV)
13568                 {
13569                   char
13570                     message[MaxTextExtent];
13571
13572                   (void) FormatLocaleString(message,MaxTextExtent,
13573                     "invalid %.60s value",attribute);
13574                   ThrowPerlException(exception,OptionError,message,
13575                     SvPV(ST(i),na));
13576                 }
13577               av=(AV *) SvRV(ST(i));
13578               break;
13579             }
13580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13581             attribute);
13582           break;
13583         }
13584         case 'g':
13585         case 'G':
13586         {
13587           if (LocaleCompare(attribute,"geometry") == 0)
13588             {
13589               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13590               break;
13591             }
13592           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13593             attribute);
13594           break;
13595         }
13596         case 'N':
13597         case 'n':
13598         {
13599           if (LocaleCompare(attribute,"normalize") == 0)
13600             {
13601               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13602                 SvPV(ST(i),na));
13603               if (option < 0)
13604                 {
13605                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13606                     SvPV(ST(i),na));
13607                   break;
13608                 }
13609              normalize=option != 0 ? MagickTrue : MagickFalse;
13610              break;
13611             }
13612           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13613             attribute);
13614           break;
13615         }
13616         case 'x':
13617         case 'X':
13618         {
13619           if (LocaleCompare(attribute,"x") == 0)
13620             {
13621               region.x=SvIV(ST(i));
13622               break;
13623             }
13624           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13625             attribute);
13626           break;
13627         }
13628         case 'y':
13629         case 'Y':
13630         {
13631           if (LocaleCompare(attribute,"y") == 0)
13632             {
13633               region.y=SvIV(ST(i));
13634               break;
13635             }
13636           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13637             attribute);
13638           break;
13639         }
13640         default:
13641         {
13642           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13643             attribute);
13644           break;
13645         }
13646       }
13647     }
13648     (void) SetImageStorageClass(image,DirectClass,exception);
13649     channel_mask=SetImageChannelMask(image,channel);
13650     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13651     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13652         (SvTYPE(av) != SVt_PVAV))
13653       PUSHs(&sv_undef);
13654     else
13655       {
13656         double
13657           scale;
13658
13659         register ssize_t
13660           i;
13661
13662         i=0;
13663         scale=1.0;
13664         if (normalize != MagickFalse)
13665           scale=QuantumRange;
13666         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13667             (i <= av_len(av)))
13668           {
13669             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13670               av_fetch(av,i,0)))),q);
13671             i++;
13672           }
13673         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13674             (i <= av_len(av)))
13675           {
13676             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13677               av_fetch(av,i,0)))),q);
13678             i++;
13679           }
13680         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13681             (i <= av_len(av)))
13682           {
13683             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13684               av_fetch(av,i,0)))),q);
13685             i++;
13686           }
13687         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13688             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13689           {
13690             SetPixelBlack(image,ClampToQuantum(scale*
13691               SvNV(*(av_fetch(av,i,0)))),q);
13692             i++;
13693           }
13694         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13695             (i <= av_len(av)))
13696           {
13697             SetPixelAlpha(image,ClampToQuantum(scale*
13698               SvNV(*(av_fetch(av,i,0)))),q);
13699             i++;
13700           }
13701         (void) SyncAuthenticPixels(image,exception);
13702       }
13703     (void) SetImageChannelMask(image,channel_mask);
13704
13705   PerlException:
13706     InheritPerlException(exception,perl_exception);
13707     exception=DestroyExceptionInfo(exception);
13708     SvREFCNT_dec(perl_exception);
13709   }
13710 \f
13711 #
13712 ###############################################################################
13713 #                                                                             #
13714 #                                                                             #
13715 #                                                                             #
13716 #   S m u s h                                                                 #
13717 #                                                                             #
13718 #                                                                             #
13719 #                                                                             #
13720 ###############################################################################
13721 #
13722 #
13723 void
13724 Smush(ref,...)
13725   Image::Magick ref=NO_INIT
13726   ALIAS:
13727     SmushImage  = 1
13728     smush       = 2
13729     smushimage  = 3
13730   PPCODE:
13731   {
13732     AV
13733       *av;
13734
13735     char
13736       *attribute;
13737
13738     ExceptionInfo
13739       *exception;
13740
13741     HV
13742       *hv;
13743
13744     Image
13745       *image;
13746
13747     register ssize_t
13748       i;
13749
13750     ssize_t
13751       offset,
13752       stack;
13753
13754     struct PackageInfo
13755       *info;
13756
13757     SV
13758       *av_reference,
13759       *perl_exception,
13760       *reference,
13761       *rv,
13762       *sv;
13763
13764     PERL_UNUSED_VAR(ref);
13765     PERL_UNUSED_VAR(ix);
13766     exception=AcquireExceptionInfo();
13767     perl_exception=newSVpv("",0);
13768     sv=NULL;
13769     attribute=NULL;
13770     av=NULL;
13771     if (sv_isobject(ST(0)) == 0)
13772       {
13773         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13774           PackageName);
13775         goto PerlException;
13776       }
13777     reference=SvRV(ST(0));
13778     hv=SvSTASH(reference);
13779     av=newAV();
13780     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13781     SvREFCNT_dec(av);
13782     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13783     if (image == (Image *) NULL)
13784       {
13785         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13786           PackageName);
13787         goto PerlException;
13788       }
13789     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13790     /*
13791       Get options.
13792     */
13793     offset=0;
13794     stack=MagickTrue;
13795     for (i=2; i < items; i+=2)
13796     {
13797       attribute=(char *) SvPV(ST(i-1),na);
13798       switch (*attribute)
13799       {
13800         case 'O':
13801         case 'o':
13802         {
13803           if (LocaleCompare(attribute,"offset") == 0)
13804             {
13805               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13806               break;
13807             }
13808           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13809             attribute);
13810           break;
13811         }
13812         case 'S':
13813         case 's':
13814         {
13815           if (LocaleCompare(attribute,"stack") == 0)
13816             {
13817               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13818                 SvPV(ST(i),na));
13819               if (stack < 0)
13820                 {
13821                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13822                     SvPV(ST(i),na));
13823                   return;
13824                 }
13825               break;
13826             }
13827           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13828             attribute);
13829           break;
13830         }
13831         default:
13832         {
13833           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13834             attribute);
13835           break;
13836         }
13837       }
13838     }
13839     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13840       exception);
13841     if (image == (Image *) NULL)
13842       goto PerlException;
13843     for ( ; image; image=image->next)
13844     {
13845       AddImageToRegistry(sv,image);
13846       rv=newRV(sv);
13847       av_push(av,sv_bless(rv,hv));
13848       SvREFCNT_dec(sv);
13849     }
13850     exception=DestroyExceptionInfo(exception);
13851     ST(0)=av_reference;
13852     SvREFCNT_dec(perl_exception);
13853     XSRETURN(1);
13854
13855   PerlException:
13856     InheritPerlException(exception,perl_exception);
13857     exception=DestroyExceptionInfo(exception);
13858     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13859     SvPOK_on(perl_exception);
13860     ST(0)=sv_2mortal(perl_exception);
13861     XSRETURN(1);
13862   }
13863 \f
13864 #
13865 ###############################################################################
13866 #                                                                             #
13867 #                                                                             #
13868 #                                                                             #
13869 #   S t a t i s t i c s                                                       #
13870 #                                                                             #
13871 #                                                                             #
13872 #                                                                             #
13873 ###############################################################################
13874 #
13875 #
13876 void
13877 Statistics(ref,...)
13878   Image::Magick ref=NO_INIT
13879   ALIAS:
13880     StatisticsImage = 1
13881     statistics      = 2
13882     statisticsimage = 3
13883   PPCODE:
13884   {
13885 #define ChannelStatistics(channel) \
13886 { \
13887   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13888     (double) channel_statistics[channel].depth); \
13889   PUSHs(sv_2mortal(newSVpv(message,0))); \
13890   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13891     channel_statistics[channel].minima/scale); \
13892   PUSHs(sv_2mortal(newSVpv(message,0))); \
13893   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13894     channel_statistics[channel].maxima/scale); \
13895   PUSHs(sv_2mortal(newSVpv(message,0))); \
13896   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13897     channel_statistics[channel].mean/scale); \
13898   PUSHs(sv_2mortal(newSVpv(message,0))); \
13899   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13900     channel_statistics[channel].standard_deviation/scale); \
13901   PUSHs(sv_2mortal(newSVpv(message,0))); \
13902   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13903     channel_statistics[channel].kurtosis); \
13904   PUSHs(sv_2mortal(newSVpv(message,0))); \
13905   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13906     channel_statistics[channel].skewness); \
13907   PUSHs(sv_2mortal(newSVpv(message,0))); \
13908 }
13909
13910     AV
13911       *av;
13912
13913     char
13914       message[MaxTextExtent];
13915
13916     ChannelStatistics
13917       *channel_statistics;
13918
13919     double
13920       scale;
13921
13922     ExceptionInfo
13923       *exception;
13924
13925     Image
13926       *image;
13927
13928     ssize_t
13929       count;
13930
13931     struct PackageInfo
13932       *info;
13933
13934     SV
13935       *perl_exception,
13936       *reference;
13937
13938     PERL_UNUSED_VAR(ref);
13939     PERL_UNUSED_VAR(ix);
13940     exception=AcquireExceptionInfo();
13941     perl_exception=newSVpv("",0);
13942     av=NULL;
13943     if (sv_isobject(ST(0)) == 0)
13944       {
13945         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13946           PackageName);
13947         goto PerlException;
13948       }
13949     reference=SvRV(ST(0));
13950     av=newAV();
13951     SvREFCNT_dec(av);
13952     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13953     if (image == (Image *) NULL)
13954       {
13955         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13956           PackageName);
13957         goto PerlException;
13958       }
13959     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13960     count=0;
13961     for ( ; image; image=image->next)
13962     {
13963       channel_statistics=GetImageStatistics(image,exception);
13964       if (channel_statistics == (ChannelStatistics *) NULL)
13965         continue;
13966       count++;
13967       EXTEND(sp,35*count);
13968       scale=(double) QuantumRange;
13969       ChannelStatistics(RedChannel);
13970       ChannelStatistics(GreenChannel);
13971       ChannelStatistics(BlueChannel);
13972       if (image->colorspace == CMYKColorspace)
13973         ChannelStatistics(BlackChannel);
13974       if (image->alpha_trait == BlendPixelTrait)
13975         ChannelStatistics(AlphaChannel);
13976       channel_statistics=(ChannelStatistics *)
13977         RelinquishMagickMemory(channel_statistics);
13978     }
13979
13980   PerlException:
13981     InheritPerlException(exception,perl_exception);
13982     exception=DestroyExceptionInfo(exception);
13983     SvREFCNT_dec(perl_exception);
13984   }
13985 \f
13986 #
13987 ###############################################################################
13988 #                                                                             #
13989 #                                                                             #
13990 #                                                                             #
13991 #   S y n c A u t h e n t i c P i x e l s                                     #
13992 #                                                                             #
13993 #                                                                             #
13994 #                                                                             #
13995 ###############################################################################
13996 #
13997 #
13998 void
13999 SyncAuthenticPixels(ref,...)
14000   Image::Magick ref = NO_INIT
14001   ALIAS:
14002     Syncauthenticpixels = 1
14003     SyncImagePixels = 2
14004     syncimagepixels = 3
14005   CODE:
14006   {
14007     ExceptionInfo
14008       *exception;
14009
14010     Image
14011       *image;
14012
14013     MagickBooleanType
14014       status;
14015
14016     struct PackageInfo
14017       *info;
14018
14019     SV
14020       *perl_exception,
14021       *reference;
14022
14023     PERL_UNUSED_VAR(ref);
14024     PERL_UNUSED_VAR(ix);
14025     exception=AcquireExceptionInfo();
14026     perl_exception=newSVpv("",0);
14027     if (sv_isobject(ST(0)) == 0)
14028       {
14029         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14030           PackageName);
14031         goto PerlException;
14032       }
14033
14034     reference=SvRV(ST(0));
14035     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14036     if (image == (Image *) NULL)
14037       {
14038         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14039           PackageName);
14040         goto PerlException;
14041       }
14042
14043     status=SyncAuthenticPixels(image,exception);
14044     if (status != MagickFalse)
14045       return;
14046
14047   PerlException:
14048     InheritPerlException(exception,perl_exception);
14049     exception=DestroyExceptionInfo(exception);
14050     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14051   }
14052 \f
14053 #
14054 ###############################################################################
14055 #                                                                             #
14056 #                                                                             #
14057 #                                                                             #
14058 #   T r a n s f o r m                                                         #
14059 #                                                                             #
14060 #                                                                             #
14061 #                                                                             #
14062 ###############################################################################
14063 #
14064 #
14065 void
14066 Transform(ref,...)
14067   Image::Magick ref=NO_INIT
14068   ALIAS:
14069     TransformImage = 1
14070     transform      = 2
14071     transformimage = 3
14072   PPCODE:
14073   {
14074     AV
14075       *av;
14076
14077     char
14078       *attribute,
14079       *crop_geometry,
14080       *geometry;
14081
14082     ExceptionInfo
14083       *exception;
14084
14085     HV
14086       *hv;
14087
14088     Image
14089       *clone,
14090       *image;
14091
14092     register ssize_t
14093       i;
14094
14095     struct PackageInfo
14096       *info;
14097
14098     SV
14099       *av_reference,
14100       *perl_exception,
14101       *reference,
14102       *rv,
14103       *sv;
14104
14105     PERL_UNUSED_VAR(ref);
14106     PERL_UNUSED_VAR(ix);
14107     exception=AcquireExceptionInfo();
14108     perl_exception=newSVpv("",0);
14109     sv=NULL;
14110     av=NULL;
14111     attribute=NULL;
14112     if (sv_isobject(ST(0)) == 0)
14113       {
14114         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14115           PackageName);
14116         goto PerlException;
14117       }
14118     reference=SvRV(ST(0));
14119     hv=SvSTASH(reference);
14120     av=newAV();
14121     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14122     SvREFCNT_dec(av);
14123     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14124     if (image == (Image *) NULL)
14125       {
14126         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14127           PackageName);
14128         goto PerlException;
14129       }
14130     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14131     /*
14132       Get attribute.
14133     */
14134     crop_geometry=(char *) NULL;
14135     geometry=(char *) NULL;
14136     for (i=2; i < items; i+=2)
14137     {
14138       attribute=(char *) SvPV(ST(i-1),na);
14139       switch (*attribute)
14140       {
14141         case 'c':
14142         case 'C':
14143         {
14144           if (LocaleCompare(attribute,"crop") == 0)
14145             {
14146               crop_geometry=SvPV(ST(i),na);
14147               break;
14148             }
14149           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14150             attribute);
14151           break;
14152         }
14153         case 'g':
14154         case 'G':
14155         {
14156           if (LocaleCompare(attribute,"geometry") == 0)
14157             {
14158               geometry=SvPV(ST(i),na);
14159               break;
14160             }
14161           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14162             attribute);
14163           break;
14164         }
14165         default:
14166         {
14167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14168             attribute);
14169           break;
14170         }
14171       }
14172     }
14173     for ( ; image; image=image->next)
14174     {
14175       clone=CloneImage(image,0,0,MagickTrue,exception);
14176       if (clone == (Image *) NULL)
14177         goto PerlException;
14178       TransformImage(&clone,crop_geometry,geometry,exception);
14179       for ( ; clone; clone=clone->next)
14180       {
14181         AddImageToRegistry(sv,clone);
14182         rv=newRV(sv);
14183         av_push(av,sv_bless(rv,hv));
14184         SvREFCNT_dec(sv);
14185       }
14186     }
14187     exception=DestroyExceptionInfo(exception);
14188     ST(0)=av_reference;
14189     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14190     XSRETURN(1);
14191
14192   PerlException:
14193     InheritPerlException(exception,perl_exception);
14194     exception=DestroyExceptionInfo(exception);
14195     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14196     SvPOK_on(perl_exception);
14197     ST(0)=sv_2mortal(perl_exception);
14198     XSRETURN(1);
14199   }
14200 \f
14201 #
14202 ###############################################################################
14203 #                                                                             #
14204 #                                                                             #
14205 #                                                                             #
14206 #   W r i t e                                                                 #
14207 #                                                                             #
14208 #                                                                             #
14209 #                                                                             #
14210 ###############################################################################
14211 #
14212 #
14213 void
14214 Write(ref,...)
14215   Image::Magick ref=NO_INIT
14216   ALIAS:
14217     WriteImage    = 1
14218     write         = 2
14219     writeimage    = 3
14220   PPCODE:
14221   {
14222     char
14223       filename[MaxTextExtent];
14224
14225     ExceptionInfo
14226       *exception;
14227
14228     Image
14229       *image,
14230       *next;
14231
14232     register ssize_t
14233       i;
14234
14235     ssize_t
14236       number_images,
14237       scene;
14238
14239     struct PackageInfo
14240       *info,
14241       *package_info;
14242
14243     SV
14244       *perl_exception,
14245       *reference;
14246
14247     PERL_UNUSED_VAR(ref);
14248     PERL_UNUSED_VAR(ix);
14249     exception=AcquireExceptionInfo();
14250     perl_exception=newSVpv("",0);
14251     number_images=0;
14252     package_info=(struct PackageInfo *) NULL;
14253     if (sv_isobject(ST(0)) == 0)
14254       {
14255         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14256           PackageName);
14257         goto PerlException;
14258       }
14259     reference=SvRV(ST(0));
14260     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14261     if (image == (Image *) NULL)
14262       {
14263         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14264           PackageName);
14265         goto PerlException;
14266       }
14267     package_info=ClonePackageInfo(info,exception);
14268     if (items == 2)
14269       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14270     else
14271       if (items > 2)
14272         for (i=2; i < items; i+=2)
14273           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14274             exception);
14275     (void) CopyMagickString(filename,package_info->image_info->filename,
14276       MaxTextExtent);
14277     scene=0;
14278     for (next=image; next; next=next->next)
14279     {
14280       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14281       next->scene=scene++;
14282     }
14283     SetImageInfo(package_info->image_info,(unsigned int)
14284       GetImageListLength(image),exception);
14285     for (next=image; next; next=next->next)
14286     {
14287       (void) WriteImage(package_info->image_info,next,exception);
14288       number_images++;
14289       if (package_info->image_info->adjoin)
14290         break;
14291     }
14292
14293   PerlException:
14294     if (package_info != (struct PackageInfo *) NULL)
14295       DestroyPackageInfo(package_info);
14296     InheritPerlException(exception,perl_exception);
14297     exception=DestroyExceptionInfo(exception);
14298     sv_setiv(perl_exception,(IV) number_images);
14299     SvPOK_on(perl_exception);
14300     ST(0)=sv_2mortal(perl_exception);
14301     XSRETURN(1);
14302   }