]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
Removed Transform method.
[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 %                                 Cristy                                      %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2016 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 <MagickCore/MagickCore.h>
57 #include "EXTERN.h"
58 #include "perl.h"
59 #include "XSUB.h"
60 #include <math.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "Mode", { {"geometry", StringReference},
535       {"width", IntegerReference},{"height", IntegerReference},
536       {"channel", MagickChannelOptions} } },
537     { "Statistic", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
540     { "Perceptible", { {"epsilon", RealReference},
541       {"channel", MagickChannelOptions} } },
542     { "Poly", { {"terms", ArrayReference},
543       {"channel", MagickChannelOptions} } },
544     { "Grayscale", { {"method", MagickNoiseOptions} } },
545     { "CannyEdge", { {"geometry", StringReference},
546       {"radius", RealReference}, {"sigma", RealReference},
547       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
548     { "HoughLine", { {"geometry", StringReference},
549       {"width", IntegerReference}, {"height", IntegerReference},
550       {"threshold", IntegerReference} } },
551     { "MeanShift", { {"geometry", StringReference},
552       {"width", IntegerReference}, {"height", IntegerReference},
553       {"distance", RealReference} } },
554     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
555       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
556     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
557     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
558       {"width", IntegerReference}, {"height", IntegerReference},
559       {"x", IntegerReference}, {"y", IntegerReference},
560       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
561       {"dx", IntegerReference}, {"dy", IntegerReference} } },
562     { "Color", { {"color", StringReference} } },
563     { "WaveletDenoise", {  {"geometry", StringReference},
564       {"threshold", RealReference}, {"softness", RealReference},
565       {"channel", MagickChannelOptions} } },
566   };
567
568 static SplayTreeInfo
569   *magick_registry = (SplayTreeInfo *) NULL;
570 \f
571 /*
572   Forward declarations.
573 */
574 static Image
575   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
576
577 static ssize_t
578   strEQcase(const char *,const char *);
579 \f
580 /*
581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
582 %                                                                             %
583 %                                                                             %
584 %                                                                             %
585 %   C l o n e P a c k a g e I n f o                                           %
586 %                                                                             %
587 %                                                                             %
588 %                                                                             %
589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
590 %
591 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
592 %  a new one.
593 %
594 %  The format of the ClonePackageInfo routine is:
595 %
596 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
597 %        exception)
598 %
599 %  A description of each parameter follows:
600 %
601 %    o info: a structure of type info.
602 %
603 %    o exception: Return any errors or warnings in this structure.
604 %
605 */
606 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
607   ExceptionInfo *exception)
608 {
609   struct PackageInfo
610     *clone_info;
611
612   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
613   if (clone_info == (struct PackageInfo *) NULL)
614     {
615       ThrowPerlException(exception,ResourceLimitError,
616         "UnableToClonePackageInfo",PackageName);
617       return((struct PackageInfo *) NULL);
618     }
619   if (info == (struct PackageInfo *) NULL)
620     {
621       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
622       return(clone_info);
623     }
624   *clone_info=(*info);
625   clone_info->image_info=CloneImageInfo(info->image_info);
626   return(clone_info);
627 }
628 \f
629 /*
630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631 %                                                                             %
632 %                                                                             %
633 %                                                                             %
634 %   c o n s t a n t                                                           %
635 %                                                                             %
636 %                                                                             %
637 %                                                                             %
638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639 %
640 %  constant() returns a double value for the specified name.
641 %
642 %  The format of the constant routine is:
643 %
644 %      double constant(char *name,ssize_t sans)
645 %
646 %  A description of each parameter follows:
647 %
648 %    o value: Method constant returns a double value for the specified name.
649 %
650 %    o name: The name of the constant.
651 %
652 %    o sans: This integer value is not used.
653 %
654 */
655 static double constant(char *name,ssize_t sans)
656 {
657   (void) sans;
658   errno=0;
659   switch (*name)
660   {
661     case 'B':
662     {
663       if (strEQ(name,"BlobError"))
664         return(BlobError);
665       if (strEQ(name,"BlobWarning"))
666         return(BlobWarning);
667       break;
668     }
669     case 'C':
670     {
671       if (strEQ(name,"CacheError"))
672         return(CacheError);
673       if (strEQ(name,"CacheWarning"))
674         return(CacheWarning);
675       if (strEQ(name,"CoderError"))
676         return(CoderError);
677       if (strEQ(name,"CoderWarning"))
678         return(CoderWarning);
679       if (strEQ(name,"ConfigureError"))
680         return(ConfigureError);
681       if (strEQ(name,"ConfigureWarning"))
682         return(ConfigureWarning);
683       if (strEQ(name,"CorruptImageError"))
684         return(CorruptImageError);
685       if (strEQ(name,"CorruptImageWarning"))
686         return(CorruptImageWarning);
687       break;
688     }
689     case 'D':
690     {
691       if (strEQ(name,"DelegateError"))
692         return(DelegateError);
693       if (strEQ(name,"DelegateWarning"))
694         return(DelegateWarning);
695       if (strEQ(name,"DrawError"))
696         return(DrawError);
697       if (strEQ(name,"DrawWarning"))
698         return(DrawWarning);
699       break;
700     }
701     case 'E':
702     {
703       if (strEQ(name,"ErrorException"))
704         return(ErrorException);
705       if (strEQ(name,"ExceptionError"))
706         return(CoderError);
707       if (strEQ(name,"ExceptionWarning"))
708         return(CoderWarning);
709       break;
710     }
711     case 'F':
712     {
713       if (strEQ(name,"FatalErrorException"))
714         return(FatalErrorException);
715       if (strEQ(name,"FileOpenError"))
716         return(FileOpenError);
717       if (strEQ(name,"FileOpenWarning"))
718         return(FileOpenWarning);
719       break;
720     }
721     case 'I':
722     {
723       if (strEQ(name,"ImageError"))
724         return(ImageError);
725       if (strEQ(name,"ImageWarning"))
726         return(ImageWarning);
727       break;
728     }
729     case 'M':
730     {
731       if (strEQ(name,"MaxRGB"))
732         return(QuantumRange);
733       if (strEQ(name,"MissingDelegateError"))
734         return(MissingDelegateError);
735       if (strEQ(name,"MissingDelegateWarning"))
736         return(MissingDelegateWarning);
737       if (strEQ(name,"ModuleError"))
738         return(ModuleError);
739       if (strEQ(name,"ModuleWarning"))
740         return(ModuleWarning);
741       break;
742     }
743     case 'O':
744     {
745       if (strEQ(name,"Opaque"))
746         return(OpaqueAlpha);
747       if (strEQ(name,"OptionError"))
748         return(OptionError);
749       if (strEQ(name,"OptionWarning"))
750         return(OptionWarning);
751       break;
752     }
753     case 'Q':
754     {
755       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
756         return(MAGICKCORE_QUANTUM_DEPTH);
757       if (strEQ(name,"QuantumDepth"))
758         return(MAGICKCORE_QUANTUM_DEPTH);
759       if (strEQ(name,"QuantumRange"))
760         return(QuantumRange);
761       break;
762     }
763     case 'R':
764     {
765       if (strEQ(name,"ResourceLimitError"))
766         return(ResourceLimitError);
767       if (strEQ(name,"ResourceLimitWarning"))
768         return(ResourceLimitWarning);
769       if (strEQ(name,"RegistryError"))
770         return(RegistryError);
771       if (strEQ(name,"RegistryWarning"))
772         return(RegistryWarning);
773       break;
774     }
775     case 'S':
776     {
777       if (strEQ(name,"StreamError"))
778         return(StreamError);
779       if (strEQ(name,"StreamWarning"))
780         return(StreamWarning);
781       if (strEQ(name,"Success"))
782         return(0);
783       break;
784     }
785     case 'T':
786     {
787       if (strEQ(name,"Transparent"))
788         return(TransparentAlpha);
789       if (strEQ(name,"TypeError"))
790         return(TypeError);
791       if (strEQ(name,"TypeWarning"))
792         return(TypeWarning);
793       break;
794     }
795     case 'W':
796     {
797       if (strEQ(name,"WarningException"))
798         return(WarningException);
799       break;
800     }
801     case 'X':
802     {
803       if (strEQ(name,"XServerError"))
804         return(XServerError);
805       if (strEQ(name,"XServerWarning"))
806         return(XServerWarning);
807       break;
808     }
809   }
810   errno=EINVAL;
811   return(0);
812 }
813 \f
814 /*
815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
816 %                                                                             %
817 %                                                                             %
818 %                                                                             %
819 %   D e s t r o y P a c k a g e I n f o                                       %
820 %                                                                             %
821 %                                                                             %
822 %                                                                             %
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 %
825 %  Method DestroyPackageInfo frees a previously created info structure.
826 %
827 %  The format of the DestroyPackageInfo routine is:
828 %
829 %      DestroyPackageInfo(struct PackageInfo *info)
830 %
831 %  A description of each parameter follows:
832 %
833 %    o info: a structure of type info.
834 %
835 */
836 static void DestroyPackageInfo(struct PackageInfo *info)
837 {
838   info->image_info=DestroyImageInfo(info->image_info);
839   info=(struct PackageInfo *) RelinquishMagickMemory(info);
840 }
841 \f
842 /*
843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844 %                                                                             %
845 %                                                                             %
846 %                                                                             %
847 %   G e t L i s t                                                             %
848 %                                                                             %
849 %                                                                             %
850 %                                                                             %
851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852 %
853 %  Method GetList is recursively called by SetupList to traverse the
854 %  Image__Magick reference.  If building an reference_vector (see SetupList),
855 %  *current is the current position in *reference_vector and *last is the final
856 %  entry in *reference_vector.
857 %
858 %  The format of the GetList routine is:
859 %
860 %      GetList(info)
861 %
862 %  A description of each parameter follows:
863 %
864 %    o info: a structure of type info.
865 %
866 */
867 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
868   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
869 {
870   Image
871     *image;
872
873   if (reference == (SV *) NULL)
874     return(NULL);
875   switch (SvTYPE(reference))
876   {
877     case SVt_PVAV:
878     {
879       AV
880         *av;
881
882       Image
883         *head,
884         *previous;
885
886       register ssize_t
887         i;
888
889       ssize_t
890         n;
891
892       /*
893         Array of images.
894       */
895       previous=(Image *) NULL;
896       head=(Image *) NULL;
897       av=(AV *) reference;
898       n=av_len(av);
899       for (i=0; i <= n; i++)
900       {
901         SV
902           **rv;
903
904         rv=av_fetch(av,i,0);
905         if (rv && *rv && sv_isobject(*rv))
906           {
907             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
908               exception);
909             if (image == (Image *) NULL)
910               continue;
911             if (image == previous)
912               {
913                 image=CloneImage(image,0,0,MagickTrue,exception);
914                 if (image == (Image *) NULL)
915                   return(NULL);
916               }
917             image->previous=previous;
918             *(previous ? &previous->next : &head)=image;
919             for (previous=image; previous->next; previous=previous->next) ;
920           }
921       }
922       return(head);
923     }
924     case SVt_PVMG:
925     {
926       /*
927         Blessed scalar, one image.
928       */
929       image=INT2PTR(Image *,SvIV(reference));
930       if (image == (Image *) NULL)
931         return(NULL);
932       image->previous=(Image *) NULL;
933       image->next=(Image *) NULL;
934       if (reference_vector)
935         {
936           if (*current == *last)
937             {
938               *last+=256;
939               if (*reference_vector == (SV **) NULL)
940                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
941                   sizeof(*reference_vector));
942               else
943                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
944                   *last,sizeof(*reference_vector));
945             }
946           if (*reference_vector == (SV **) NULL)
947             {
948               ThrowPerlException(exception,ResourceLimitError,
949                 "MemoryAllocationFailed",PackageName);
950               return((Image *) NULL);
951             }
952           (*reference_vector)[*current]=reference;
953           (*reference_vector)[++(*current)]=NULL;
954         }
955       return(image);
956     }
957     default:
958       break;
959   }
960   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
961     (double) SvTYPE(reference));
962   return((Image *) NULL);
963 }
964 \f
965 /*
966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
967 %                                                                             %
968 %                                                                             %
969 %                                                                             %
970 %   G e t P a c k a g e I n f o                                               %
971 %                                                                             %
972 %                                                                             %
973 %                                                                             %
974 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
975 %
976 %  Method GetPackageInfo looks up or creates an info structure for the given
977 %  Image__Magick reference.  If it does create a new one, the information in
978 %  package_info is used to initialize it.
979 %
980 %  The format of the GetPackageInfo routine is:
981 %
982 %      struct PackageInfo *GetPackageInfo(void *reference,
983 %        struct PackageInfo *package_info,ExceptionInfo *exception)
984 %
985 %  A description of each parameter follows:
986 %
987 %    o info: a structure of type info.
988 %
989 %    o exception: Return any errors or warnings in this structure.
990 %
991 */
992 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
993   struct PackageInfo *package_info,ExceptionInfo *exception)
994 {
995   char
996     message[MagickPathExtent];
997
998   struct PackageInfo
999     *clone_info;
1000
1001   SV
1002     *sv;
1003
1004   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1005     PackageName,XS_VERSION,reference);
1006   sv=perl_get_sv(message,(TRUE | 0x02));
1007   if (sv == (SV *) NULL)
1008     {
1009       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1010         message);
1011       return(package_info);
1012     }
1013   if (SvREFCNT(sv) == 0)
1014     (void) SvREFCNT_inc(sv);
1015   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1016     return(clone_info);
1017   clone_info=ClonePackageInfo(package_info,exception);
1018   sv_setiv(sv,PTR2IV(clone_info));
1019   return(clone_info);
1020 }
1021 \f
1022 /*
1023 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1024 %                                                                             %
1025 %                                                                             %
1026 %                                                                             %
1027 %   S e t A t t r i b u t e                                                   %
1028 %                                                                             %
1029 %                                                                             %
1030 %                                                                             %
1031 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1032 %
1033 %  SetAttribute() sets the attribute to the value in sval.  This can change
1034 %  either or both of image or info.
1035 %
1036 %  The format of the SetAttribute routine is:
1037 %
1038 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1039 %        SV *sval,ExceptionInfo *exception)
1040 %
1041 %  A description of each parameter follows:
1042 %
1043 %    o list: a list of strings.
1044 %
1045 %    o string: a character string.
1046 %
1047 */
1048
1049 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1050 {
1051   char
1052     *q;
1053
1054   double
1055     value;
1056
1057   value=InterpretSiPrefixValue(string,&q);
1058   if (*q == '%')
1059     value*=interval/100.0;
1060   return(value);
1061 }
1062
1063 static inline double StringToDouble(const char *string,char **sentinal)
1064 {
1065   return(InterpretLocaleValue(string,sentinal));
1066 }
1067
1068 static double StringToDoubleInterval(const char *string,const double interval)
1069 {
1070   char
1071     *q;
1072
1073   double
1074     value;
1075
1076   value=InterpretLocaleValue(string,&q);
1077   if (*q == '%')
1078     value*=interval/100.0;
1079   return(value);
1080 }
1081
1082 static inline ssize_t StringToLong(const char *value)
1083 {
1084   return(strtol(value,(char **) NULL,10));
1085 }
1086
1087 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1088   const char *attribute,SV *sval,ExceptionInfo *exception)
1089 {
1090   GeometryInfo
1091     geometry_info;
1092
1093   long
1094     x,
1095     y;
1096
1097   PixelInfo
1098     pixel;
1099
1100   MagickStatusType
1101     flags;
1102
1103   PixelInfo
1104     *color,
1105     target_color;
1106
1107   ssize_t
1108     sp;
1109
1110   switch (*attribute)
1111   {
1112     case 'A':
1113     case 'a':
1114     {
1115       if (LocaleCompare(attribute,"adjoin") == 0)
1116         {
1117           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1118             SvPV(sval,na)) : SvIV(sval);
1119           if (sp < 0)
1120             {
1121               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1122                 SvPV(sval,na));
1123               break;
1124             }
1125           if (info)
1126             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1127           break;
1128         }
1129       if (LocaleCompare(attribute,"alpha") == 0)
1130         {
1131           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1132             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1133           if (sp < 0)
1134             {
1135               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1136                 SvPV(sval,na));
1137               break;
1138             }
1139           for ( ; image; image=image->next)
1140             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1141               exception);
1142           break;
1143         }
1144       if (LocaleCompare(attribute,"antialias") == 0)
1145         {
1146           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1147             SvPV(sval,na)) : SvIV(sval);
1148           if (sp < 0)
1149             {
1150               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1151                 SvPV(sval,na));
1152               break;
1153             }
1154           if (info)
1155             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1156           break;
1157         }
1158       if (LocaleCompare(attribute,"area-limit") == 0)
1159         {
1160           MagickSizeType
1161             limit;
1162
1163           limit=MagickResourceInfinity;
1164           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1165             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1166               100.0);
1167           (void) SetMagickResourceLimit(AreaResource,limit);
1168           break;
1169         }
1170       if (LocaleCompare(attribute,"attenuate") == 0)
1171         {
1172           if (info)
1173             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1174           break;
1175         }
1176       if (LocaleCompare(attribute,"authenticate") == 0)
1177         {
1178           if (info)
1179             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1180           break;
1181         }
1182       if (info)
1183         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1184       for ( ; image; image=image->next)
1185         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1186       break;
1187     }
1188     case 'B':
1189     case 'b':
1190     {
1191       if (LocaleCompare(attribute,"background") == 0)
1192         {
1193           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1194             exception);
1195           if (info)
1196             info->image_info->background_color=target_color;
1197           for ( ; image; image=image->next)
1198             image->background_color=target_color;
1199           break;
1200         }
1201       if (LocaleCompare(attribute,"blue-primary") == 0)
1202         {
1203           for ( ; image; image=image->next)
1204           {
1205             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1206             image->chromaticity.blue_primary.x=geometry_info.rho;
1207             image->chromaticity.blue_primary.y=geometry_info.sigma;
1208             if ((flags & SigmaValue) == 0)
1209               image->chromaticity.blue_primary.y=
1210                 image->chromaticity.blue_primary.x;
1211           }
1212           break;
1213         }
1214       if (LocaleCompare(attribute,"bordercolor") == 0)
1215         {
1216           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1217             exception);
1218           if (info)
1219             info->image_info->border_color=target_color;
1220           for ( ; image; image=image->next)
1221             image->border_color=target_color;
1222           break;
1223         }
1224       if (info)
1225         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1226       for ( ; image; image=image->next)
1227         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1228       break;
1229     }
1230     case 'C':
1231     case 'c':
1232     {
1233       if (LocaleCompare(attribute,"cache-threshold") == 0)
1234         {
1235           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1236             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1237           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1238             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1239           break;
1240         }
1241       if (LocaleCompare(attribute,"clip-mask") == 0)
1242         {
1243           Image
1244             *clip_mask;
1245
1246           clip_mask=(Image *) NULL;
1247           if (SvPOK(sval))
1248             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1249           for ( ; image; image=image->next)
1250             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1251           break;
1252         }
1253       if (LocaleNCompare(attribute,"colormap",8) == 0)
1254         {
1255           for ( ; image; image=image->next)
1256           {
1257             int
1258               items;
1259
1260             long
1261               i;
1262
1263             if (image->storage_class == DirectClass)
1264               continue;
1265             i=0;
1266             items=sscanf(attribute,"%*[^[][%ld",&i);
1267             (void) items;
1268             if (i > (ssize_t) image->colors)
1269               i%=image->colors;
1270             if ((strchr(SvPV(sval,na),',') == 0) ||
1271                 (strchr(SvPV(sval,na),')') != 0))
1272               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1273                 image->colormap+i,exception);
1274             else
1275               {
1276                 color=image->colormap+i;
1277                 pixel.red=color->red;
1278                 pixel.green=color->green;
1279                 pixel.blue=color->blue;
1280                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1281                 pixel.red=geometry_info.rho;
1282                 pixel.green=geometry_info.sigma;
1283                 pixel.blue=geometry_info.xi;
1284                 color->red=ClampToQuantum(pixel.red);
1285                 color->green=ClampToQuantum(pixel.green);
1286                 color->blue=ClampToQuantum(pixel.blue);
1287               }
1288           }
1289           break;
1290         }
1291       if (LocaleCompare(attribute,"colorspace") == 0)
1292         {
1293           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1294             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1295           if (sp < 0)
1296             {
1297               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1298                 SvPV(sval,na));
1299               break;
1300             }
1301           for ( ; image; image=image->next)
1302             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1303               exception);
1304           break;
1305         }
1306       if (LocaleCompare(attribute,"comment") == 0)
1307         {
1308           for ( ; image; image=image->next)
1309             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1310               info ? info->image_info : (ImageInfo *) NULL,image,
1311               SvPV(sval,na),exception),exception);
1312           break;
1313         }
1314       if (LocaleCompare(attribute,"compression") == 0)
1315         {
1316           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1317             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1318           if (sp < 0)
1319             {
1320               ThrowPerlException(exception,OptionError,
1321                 "UnrecognizedImageCompression",SvPV(sval,na));
1322               break;
1323             }
1324           if (info)
1325             info->image_info->compression=(CompressionType) sp;
1326           for ( ; image; image=image->next)
1327             image->compression=(CompressionType) sp;
1328           break;
1329         }
1330       if (info)
1331         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1332       for ( ; image; image=image->next)
1333         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1334       break;
1335     }
1336     case 'D':
1337     case 'd':
1338     {
1339       if (LocaleCompare(attribute,"debug") == 0)
1340         {
1341           SetLogEventMask(SvPV(sval,na));
1342           break;
1343         }
1344       if (LocaleCompare(attribute,"delay") == 0)
1345         {
1346           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1347           for ( ; image; image=image->next)
1348           {
1349             image->delay=(size_t) floor(geometry_info.rho+0.5);
1350             if ((flags & SigmaValue) != 0)
1351               image->ticks_per_second=(ssize_t)
1352                 floor(geometry_info.sigma+0.5);
1353           }
1354           break;
1355         }
1356       if (LocaleCompare(attribute,"disk-limit") == 0)
1357         {
1358           MagickSizeType
1359             limit;
1360
1361           limit=MagickResourceInfinity;
1362           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1363             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1364               100.0);
1365           (void) SetMagickResourceLimit(DiskResource,limit);
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"density") == 0)
1369         {
1370           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1371             {
1372               ThrowPerlException(exception,OptionError,"MissingGeometry",
1373                 SvPV(sval,na));
1374               break;
1375             }
1376           if (info)
1377             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1378           for ( ; image; image=image->next)
1379           {
1380             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1381             image->resolution.x=geometry_info.rho;
1382             image->resolution.y=geometry_info.sigma;
1383             if ((flags & SigmaValue) == 0)
1384               image->resolution.y=image->resolution.x;
1385           }
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"depth") == 0)
1389         {
1390           if (info)
1391             info->image_info->depth=SvIV(sval);
1392           for ( ; image; image=image->next)
1393             (void) SetImageDepth(image,SvIV(sval),exception);
1394           break;
1395         }
1396       if (LocaleCompare(attribute,"dispose") == 0)
1397         {
1398           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1399             SvPV(sval,na)) : SvIV(sval);
1400           if (sp < 0)
1401             {
1402               ThrowPerlException(exception,OptionError,
1403                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1404               break;
1405             }
1406           for ( ; image; image=image->next)
1407             image->dispose=(DisposeType) sp;
1408           break;
1409         }
1410       if (LocaleCompare(attribute,"dither") == 0)
1411         {
1412           if (info)
1413             {
1414               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1415                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1416               if (sp < 0)
1417                 {
1418                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1419                     SvPV(sval,na));
1420                   break;
1421                 }
1422               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1423             }
1424           break;
1425         }
1426       if (LocaleCompare(attribute,"display") == 0)
1427         {
1428           display:
1429           if (info)
1430             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1431           break;
1432         }
1433       if (info)
1434         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1435       for ( ; image; image=image->next)
1436         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1437       break;
1438     }
1439     case 'E':
1440     case 'e':
1441     {
1442       if (LocaleCompare(attribute,"endian") == 0)
1443         {
1444           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1445             SvPV(sval,na)) : SvIV(sval);
1446           if (sp < 0)
1447             {
1448               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1449                 SvPV(sval,na));
1450               break;
1451             }
1452           if (info)
1453             info->image_info->endian=(EndianType) sp;
1454           for ( ; image; image=image->next)
1455             image->endian=(EndianType) sp;
1456           break;
1457         }
1458       if (LocaleCompare(attribute,"extract") == 0)
1459         {
1460           /*
1461             Set image extract geometry.
1462           */
1463           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1464           break;
1465         }
1466       if (info)
1467         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1468       for ( ; image; image=image->next)
1469         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1470       break;
1471     }
1472     case 'F':
1473     case 'f':
1474     {
1475       if (LocaleCompare(attribute,"filename") == 0)
1476         {
1477           if (info)
1478             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1479               MagickPathExtent);
1480           for ( ; image; image=image->next)
1481             (void) CopyMagickString(image->filename,SvPV(sval,na),
1482               MagickPathExtent);
1483           break;
1484         }
1485       if (LocaleCompare(attribute,"file") == 0)
1486         {
1487           FILE
1488             *file;
1489
1490           PerlIO
1491             *io_info;
1492
1493           if (info == (struct PackageInfo *) NULL)
1494             break;
1495           io_info=IoIFP(sv_2io(sval));
1496           if (io_info == (PerlIO *) NULL)
1497             {
1498               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1499                 PackageName);
1500               break;
1501             }
1502           file=PerlIO_findFILE(io_info);
1503           if (file == (FILE *) NULL)
1504             {
1505               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1506                 PackageName);
1507               break;
1508             }
1509           SetImageInfoFile(info->image_info,file);
1510           break;
1511         }
1512       if (LocaleCompare(attribute,"fill") == 0)
1513         {
1514           if (info)
1515             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1516           break;
1517         }
1518       if (LocaleCompare(attribute,"font") == 0)
1519         {
1520           if (info)
1521             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1522           break;
1523         }
1524       if (LocaleCompare(attribute,"foreground") == 0)
1525         break;
1526       if (LocaleCompare(attribute,"fuzz") == 0)
1527         {
1528           if (info)
1529             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1530               QuantumRange+1.0);
1531           for ( ; image; image=image->next)
1532             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1533               QuantumRange+1.0);
1534           break;
1535         }
1536       if (info)
1537         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1538       for ( ; image; image=image->next)
1539         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1540       break;
1541     }
1542     case 'G':
1543     case 'g':
1544     {
1545       if (LocaleCompare(attribute,"gamma") == 0)
1546         {
1547           for ( ; image; image=image->next)
1548             image->gamma=SvNV(sval);
1549           break;
1550         }
1551       if (LocaleCompare(attribute,"gravity") == 0)
1552         {
1553           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1554             SvPV(sval,na)) : SvIV(sval);
1555           if (sp < 0)
1556             {
1557               ThrowPerlException(exception,OptionError,
1558                 "UnrecognizedGravityType",SvPV(sval,na));
1559               break;
1560             }
1561           if (info)
1562             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1563           for ( ; image; image=image->next)
1564             image->gravity=(GravityType) sp;
1565           break;
1566         }
1567       if (LocaleCompare(attribute,"green-primary") == 0)
1568         {
1569           for ( ; image; image=image->next)
1570           {
1571             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1572             image->chromaticity.green_primary.x=geometry_info.rho;
1573             image->chromaticity.green_primary.y=geometry_info.sigma;
1574             if ((flags & SigmaValue) == 0)
1575               image->chromaticity.green_primary.y=
1576                 image->chromaticity.green_primary.x;
1577           }
1578           break;
1579         }
1580       if (info)
1581         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1582       for ( ; image; image=image->next)
1583         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1584       break;
1585     }
1586     case 'I':
1587     case 'i':
1588     {
1589       if (LocaleNCompare(attribute,"index",5) == 0)
1590         {
1591           int
1592             items;
1593
1594           long
1595             index;
1596
1597           register Quantum
1598             *q;
1599
1600           CacheView
1601             *image_view;
1602
1603           for ( ; image; image=image->next)
1604           {
1605             if (image->storage_class != PseudoClass)
1606               continue;
1607             x=0;
1608             y=0;
1609             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1610             (void) items;
1611             image_view=AcquireAuthenticCacheView(image,exception);
1612             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1613             if (q != (Quantum *) NULL)
1614               {
1615                 items=sscanf(SvPV(sval,na),"%ld",&index);
1616                 if ((index >= 0) && (index < (ssize_t) image->colors))
1617                   SetPixelIndex(image,index,q);
1618                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1619               }
1620             image_view=DestroyCacheView(image_view);
1621           }
1622           break;
1623         }
1624       if (LocaleCompare(attribute,"iterations") == 0)
1625         {
1626   iterations:
1627           for ( ; image; image=image->next)
1628             image->iterations=SvIV(sval);
1629           break;
1630         }
1631       if (LocaleCompare(attribute,"interlace") == 0)
1632         {
1633           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1634             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1635           if (sp < 0)
1636             {
1637               ThrowPerlException(exception,OptionError,
1638                 "UnrecognizedInterlaceType",SvPV(sval,na));
1639               break;
1640             }
1641           if (info)
1642             info->image_info->interlace=(InterlaceType) sp;
1643           for ( ; image; image=image->next)
1644             image->interlace=(InterlaceType) sp;
1645           break;
1646         }
1647       if (info)
1648         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1649       for ( ; image; image=image->next)
1650         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1651       break;
1652     }
1653     case 'L':
1654     case 'l':
1655     {
1656       if (LocaleCompare(attribute,"label") == 0)
1657         {
1658           for ( ; image; image=image->next)
1659             (void) SetImageProperty(image,"label",InterpretImageProperties(
1660               info ? info->image_info : (ImageInfo *) NULL,image,
1661               SvPV(sval,na),exception),exception);
1662           break;
1663         }
1664       if (LocaleCompare(attribute,"loop") == 0)
1665         goto iterations;
1666       if (info)
1667         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1668       for ( ; image; image=image->next)
1669         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1670       break;
1671     }
1672     case 'M':
1673     case 'm':
1674     {
1675       if (LocaleCompare(attribute,"magick") == 0)
1676         {
1677           if (info)
1678             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1679               "%s:",SvPV(sval,na));
1680           for ( ; image; image=image->next)
1681             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1682           break;
1683         }
1684       if (LocaleCompare(attribute,"map-limit") == 0)
1685         {
1686           MagickSizeType
1687             limit;
1688
1689           limit=MagickResourceInfinity;
1690           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1691             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1692               100.0);
1693           (void) SetMagickResourceLimit(MapResource,limit);
1694           break;
1695         }
1696       if (LocaleCompare(attribute,"mask") == 0)
1697         {
1698           Image
1699             *mask;
1700
1701           mask=(Image *) NULL;
1702           if (SvPOK(sval))
1703             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1704           for ( ; image; image=image->next)
1705             SetImageMask(image,ReadPixelMask,mask,exception);
1706           break;
1707         }
1708       if (LocaleCompare(attribute,"mattecolor") == 0)
1709         {
1710           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1711             exception);
1712           if (info)
1713             info->image_info->alpha_color=target_color;
1714           for ( ; image; image=image->next)
1715             image->alpha_color=target_color;
1716           break;
1717         }
1718       if (LocaleCompare(attribute,"matte") == 0)
1719         {
1720           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1721             SvPV(sval,na)) : SvIV(sval);
1722           if (sp < 0)
1723             {
1724               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1725                 SvPV(sval,na));
1726               break;
1727             }
1728           for ( ; image; image=image->next)
1729             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1730           break;
1731         }
1732       if (LocaleCompare(attribute,"memory-limit") == 0)
1733         {
1734           MagickSizeType
1735             limit;
1736
1737           limit=MagickResourceInfinity;
1738           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1739             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1740               100.0);
1741           (void) SetMagickResourceLimit(MemoryResource,limit);
1742           break;
1743         }
1744       if (LocaleCompare(attribute,"monochrome") == 0)
1745         {
1746           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1747             SvPV(sval,na)) : SvIV(sval);
1748           if (sp < 0)
1749             {
1750               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1751                 SvPV(sval,na));
1752               break;
1753             }
1754           if (info)
1755             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1756           for ( ; image; image=image->next)
1757             (void) SetImageType(image,BilevelType,exception);
1758           break;
1759         }
1760       if (info)
1761         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1762       for ( ; image; image=image->next)
1763         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1764       break;
1765     }
1766     case 'O':
1767     case 'o':
1768     {
1769       if (LocaleCompare(attribute,"option") == 0)
1770         {
1771           if (info)
1772             DefineImageOption(info->image_info,SvPV(sval,na));
1773           break;
1774         }
1775       if (LocaleCompare(attribute,"orientation") == 0)
1776         {
1777           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1778             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1779           if (sp < 0)
1780             {
1781               ThrowPerlException(exception,OptionError,
1782                 "UnrecognizedOrientationType",SvPV(sval,na));
1783               break;
1784             }
1785           if (info)
1786             info->image_info->orientation=(OrientationType) sp;
1787           for ( ; image; image=image->next)
1788             image->orientation=(OrientationType) sp;
1789           break;
1790         }
1791       if (info)
1792         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1793       for ( ; image; image=image->next)
1794         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1795       break;
1796     }
1797     case 'P':
1798     case 'p':
1799     {
1800       if (LocaleCompare(attribute,"page") == 0)
1801         {
1802           char
1803             *geometry;
1804
1805           geometry=GetPageGeometry(SvPV(sval,na));
1806           if (info)
1807             (void) CloneString(&info->image_info->page,geometry);
1808           for ( ; image; image=image->next)
1809             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1810           geometry=(char *) RelinquishMagickMemory(geometry);
1811           break;
1812         }
1813       if (LocaleNCompare(attribute,"pixel",5) == 0)
1814         {
1815           int
1816             items;
1817
1818           PixelInfo
1819             pixel;
1820
1821           register Quantum
1822             *q;
1823
1824           CacheView
1825             *image_view;
1826
1827           for ( ; image; image=image->next)
1828           {
1829             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1830               break;
1831             x=0;
1832             y=0;
1833             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1834             (void) items;
1835             image_view=AcquireVirtualCacheView(image,exception);
1836             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1837             if (q != (Quantum *) NULL)
1838               {
1839                 if ((strchr(SvPV(sval,na),',') == 0) ||
1840                     (strchr(SvPV(sval,na),')') != 0))
1841                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1842                     &pixel,exception);
1843                 else
1844                   {
1845                     GetPixelInfo(image,&pixel);
1846                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1847                     pixel.red=geometry_info.rho;
1848                     if ((flags & SigmaValue) != 0)
1849                       pixel.green=geometry_info.sigma;
1850                     if ((flags & XiValue) != 0)
1851                       pixel.blue=geometry_info.xi;
1852                     if ((flags & PsiValue) != 0)
1853                       pixel.alpha=geometry_info.psi;
1854                     if ((flags & ChiValue) != 0)
1855                       pixel.black=geometry_info.chi;
1856                   }
1857                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1858                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1859                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1860                 if (image->colorspace == CMYKColorspace)
1861                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1862                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1863                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1864               }
1865             image_view=DestroyCacheView(image_view);
1866           }
1867           break;
1868         }
1869       if (LocaleCompare(attribute,"pointsize") == 0)
1870         {
1871           if (info)
1872             {
1873               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1874               info->image_info->pointsize=geometry_info.rho;
1875             }
1876           break;
1877         }
1878       if (LocaleCompare(attribute,"preview") == 0)
1879         {
1880           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1881             SvPV(sval,na)) : SvIV(sval);
1882           if (sp < 0)
1883             {
1884               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1885                 SvPV(sval,na));
1886               break;
1887             }
1888           if (info)
1889             info->image_info->preview_type=(PreviewType) sp;
1890           break;
1891         }
1892       if (info)
1893         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1894       for ( ; image; image=image->next)
1895         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1896       break;
1897     }
1898     case 'Q':
1899     case 'q':
1900     {
1901       if (LocaleCompare(attribute,"quality") == 0)
1902         {
1903           if (info)
1904             info->image_info->quality=SvIV(sval);
1905           for ( ; image; image=image->next)
1906             image->quality=SvIV(sval);
1907           break;
1908         }
1909       if (info)
1910         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1911       for ( ; image; image=image->next)
1912         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1913       break;
1914     }
1915     case 'R':
1916     case 'r':
1917     {
1918       if (LocaleCompare(attribute,"read-mask") == 0)
1919         {
1920           Image
1921             *mask;
1922
1923           mask=(Image *) NULL;
1924           if (SvPOK(sval))
1925             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1926           for ( ; image; image=image->next)
1927             SetImageMask(image,ReadPixelMask,mask,exception);
1928           break;
1929         }
1930       if (LocaleCompare(attribute,"red-primary") == 0)
1931         {
1932           for ( ; image; image=image->next)
1933           {
1934             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1935             image->chromaticity.red_primary.x=geometry_info.rho;
1936             image->chromaticity.red_primary.y=geometry_info.sigma;
1937             if ((flags & SigmaValue) == 0)
1938               image->chromaticity.red_primary.y=
1939                 image->chromaticity.red_primary.x;
1940           }
1941           break;
1942         }
1943       if (LocaleCompare(attribute,"render") == 0)
1944         {
1945           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1946             SvPV(sval,na)) : SvIV(sval);
1947           if (sp < 0)
1948             {
1949               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1950                 SvPV(sval,na));
1951               break;
1952             }
1953          for ( ; image; image=image->next)
1954            image->rendering_intent=(RenderingIntent) sp;
1955          break;
1956        }
1957       if (LocaleCompare(attribute,"repage") == 0)
1958         {
1959           RectangleInfo
1960             geometry;
1961
1962           for ( ; image; image=image->next)
1963           {
1964             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1965             if ((flags & WidthValue) != 0)
1966               {
1967                 if ((flags & HeightValue) == 0)
1968                   geometry.height=geometry.width;
1969                 image->page.width=geometry.width;
1970                 image->page.height=geometry.height;
1971               }
1972             if ((flags & AspectValue) != 0)
1973               {
1974                 if ((flags & XValue) != 0)
1975                   image->page.x+=geometry.x;
1976                 if ((flags & YValue) != 0)
1977                   image->page.y+=geometry.y;
1978               }
1979             else
1980               {
1981                 if ((flags & XValue) != 0)
1982                   {
1983                     image->page.x=geometry.x;
1984                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1985                       image->page.width=image->columns+geometry.x;
1986                   }
1987                 if ((flags & YValue) != 0)
1988                   {
1989                     image->page.y=geometry.y;
1990                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1991                       image->page.height=image->rows+geometry.y;
1992                   }
1993               }
1994           }
1995           break;
1996         }
1997       if (info)
1998         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1999       for ( ; image; image=image->next)
2000         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2001       break;
2002     }
2003     case 'S':
2004     case 's':
2005     {
2006       if (LocaleCompare(attribute,"sampling-factor") == 0)
2007         {
2008           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2009             {
2010               ThrowPerlException(exception,OptionError,"MissingGeometry",
2011                 SvPV(sval,na));
2012               break;
2013             }
2014           if (info)
2015             (void) CloneString(&info->image_info->sampling_factor,
2016               SvPV(sval,na));
2017           break;
2018         }
2019       if (LocaleCompare(attribute,"scene") == 0)
2020         {
2021           for ( ; image; image=image->next)
2022             image->scene=SvIV(sval);
2023           break;
2024         }
2025       if (LocaleCompare(attribute,"server") == 0)
2026         goto display;
2027       if (LocaleCompare(attribute,"size") == 0)
2028         {
2029           if (info)
2030             {
2031               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2032                 {
2033                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2034                     SvPV(sval,na));
2035                   break;
2036                 }
2037               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2038             }
2039           break;
2040         }
2041       if (LocaleCompare(attribute,"stroke") == 0)
2042         {
2043           if (info)
2044             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2045           break;
2046         }
2047       if (info)
2048         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2049       for ( ; image; image=image->next)
2050         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2051       break;
2052     }
2053     case 'T':
2054     case 't':
2055     {
2056       if (LocaleCompare(attribute,"texture") == 0)
2057         {
2058           if (info)
2059             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2060           break;
2061         }
2062       if (LocaleCompare(attribute,"thread-limit") == 0)
2063         {
2064           MagickSizeType
2065             limit;
2066
2067           limit=MagickResourceInfinity;
2068           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2069             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2070               100.0);
2071           (void) SetMagickResourceLimit(ThreadResource,limit);
2072           break;
2073         }
2074       if (LocaleCompare(attribute,"tile-offset") == 0)
2075         {
2076           char
2077             *geometry;
2078
2079           geometry=GetPageGeometry(SvPV(sval,na));
2080           if (info)
2081             (void) CloneString(&info->image_info->page,geometry);
2082           for ( ; image; image=image->next)
2083             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2084               exception);
2085           geometry=(char *) RelinquishMagickMemory(geometry);
2086           break;
2087         }
2088       if (LocaleCompare(attribute,"time-limit") == 0)
2089         {
2090           MagickSizeType
2091             limit;
2092
2093           limit=MagickResourceInfinity;
2094           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2095             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2096               100.0);
2097           (void) SetMagickResourceLimit(TimeResource,limit);
2098           break;
2099         }
2100       if (LocaleCompare(attribute,"transparent-color") == 0)
2101         {
2102           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2103             exception);
2104           if (info)
2105             info->image_info->transparent_color=target_color;
2106           for ( ; image; image=image->next)
2107             image->transparent_color=target_color;
2108           break;
2109         }
2110       if (LocaleCompare(attribute,"type") == 0)
2111         {
2112           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2113             SvPV(sval,na)) : SvIV(sval);
2114           if (sp < 0)
2115             {
2116               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2117                 SvPV(sval,na));
2118               break;
2119             }
2120           if (info)
2121             info->image_info->type=(ImageType) sp;
2122           for ( ; image; image=image->next)
2123             SetImageType(image,(ImageType) sp,exception);
2124           break;
2125         }
2126       if (info)
2127         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2128       for ( ; image; image=image->next)
2129         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2130       break;
2131     }
2132     case 'U':
2133     case 'u':
2134     {
2135       if (LocaleCompare(attribute,"units") == 0)
2136         {
2137           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2138             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2139           if (sp < 0)
2140             {
2141               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2142                 SvPV(sval,na));
2143               break;
2144             }
2145           if (info)
2146             info->image_info->units=(ResolutionType) sp;
2147           for ( ; image; image=image->next)
2148           {
2149             ResolutionType
2150               units;
2151
2152             units=(ResolutionType) sp;
2153             if (image->units != units)
2154               switch (image->units)
2155               {
2156                 case UndefinedResolution:
2157                 case PixelsPerInchResolution:
2158                 {
2159                   if (units == PixelsPerCentimeterResolution)
2160                     {
2161                       image->resolution.x*=2.54;
2162                       image->resolution.y*=2.54;
2163                     }
2164                   break;
2165                 }
2166                 case PixelsPerCentimeterResolution:
2167                 {
2168                   if (units == PixelsPerInchResolution)
2169                     {
2170                       image->resolution.x/=2.54;
2171                       image->resolution.y/=2.54;
2172                     }
2173                   break;
2174                 }
2175               }
2176             image->units=units;
2177           }
2178           break;
2179         }
2180       if (info)
2181         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2182       for ( ; image; image=image->next)
2183         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2184       break;
2185     }
2186     case 'V':
2187     case 'v':
2188     {
2189       if (LocaleCompare(attribute,"verbose") == 0)
2190         {
2191           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2192             SvPV(sval,na)) : SvIV(sval);
2193           if (sp < 0)
2194             {
2195               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2196                 SvPV(sval,na));
2197               break;
2198             }
2199           if (info)
2200             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2201           break;
2202         }
2203       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2204         {
2205           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2206             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2207           if (sp < 0)
2208             {
2209               ThrowPerlException(exception,OptionError,
2210                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2211               break;
2212             }
2213           for ( ; image; image=image->next)
2214             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2215           break;
2216         }
2217       if (info)
2218         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2219       for ( ; image; image=image->next)
2220         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2221       break;
2222     }
2223     case 'W':
2224     case 'w':
2225     {
2226       if (LocaleCompare(attribute,"white-point") == 0)
2227         {
2228           for ( ; image; image=image->next)
2229           {
2230             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2231             image->chromaticity.white_point.x=geometry_info.rho;
2232             image->chromaticity.white_point.y=geometry_info.sigma;
2233             if ((flags & SigmaValue) == 0)
2234               image->chromaticity.white_point.y=
2235                 image->chromaticity.white_point.x;
2236           }
2237           break;
2238         }
2239       if (LocaleCompare(attribute,"write-mask") == 0)
2240         {
2241           Image
2242             *mask;
2243
2244           mask=(Image *) NULL;
2245           if (SvPOK(sval))
2246             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2247           for ( ; image; image=image->next)
2248             SetImageMask(image,WritePixelMask,mask,exception);
2249           break;
2250         }
2251       if (info)
2252         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2253       for ( ; image; image=image->next)
2254         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2255       break;
2256     }
2257     default:
2258     {
2259       if (info)
2260         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2261       for ( ; image; image=image->next)
2262         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2263       break;
2264     }
2265   }
2266 }
2267 \f
2268 /*
2269 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2270 %                                                                             %
2271 %                                                                             %
2272 %                                                                             %
2273 %   S e t u p L i s t                                                         %
2274 %                                                                             %
2275 %                                                                             %
2276 %                                                                             %
2277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278 %
2279 %  Method SetupList returns the list of all the images linked by their
2280 %  image->next and image->previous link lists for use with ImageMagick.  If
2281 %  info is non-NULL, an info structure is returned in *info.  If
2282 %  reference_vector is non-NULL,an array of SV* are returned in
2283 %  *reference_vector.  Reference_vector is used when the images are going to be
2284 %  replaced with new Image*'s.
2285 %
2286 %  The format of the SetupList routine is:
2287 %
2288 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2289 %        SV ***reference_vector,ExceptionInfo *exception)
2290 %
2291 %  A description of each parameter follows:
2292 %
2293 %    o list: a list of strings.
2294 %
2295 %    o string: a character string.
2296 %
2297 %    o exception: Return any errors or warnings in this structure.
2298 %
2299 */
2300 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2301   SV ***reference_vector,ExceptionInfo *exception)
2302 {
2303   Image
2304     *image;
2305
2306   ssize_t
2307     current,
2308     last;
2309
2310   if (reference_vector)
2311     *reference_vector=NULL;
2312   if (info)
2313     *info=NULL;
2314   current=0;
2315   last=0;
2316   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2317   if (info && (SvTYPE(reference) == SVt_PVAV))
2318     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2319       exception);
2320   return(image);
2321 }
2322 \f
2323 /*
2324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2325 %                                                                             %
2326 %                                                                             %
2327 %                                                                             %
2328 %   s t r E Q c a s e                                                         %
2329 %                                                                             %
2330 %                                                                             %
2331 %                                                                             %
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 %
2334 %  strEQcase() compares two strings and returns 0 if they are the
2335 %  same or if the second string runs out first.  The comparison is case
2336 %  insensitive.
2337 %
2338 %  The format of the strEQcase routine is:
2339 %
2340 %      ssize_t strEQcase(const char *p,const char *q)
2341 %
2342 %  A description of each parameter follows:
2343 %
2344 %    o p: a character string.
2345 %
2346 %    o q: a character string.
2347 %
2348 %
2349 */
2350 static ssize_t strEQcase(const char *p,const char *q)
2351 {
2352   char
2353     c;
2354
2355   register ssize_t
2356     i;
2357
2358   for (i=0 ; (c=(*q)) != 0; i++)
2359   {
2360     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2361         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2362       return(0);
2363     p++;
2364     q++;
2365   }
2366   return(((*q == 0) && (*p == 0)) ? i : 0);
2367 }
2368 \f
2369 /*
2370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2371 %                                                                             %
2372 %                                                                             %
2373 %                                                                             %
2374 %   I m a g e : : M a g i c k                                                 %
2375 %                                                                             %
2376 %                                                                             %
2377 %                                                                             %
2378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2379 %
2380 %
2381 */
2382 MODULE = Image::Magick PACKAGE = Image::Magick
2383
2384 PROTOTYPES: ENABLE
2385
2386 BOOT:
2387   MagickCoreGenesis("PerlMagick",MagickFalse);
2388   SetWarningHandler(NULL);
2389   SetErrorHandler(NULL);
2390   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2391     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2392
2393 void
2394 UNLOAD()
2395   PPCODE:
2396   {
2397     if (magick_registry != (SplayTreeInfo *) NULL)
2398       magick_registry=DestroySplayTree(magick_registry);
2399     MagickCoreTerminus();
2400   }
2401
2402 double
2403 constant(name,argument)
2404   char *name
2405   ssize_t argument
2406 \f
2407 #
2408 ###############################################################################
2409 #                                                                             #
2410 #                                                                             #
2411 #                                                                             #
2412 #   A n i m a t e                                                             #
2413 #                                                                             #
2414 #                                                                             #
2415 #                                                                             #
2416 ###############################################################################
2417 #
2418 #
2419 void
2420 Animate(ref,...)
2421   Image::Magick ref=NO_INIT
2422   ALIAS:
2423     AnimateImage  = 1
2424     animate       = 2
2425     animateimage  = 3
2426   PPCODE:
2427   {
2428     ExceptionInfo
2429       *exception;
2430
2431     Image
2432       *image;
2433
2434     register ssize_t
2435       i;
2436
2437     struct PackageInfo
2438       *info,
2439       *package_info;
2440
2441     SV
2442       *perl_exception,
2443       *reference;
2444
2445     PERL_UNUSED_VAR(ref);
2446     PERL_UNUSED_VAR(ix);
2447     exception=AcquireExceptionInfo();
2448     perl_exception=newSVpv("",0);
2449     package_info=(struct PackageInfo *) NULL;
2450     if (sv_isobject(ST(0)) == 0)
2451       {
2452         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2453           PackageName);
2454         goto PerlException;
2455       }
2456     reference=SvRV(ST(0));
2457     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2458     if (image == (Image *) NULL)
2459       {
2460         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2461           PackageName);
2462         goto PerlException;
2463       }
2464     package_info=ClonePackageInfo(info,exception);
2465     if (items == 2)
2466       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2467     else
2468       if (items > 2)
2469         for (i=2; i < items; i+=2)
2470           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2471             exception);
2472     (void) AnimateImages(package_info->image_info,image,exception);
2473     (void) CatchImageException(image);
2474
2475   PerlException:
2476     if (package_info != (struct PackageInfo *) NULL)
2477       DestroyPackageInfo(package_info);
2478     InheritPerlException(exception,perl_exception);
2479     exception=DestroyExceptionInfo(exception);
2480     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2481     SvPOK_on(perl_exception);
2482     ST(0)=sv_2mortal(perl_exception);
2483     XSRETURN(1);
2484   }
2485 \f
2486 #
2487 ###############################################################################
2488 #                                                                             #
2489 #                                                                             #
2490 #                                                                             #
2491 #   A p p e n d                                                               #
2492 #                                                                             #
2493 #                                                                             #
2494 #                                                                             #
2495 ###############################################################################
2496 #
2497 #
2498 void
2499 Append(ref,...)
2500   Image::Magick ref=NO_INIT
2501   ALIAS:
2502     AppendImage  = 1
2503     append       = 2
2504     appendimage  = 3
2505   PPCODE:
2506   {
2507     AV
2508       *av;
2509
2510     char
2511       *attribute;
2512
2513     ExceptionInfo
2514       *exception;
2515
2516     HV
2517       *hv;
2518
2519     Image
2520       *image;
2521
2522     register ssize_t
2523       i;
2524
2525     ssize_t
2526       stack;
2527
2528     struct PackageInfo
2529       *info;
2530
2531     SV
2532       *av_reference,
2533       *perl_exception,
2534       *reference,
2535       *rv,
2536       *sv;
2537
2538     PERL_UNUSED_VAR(ref);
2539     PERL_UNUSED_VAR(ix);
2540     exception=AcquireExceptionInfo();
2541     perl_exception=newSVpv("",0);
2542     sv=NULL;
2543     attribute=NULL;
2544     av=NULL;
2545     if (sv_isobject(ST(0)) == 0)
2546       {
2547         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2548           PackageName);
2549         goto PerlException;
2550       }
2551     reference=SvRV(ST(0));
2552     hv=SvSTASH(reference);
2553     av=newAV();
2554     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2555     SvREFCNT_dec(av);
2556     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2557     if (image == (Image *) NULL)
2558       {
2559         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2560           PackageName);
2561         goto PerlException;
2562       }
2563     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2564     /*
2565       Get options.
2566     */
2567     stack=MagickTrue;
2568     for (i=2; i < items; i+=2)
2569     {
2570       attribute=(char *) SvPV(ST(i-1),na);
2571       switch (*attribute)
2572       {
2573         case 'S':
2574         case 's':
2575         {
2576           if (LocaleCompare(attribute,"stack") == 0)
2577             {
2578               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2579                 SvPV(ST(i),na));
2580               if (stack < 0)
2581                 {
2582                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2583                     SvPV(ST(i),na));
2584                   return;
2585                 }
2586               break;
2587             }
2588           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2589             attribute);
2590           break;
2591         }
2592         default:
2593         {
2594           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2595             attribute);
2596           break;
2597         }
2598       }
2599     }
2600     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2601     if (image == (Image *) NULL)
2602       goto PerlException;
2603     for ( ; image; image=image->next)
2604     {
2605       AddImageToRegistry(sv,image);
2606       rv=newRV(sv);
2607       av_push(av,sv_bless(rv,hv));
2608       SvREFCNT_dec(sv);
2609     }
2610     exception=DestroyExceptionInfo(exception);
2611     ST(0)=av_reference;
2612     SvREFCNT_dec(perl_exception);
2613     XSRETURN(1);
2614
2615   PerlException:
2616     InheritPerlException(exception,perl_exception);
2617     exception=DestroyExceptionInfo(exception);
2618     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2619     SvPOK_on(perl_exception);
2620     ST(0)=sv_2mortal(perl_exception);
2621     XSRETURN(1);
2622   }
2623 \f
2624 #
2625 ###############################################################################
2626 #                                                                             #
2627 #                                                                             #
2628 #                                                                             #
2629 #   A v e r a g e                                                             #
2630 #                                                                             #
2631 #                                                                             #
2632 #                                                                             #
2633 ###############################################################################
2634 #
2635 #
2636 void
2637 Average(ref)
2638   Image::Magick ref=NO_INIT
2639   ALIAS:
2640     AverageImage   = 1
2641     average        = 2
2642     averageimage   = 3
2643   PPCODE:
2644   {
2645     AV
2646       *av;
2647
2648     char
2649       *p;
2650
2651     ExceptionInfo
2652       *exception;
2653
2654     HV
2655       *hv;
2656
2657     Image
2658       *image;
2659
2660     struct PackageInfo
2661       *info;
2662
2663     SV
2664       *perl_exception,
2665       *reference,
2666       *rv,
2667       *sv;
2668
2669     PERL_UNUSED_VAR(ref);
2670     PERL_UNUSED_VAR(ix);
2671     exception=AcquireExceptionInfo();
2672     perl_exception=newSVpv("",0);
2673     sv=NULL;
2674     if (sv_isobject(ST(0)) == 0)
2675       {
2676         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2677           PackageName);
2678         goto PerlException;
2679       }
2680     reference=SvRV(ST(0));
2681     hv=SvSTASH(reference);
2682     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2683     if (image == (Image *) NULL)
2684       {
2685         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2686           PackageName);
2687         goto PerlException;
2688       }
2689     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2690     if (image == (Image *) NULL)
2691       goto PerlException;
2692     /*
2693       Create blessed Perl array for the returned image.
2694     */
2695     av=newAV();
2696     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2697     SvREFCNT_dec(av);
2698     AddImageToRegistry(sv,image);
2699     rv=newRV(sv);
2700     av_push(av,sv_bless(rv,hv));
2701     SvREFCNT_dec(sv);
2702     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2703     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2704       "average-%.*s",(int) (MagickPathExtent-9),
2705       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2706     (void) CopyMagickString(image->filename,info->image_info->filename,
2707       MagickPathExtent);
2708     SetImageInfo(info->image_info,0,exception);
2709     exception=DestroyExceptionInfo(exception);
2710     SvREFCNT_dec(perl_exception);
2711     XSRETURN(1);
2712
2713   PerlException:
2714     InheritPerlException(exception,perl_exception);
2715     exception=DestroyExceptionInfo(exception);
2716     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2717     SvPOK_on(perl_exception);
2718     ST(0)=sv_2mortal(perl_exception);
2719     XSRETURN(1);
2720   }
2721 \f
2722 #
2723 ###############################################################################
2724 #                                                                             #
2725 #                                                                             #
2726 #                                                                             #
2727 #   B l o b T o I m a g e                                                     #
2728 #                                                                             #
2729 #                                                                             #
2730 #                                                                             #
2731 ###############################################################################
2732 #
2733 #
2734 void
2735 BlobToImage(ref,...)
2736   Image::Magick ref=NO_INIT
2737   ALIAS:
2738     BlobToImage  = 1
2739     blobtoimage  = 2
2740     blobto       = 3
2741   PPCODE:
2742   {
2743     AV
2744       *av;
2745
2746     char
2747       **keep,
2748       **list;
2749
2750     ExceptionInfo
2751       *exception;
2752
2753     HV
2754       *hv;
2755
2756     Image
2757       *image;
2758
2759     register char
2760       **p;
2761
2762     register ssize_t
2763       i;
2764
2765     ssize_t
2766       ac,
2767       n,
2768       number_images;
2769
2770     STRLEN
2771       *length;
2772
2773     struct PackageInfo
2774       *info;
2775
2776     SV
2777       *perl_exception,
2778       *reference,
2779       *rv,
2780       *sv;
2781
2782     PERL_UNUSED_VAR(ref);
2783     PERL_UNUSED_VAR(ix);
2784     exception=AcquireExceptionInfo();
2785     perl_exception=newSVpv("",0);
2786     sv=NULL;
2787     number_images=0;
2788     ac=(items < 2) ? 1 : items-1;
2789     length=(STRLEN *) NULL;
2790     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2791     if (list == (char **) NULL)
2792       {
2793         ThrowPerlException(exception,ResourceLimitError,
2794           "MemoryAllocationFailed",PackageName);
2795         goto PerlException;
2796       }
2797     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2798     if (length == (STRLEN *) NULL)
2799       {
2800         ThrowPerlException(exception,ResourceLimitError,
2801           "MemoryAllocationFailed",PackageName);
2802         goto PerlException;
2803       }
2804     if (sv_isobject(ST(0)) == 0)
2805       {
2806         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2807           PackageName);
2808         goto PerlException;
2809       }
2810     reference=SvRV(ST(0));
2811     hv=SvSTASH(reference);
2812     if (SvTYPE(reference) != SVt_PVAV)
2813       {
2814         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2815           PackageName);
2816         goto PerlException;
2817       }
2818     av=(AV *) reference;
2819     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2820       exception);
2821     n=1;
2822     if (items <= 1)
2823       {
2824         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2825         goto PerlException;
2826       }
2827     for (n=0, i=0; i < ac; i++)
2828     {
2829       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2830       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2831         {
2832           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2833           continue;
2834         }
2835       n++;
2836     }
2837     list[n]=(char *) NULL;
2838     keep=list;
2839     for (i=number_images=0; i < n; i++)
2840     {
2841       image=BlobToImage(info->image_info,list[i],length[i],exception);
2842       if (image == (Image *) NULL)
2843         break;
2844       for ( ; image; image=image->next)
2845       {
2846         AddImageToRegistry(sv,image);
2847         rv=newRV(sv);
2848         av_push(av,sv_bless(rv,hv));
2849         SvREFCNT_dec(sv);
2850         number_images++;
2851       }
2852     }
2853     /*
2854       Free resources.
2855     */
2856     for (i=0; i < n; i++)
2857       if (list[i] != (char *) NULL)
2858         for (p=keep; list[i] != *p++; )
2859           if (*p == (char *) NULL)
2860             {
2861               list[i]=(char *) RelinquishMagickMemory(list[i]);
2862               break;
2863             }
2864
2865   PerlException:
2866     if (list)
2867       list=(char **) RelinquishMagickMemory(list);
2868     if (length)
2869       length=(STRLEN *) RelinquishMagickMemory(length);
2870     InheritPerlException(exception,perl_exception);
2871     exception=DestroyExceptionInfo(exception);
2872     sv_setiv(perl_exception,(IV) number_images);
2873     SvPOK_on(perl_exception);
2874     ST(0)=sv_2mortal(perl_exception);
2875     XSRETURN(1);
2876   }
2877 \f
2878 #
2879 ###############################################################################
2880 #                                                                             #
2881 #                                                                             #
2882 #                                                                             #
2883 #   C h a n n e l F x                                                         #
2884 #                                                                             #
2885 #                                                                             #
2886 #                                                                             #
2887 ###############################################################################
2888 #
2889 #
2890 void
2891 ChannelFx(ref,...)
2892   Image::Magick ref=NO_INIT
2893   ALIAS:
2894     ChannelFxImage  = 1
2895     channelfx       = 2
2896     channelfximage  = 3
2897   PPCODE:
2898   {
2899     AV
2900       *av;
2901
2902     char
2903       *attribute,
2904       expression[MagickPathExtent];
2905
2906     ChannelType
2907       channel,
2908       channel_mask;
2909
2910     ExceptionInfo
2911       *exception;
2912
2913     HV
2914       *hv;
2915
2916     Image
2917       *image;
2918
2919     register ssize_t
2920       i;
2921
2922     struct PackageInfo
2923       *info;
2924
2925     SV
2926       *av_reference,
2927       *perl_exception,
2928       *reference,
2929       *rv,
2930       *sv;
2931
2932     PERL_UNUSED_VAR(ref);
2933     PERL_UNUSED_VAR(ix);
2934     exception=AcquireExceptionInfo();
2935     perl_exception=newSVpv("",0);
2936     sv=NULL;
2937     attribute=NULL;
2938     av=NULL;
2939     if (sv_isobject(ST(0)) == 0)
2940       {
2941         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2942           PackageName);
2943         goto PerlException;
2944       }
2945     reference=SvRV(ST(0));
2946     hv=SvSTASH(reference);
2947     av=newAV();
2948     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2949     SvREFCNT_dec(av);
2950     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2951     if (image == (Image *) NULL)
2952       {
2953         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2954           PackageName);
2955         goto PerlException;
2956       }
2957     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2958     /*
2959       Get options.
2960     */
2961     channel=DefaultChannels;
2962     (void) CopyMagickString(expression,"u",MagickPathExtent);
2963     if (items == 2)
2964       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2965     else
2966       for (i=2; i < items; i+=2)
2967       {
2968         attribute=(char *) SvPV(ST(i-1),na);
2969         switch (*attribute)
2970         {
2971           case 'C':
2972           case 'c':
2973           {
2974             if (LocaleCompare(attribute,"channel") == 0)
2975               {
2976                 ssize_t
2977                   option;
2978
2979                 option=ParseChannelOption(SvPV(ST(i),na));
2980                 if (option < 0)
2981                   {
2982                     ThrowPerlException(exception,OptionError,
2983                       "UnrecognizedType",SvPV(ST(i),na));
2984                     return;
2985                   }
2986                 channel=(ChannelType) option;
2987                 break;
2988               }
2989             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2990               attribute);
2991             break;
2992           }
2993           case 'E':
2994           case 'e':
2995           {
2996             if (LocaleCompare(attribute,"expression") == 0)
2997               {
2998                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2999                   MagickPathExtent);
3000                 break;
3001               }
3002             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3003               attribute);
3004             break;
3005           }
3006           default:
3007           {
3008             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3009               attribute);
3010             break;
3011           }
3012         }
3013       }
3014     channel_mask=SetImageChannelMask(image,channel);
3015     image=ChannelFxImage(image,expression,exception);
3016     if (image != (Image *) NULL)
3017       (void) SetImageChannelMask(image,channel_mask);
3018     if (image == (Image *) NULL)
3019       goto PerlException;
3020     for ( ; image; image=image->next)
3021     {
3022       AddImageToRegistry(sv,image);
3023       rv=newRV(sv);
3024       av_push(av,sv_bless(rv,hv));
3025       SvREFCNT_dec(sv);
3026     }
3027     exception=DestroyExceptionInfo(exception);
3028     ST(0)=av_reference;
3029     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3030     XSRETURN(1);
3031
3032   PerlException:
3033     InheritPerlException(exception,perl_exception);
3034     exception=DestroyExceptionInfo(exception);
3035     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3036     SvPOK_on(perl_exception);
3037     ST(0)=sv_2mortal(perl_exception);
3038     XSRETURN(1);
3039   }
3040 \f
3041 #
3042 ###############################################################################
3043 #                                                                             #
3044 #                                                                             #
3045 #                                                                             #
3046 #   C l o n e                                                                 #
3047 #                                                                             #
3048 #                                                                             #
3049 #                                                                             #
3050 ###############################################################################
3051 #
3052 #
3053 void
3054 Clone(ref)
3055   Image::Magick ref=NO_INIT
3056   ALIAS:
3057     CopyImage   = 1
3058     copy        = 2
3059     copyimage   = 3
3060     CloneImage  = 4
3061     clone       = 5
3062     cloneimage  = 6
3063     Clone       = 7
3064   PPCODE:
3065   {
3066     AV
3067       *av;
3068
3069     ExceptionInfo
3070       *exception;
3071
3072     HV
3073       *hv;
3074
3075     Image
3076       *clone,
3077       *image;
3078
3079     struct PackageInfo
3080       *info;
3081
3082     SV
3083       *perl_exception,
3084       *reference,
3085       *rv,
3086       *sv;
3087
3088     PERL_UNUSED_VAR(ref);
3089     PERL_UNUSED_VAR(ix);
3090     exception=AcquireExceptionInfo();
3091     perl_exception=newSVpv("",0);
3092     sv=NULL;
3093     if (sv_isobject(ST(0)) == 0)
3094       {
3095         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3096           PackageName);
3097         goto PerlException;
3098       }
3099     reference=SvRV(ST(0));
3100     hv=SvSTASH(reference);
3101     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3102     if (image == (Image *) NULL)
3103       {
3104         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3105           PackageName);
3106         goto PerlException;
3107       }
3108     /*
3109       Create blessed Perl array for the returned image.
3110     */
3111     av=newAV();
3112     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3113     SvREFCNT_dec(av);
3114     for ( ; image; image=image->next)
3115     {
3116       clone=CloneImage(image,0,0,MagickTrue,exception);
3117       if (clone == (Image *) NULL)
3118         break;
3119       AddImageToRegistry(sv,clone);
3120       rv=newRV(sv);
3121       av_push(av,sv_bless(rv,hv));
3122       SvREFCNT_dec(sv);
3123     }
3124     exception=DestroyExceptionInfo(exception);
3125     SvREFCNT_dec(perl_exception);
3126     XSRETURN(1);
3127
3128   PerlException:
3129     InheritPerlException(exception,perl_exception);
3130     exception=DestroyExceptionInfo(exception);
3131     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3132     SvPOK_on(perl_exception);
3133     ST(0)=sv_2mortal(perl_exception);
3134     XSRETURN(1);
3135   }
3136 \f
3137 #
3138 ###############################################################################
3139 #                                                                             #
3140 #                                                                             #
3141 #                                                                             #
3142 #   C L O N E                                                                 #
3143 #                                                                             #
3144 #                                                                             #
3145 #                                                                             #
3146 ###############################################################################
3147 #
3148 #
3149 void
3150 CLONE(ref,...)
3151   SV *ref;
3152   CODE:
3153   {
3154     PERL_UNUSED_VAR(ref);
3155     if (magick_registry != (SplayTreeInfo *) NULL)
3156       {
3157         register Image
3158           *p;
3159
3160         ResetSplayTreeIterator(magick_registry);
3161         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3162         while (p != (Image *) NULL)
3163         {
3164           ReferenceImage(p);
3165           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3166         }
3167       }
3168   }
3169 \f
3170 #
3171 ###############################################################################
3172 #                                                                             #
3173 #                                                                             #
3174 #                                                                             #
3175 #   C o a l e s c e                                                           #
3176 #                                                                             #
3177 #                                                                             #
3178 #                                                                             #
3179 ###############################################################################
3180 #
3181 #
3182 void
3183 Coalesce(ref)
3184   Image::Magick ref=NO_INIT
3185   ALIAS:
3186     CoalesceImage   = 1
3187     coalesce        = 2
3188     coalesceimage   = 3
3189   PPCODE:
3190   {
3191     AV
3192       *av;
3193
3194     ExceptionInfo
3195       *exception;
3196
3197     HV
3198       *hv;
3199
3200     Image
3201       *image;
3202
3203     struct PackageInfo
3204       *info;
3205
3206     SV
3207       *av_reference,
3208       *perl_exception,
3209       *reference,
3210       *rv,
3211       *sv;
3212
3213     PERL_UNUSED_VAR(ref);
3214     PERL_UNUSED_VAR(ix);
3215     exception=AcquireExceptionInfo();
3216     perl_exception=newSVpv("",0);
3217     sv=NULL;
3218     if (sv_isobject(ST(0)) == 0)
3219       {
3220         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3221           PackageName);
3222         goto PerlException;
3223       }
3224     reference=SvRV(ST(0));
3225     hv=SvSTASH(reference);
3226     av=newAV();
3227     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3228     SvREFCNT_dec(av);
3229     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3230     if (image == (Image *) NULL)
3231       {
3232         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3233           PackageName);
3234         goto PerlException;
3235       }
3236     image=CoalesceImages(image,exception);
3237     if (image == (Image *) NULL)
3238       goto PerlException;
3239     for ( ; image; image=image->next)
3240     {
3241       AddImageToRegistry(sv,image);
3242       rv=newRV(sv);
3243       av_push(av,sv_bless(rv,hv));
3244       SvREFCNT_dec(sv);
3245     }
3246     exception=DestroyExceptionInfo(exception);
3247     ST(0)=av_reference;
3248     SvREFCNT_dec(perl_exception);
3249     XSRETURN(1);
3250
3251   PerlException:
3252     InheritPerlException(exception,perl_exception);
3253     exception=DestroyExceptionInfo(exception);
3254     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3255     SvPOK_on(perl_exception);
3256     ST(0)=sv_2mortal(perl_exception);
3257     XSRETURN(1);
3258   }
3259 \f
3260 #
3261 ###############################################################################
3262 #                                                                             #
3263 #                                                                             #
3264 #                                                                             #
3265 #   C o m p a r e                                                             #
3266 #                                                                             #
3267 #                                                                             #
3268 #                                                                             #
3269 ###############################################################################
3270 #
3271 #
3272 void
3273 Compare(ref,...)
3274   Image::Magick ref=NO_INIT
3275   ALIAS:
3276     CompareImages = 1
3277     compare      = 2
3278     compareimage = 3
3279   PPCODE:
3280   {
3281     AV
3282       *av;
3283
3284     char
3285       *attribute;
3286
3287     double
3288       distortion;
3289
3290     ExceptionInfo
3291       *exception;
3292
3293     HV
3294       *hv;
3295
3296     Image
3297       *difference_image,
3298       *image,
3299       *reconstruct_image;
3300
3301     MetricType
3302       metric;
3303
3304     register ssize_t
3305       i;
3306
3307     ssize_t
3308       option;
3309
3310     struct PackageInfo
3311       *info;
3312
3313     SV
3314       *av_reference,
3315       *perl_exception,
3316       *reference,
3317       *rv,
3318       *sv;
3319
3320     PERL_UNUSED_VAR(ref);
3321     PERL_UNUSED_VAR(ix);
3322     exception=AcquireExceptionInfo();
3323     perl_exception=newSVpv("",0);
3324     sv=NULL;
3325     av=NULL;
3326     attribute=NULL;
3327     if (sv_isobject(ST(0)) == 0)
3328       {
3329         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3330           PackageName);
3331         goto PerlException;
3332       }
3333     reference=SvRV(ST(0));
3334     hv=SvSTASH(reference);
3335     av=newAV();
3336     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3337     SvREFCNT_dec(av);
3338     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3339     if (image == (Image *) NULL)
3340       {
3341         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3342           PackageName);
3343         goto PerlException;
3344       }
3345     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3346     /*
3347       Get attribute.
3348     */
3349     reconstruct_image=image;
3350     metric=RootMeanSquaredErrorMetric;
3351     for (i=2; i < items; i+=2)
3352     {
3353       attribute=(char *) SvPV(ST(i-1),na);
3354       switch (*attribute)
3355       {
3356         case 'C':
3357         case 'c':
3358         {
3359           if (LocaleCompare(attribute,"channel") == 0)
3360             {
3361               ssize_t
3362                 option;
3363
3364               option=ParseChannelOption(SvPV(ST(i),na));
3365               if (option < 0)
3366                 {
3367                   ThrowPerlException(exception,OptionError,
3368                     "UnrecognizedType",SvPV(ST(i),na));
3369                   return;
3370                 }
3371               (void) SetPixelChannelMask(image,(ChannelType) option);
3372               break;
3373             }
3374           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3375             attribute);
3376           break;
3377         }
3378         case 'F':
3379         case 'f':
3380         {
3381           if (LocaleCompare(attribute,"fuzz") == 0)
3382             {
3383               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3384               break;
3385             }
3386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3387             attribute);
3388           break;
3389         }
3390         case 'I':
3391         case 'i':
3392         {
3393           if (LocaleCompare(attribute,"image") == 0)
3394             {
3395               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3396                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3397               break;
3398             }
3399           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3400             attribute);
3401           break;
3402         }
3403         case 'M':
3404         case 'm':
3405         {
3406           if (LocaleCompare(attribute,"metric") == 0)
3407             {
3408               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3409                 SvPV(ST(i),na));
3410               if (option < 0)
3411                 {
3412                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3413                     SvPV(ST(i),na));
3414                   break;
3415                 }
3416               metric=(MetricType) option;
3417               break;
3418             }
3419           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3420             attribute);
3421           break;
3422         }
3423         default:
3424         {
3425           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3426             attribute);
3427           break;
3428         }
3429       }
3430     }
3431     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3432       exception);
3433     if (difference_image != (Image *) NULL)
3434       {
3435         difference_image->error.mean_error_per_pixel=distortion;
3436         AddImageToRegistry(sv,difference_image);
3437         rv=newRV(sv);
3438         av_push(av,sv_bless(rv,hv));
3439         SvREFCNT_dec(sv);
3440       }
3441     exception=DestroyExceptionInfo(exception);
3442     ST(0)=av_reference;
3443     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3444     XSRETURN(1);
3445
3446   PerlException:
3447     InheritPerlException(exception,perl_exception);
3448     exception=DestroyExceptionInfo(exception);
3449     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3450     SvPOK_on(perl_exception);
3451     ST(0)=sv_2mortal(perl_exception);
3452     XSRETURN(1);
3453   }
3454 \f
3455 #
3456 ###############################################################################
3457 #                                                                             #
3458 #                                                                             #
3459 #                                                                             #
3460 #   C o m p l e x I m a g e s                                                 #
3461 #                                                                             #
3462 #                                                                             #
3463 #                                                                             #
3464 ###############################################################################
3465 #
3466 #
3467 void
3468 ComplexImages(ref)
3469   Image::Magick ref=NO_INIT
3470   ALIAS:
3471     ComplexImages   = 1
3472     compleximages   = 2
3473   PPCODE:
3474   {
3475     AV
3476       *av;
3477
3478     char
3479       *attribute,
3480       *p;
3481
3482     ComplexOperator
3483       op;
3484
3485     ExceptionInfo
3486       *exception;
3487
3488     HV
3489       *hv;
3490
3491     Image
3492       *image;
3493
3494     register ssize_t
3495       i;
3496
3497     struct PackageInfo
3498       *info;
3499
3500     SV
3501       *perl_exception,
3502       *reference,
3503       *rv,
3504       *sv;
3505
3506     PERL_UNUSED_VAR(ref);
3507     PERL_UNUSED_VAR(ix);
3508     exception=AcquireExceptionInfo();
3509     perl_exception=newSVpv("",0);
3510     sv=NULL;
3511     if (sv_isobject(ST(0)) == 0)
3512       {
3513         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3514           PackageName);
3515         goto PerlException;
3516       }
3517     reference=SvRV(ST(0));
3518     hv=SvSTASH(reference);
3519     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3520     if (image == (Image *) NULL)
3521       {
3522         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3523           PackageName);
3524         goto PerlException;
3525       }
3526     op=UndefinedComplexOperator;
3527     if (items == 2)
3528       {
3529         ssize_t
3530           in;
3531
3532         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3533           SvPV(ST(1),na));
3534         if (in < 0)
3535           {
3536             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3537               SvPV(ST(1),na));
3538             return;
3539           }
3540         op=(ComplexOperator) in;
3541       }
3542     else
3543       for (i=2; i < items; i+=2)
3544       {
3545         attribute=(char *) SvPV(ST(i-1),na);
3546         switch (*attribute)
3547         {
3548           case 'O':
3549           case 'o':
3550           {
3551             if (LocaleCompare(attribute,"operator") == 0)
3552               {
3553                 ssize_t
3554                   in;
3555
3556                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3557                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3558                 if (in < 0)
3559                   {
3560                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3561                       SvPV(ST(i),na));
3562                     return;
3563                   }
3564                 op=(ComplexOperator) in;
3565                 break;
3566               }
3567             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3568               attribute);
3569             break;
3570           }
3571           default:
3572           {
3573             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3574               attribute);
3575             break;
3576           }
3577         }
3578       }
3579     image=ComplexImages(image,op,exception);
3580     if (image == (Image *) NULL)
3581       goto PerlException;
3582     /*
3583       Create blessed Perl array for the returned image.
3584     */
3585     av=newAV();
3586     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3587     SvREFCNT_dec(av);
3588     AddImageToRegistry(sv,image);
3589     rv=newRV(sv);
3590     av_push(av,sv_bless(rv,hv));
3591     SvREFCNT_dec(sv);
3592     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3593     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3594       "complex-%.*s",(int) (MagickPathExtent-9),
3595       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3596     (void) CopyMagickString(image->filename,info->image_info->filename,
3597       MagickPathExtent);
3598     SetImageInfo(info->image_info,0,exception);
3599     exception=DestroyExceptionInfo(exception);
3600     SvREFCNT_dec(perl_exception);
3601     XSRETURN(1);
3602
3603   PerlException:
3604     InheritPerlException(exception,perl_exception);
3605     exception=DestroyExceptionInfo(exception);
3606     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3607     SvPOK_on(perl_exception);
3608     ST(0)=sv_2mortal(perl_exception);
3609     XSRETURN(1);
3610   }
3611 \f
3612 #
3613 ###############################################################################
3614 #                                                                             #
3615 #                                                                             #
3616 #                                                                             #
3617 #   C o m p a r e L a y e r s                                                 #
3618 #                                                                             #
3619 #                                                                             #
3620 #                                                                             #
3621 ###############################################################################
3622 #
3623 #
3624 void
3625 CompareLayers(ref)
3626   Image::Magick ref=NO_INIT
3627   ALIAS:
3628     CompareImagesLayers   = 1
3629     comparelayers        = 2
3630     compareimagelayers   = 3
3631   PPCODE:
3632   {
3633     AV
3634       *av;
3635
3636     char
3637       *attribute;
3638
3639     ExceptionInfo
3640       *exception;
3641
3642     HV
3643       *hv;
3644
3645     Image
3646       *image;
3647
3648     LayerMethod
3649       method;
3650
3651     register ssize_t
3652       i;
3653
3654     ssize_t
3655       option;
3656
3657     struct PackageInfo
3658       *info;
3659
3660     SV
3661       *av_reference,
3662       *perl_exception,
3663       *reference,
3664       *rv,
3665       *sv;
3666
3667     PERL_UNUSED_VAR(ref);
3668     PERL_UNUSED_VAR(ix);
3669     exception=AcquireExceptionInfo();
3670     perl_exception=newSVpv("",0);
3671     sv=NULL;
3672     if (sv_isobject(ST(0)) == 0)
3673       {
3674         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3675           PackageName);
3676         goto PerlException;
3677       }
3678     reference=SvRV(ST(0));
3679     hv=SvSTASH(reference);
3680     av=newAV();
3681     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3682     SvREFCNT_dec(av);
3683     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3684     if (image == (Image *) NULL)
3685       {
3686         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3687           PackageName);
3688         goto PerlException;
3689       }
3690     method=CompareAnyLayer;
3691     for (i=2; i < items; i+=2)
3692     {
3693       attribute=(char *) SvPV(ST(i-1),na);
3694       switch (*attribute)
3695       {
3696         case 'M':
3697         case 'm':
3698         {
3699           if (LocaleCompare(attribute,"method") == 0)
3700             {
3701               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3702                 SvPV(ST(i),na));
3703               if (option < 0)
3704                 {
3705                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3706                     SvPV(ST(i),na));
3707                   break;
3708                 }
3709                method=(LayerMethod) option;
3710               break;
3711             }
3712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3713             attribute);
3714           break;
3715         }
3716         default:
3717         {
3718           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3719             attribute);
3720           break;
3721         }
3722       }
3723     }
3724     image=CompareImagesLayers(image,method,exception);
3725     if (image == (Image *) NULL)
3726       goto PerlException;
3727     for ( ; image; image=image->next)
3728     {
3729       AddImageToRegistry(sv,image);
3730       rv=newRV(sv);
3731       av_push(av,sv_bless(rv,hv));
3732       SvREFCNT_dec(sv);
3733     }
3734     exception=DestroyExceptionInfo(exception);
3735     ST(0)=av_reference;
3736     SvREFCNT_dec(perl_exception);
3737     XSRETURN(1);
3738
3739   PerlException:
3740     InheritPerlException(exception,perl_exception);
3741     exception=DestroyExceptionInfo(exception);
3742     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3743     SvPOK_on(perl_exception);
3744     ST(0)=sv_2mortal(perl_exception);
3745     XSRETURN(1);
3746   }
3747 \f
3748 #
3749 ###############################################################################
3750 #                                                                             #
3751 #                                                                             #
3752 #                                                                             #
3753 #   D e s t r o y                                                             #
3754 #                                                                             #
3755 #                                                                             #
3756 #                                                                             #
3757 ###############################################################################
3758 #
3759 #
3760 void
3761 DESTROY(ref)
3762   Image::Magick ref=NO_INIT
3763   PPCODE:
3764   {
3765     SV
3766       *reference;
3767
3768     PERL_UNUSED_VAR(ref);
3769     if (sv_isobject(ST(0)) == 0)
3770       croak("ReferenceIsNotMyType");
3771     reference=SvRV(ST(0));
3772     switch (SvTYPE(reference))
3773     {
3774       case SVt_PVAV:
3775       {
3776         char
3777           message[MagickPathExtent];
3778
3779         const SV
3780           *key;
3781
3782         HV
3783           *hv;
3784
3785         GV
3786           **gvp;
3787
3788         struct PackageInfo
3789           *info;
3790
3791         SV
3792           *sv;
3793
3794         /*
3795           Array (AV *) reference
3796         */
3797         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3798           XS_VERSION,reference);
3799         hv=gv_stashpv(PackageName, FALSE);
3800         if (!hv)
3801           break;
3802         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3803         if (!gvp)
3804           break;
3805         sv=GvSV(*gvp);
3806         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3807           {
3808             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3809             DestroyPackageInfo(info);
3810           }
3811         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3812         (void) key;
3813         break;
3814       }
3815       case SVt_PVMG:
3816       {
3817         Image
3818           *image;
3819
3820         /*
3821           Blessed scalar = (Image *) SvIV(reference)
3822         */
3823         image=INT2PTR(Image *,SvIV(reference));
3824         if (image != (Image *) NULL)
3825           DeleteImageFromRegistry(reference,image);
3826         break;
3827       }
3828       default:
3829         break;
3830     }
3831   }
3832 \f
3833 #
3834 ###############################################################################
3835 #                                                                             #
3836 #                                                                             #
3837 #                                                                             #
3838 #   D i s p l a y                                                             #
3839 #                                                                             #
3840 #                                                                             #
3841 #                                                                             #
3842 ###############################################################################
3843 #
3844 #
3845 void
3846 Display(ref,...)
3847   Image::Magick ref=NO_INIT
3848   ALIAS:
3849     DisplayImage  = 1
3850     display       = 2
3851     displayimage  = 3
3852   PPCODE:
3853   {
3854     ExceptionInfo
3855       *exception;
3856
3857     Image
3858       *image;
3859
3860     register ssize_t
3861       i;
3862
3863     struct PackageInfo
3864       *info,
3865       *package_info;
3866
3867     SV
3868       *perl_exception,
3869       *reference;
3870
3871     PERL_UNUSED_VAR(ref);
3872     PERL_UNUSED_VAR(ix);
3873     exception=AcquireExceptionInfo();
3874     perl_exception=newSVpv("",0);
3875     package_info=(struct PackageInfo *) NULL;
3876     if (sv_isobject(ST(0)) == 0)
3877       {
3878         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3879           PackageName);
3880         goto PerlException;
3881       }
3882     reference=SvRV(ST(0));
3883     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3884     if (image == (Image *) NULL)
3885       {
3886         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3887           PackageName);
3888         goto PerlException;
3889       }
3890     package_info=ClonePackageInfo(info,exception);
3891     if (items == 2)
3892       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3893     else
3894       if (items > 2)
3895         for (i=2; i < items; i+=2)
3896           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3897             exception);
3898     (void) DisplayImages(package_info->image_info,image,exception);
3899     (void) CatchImageException(image);
3900
3901   PerlException:
3902     if (package_info != (struct PackageInfo *) NULL)
3903       DestroyPackageInfo(package_info);
3904     InheritPerlException(exception,perl_exception);
3905     exception=DestroyExceptionInfo(exception);
3906     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3907     SvPOK_on(perl_exception);
3908     ST(0)=sv_2mortal(perl_exception);
3909     XSRETURN(1);
3910   }
3911 \f
3912 #
3913 ###############################################################################
3914 #                                                                             #
3915 #                                                                             #
3916 #                                                                             #
3917 #   E v a l u a t e I m a g e s                                               #
3918 #                                                                             #
3919 #                                                                             #
3920 #                                                                             #
3921 ###############################################################################
3922 #
3923 #
3924 void
3925 EvaluateImages(ref)
3926   Image::Magick ref=NO_INIT
3927   ALIAS:
3928     EvaluateImages   = 1
3929     evaluateimages   = 2
3930   PPCODE:
3931   {
3932     AV
3933       *av;
3934
3935     char
3936       *attribute,
3937       *p;
3938
3939     ExceptionInfo
3940       *exception;
3941
3942     HV
3943       *hv;
3944
3945     Image
3946       *image;
3947
3948     MagickEvaluateOperator
3949       op;
3950
3951     register ssize_t
3952       i;
3953
3954     struct PackageInfo
3955       *info;
3956
3957     SV
3958       *perl_exception,
3959       *reference,
3960       *rv,
3961       *sv;
3962
3963     PERL_UNUSED_VAR(ref);
3964     PERL_UNUSED_VAR(ix);
3965     exception=AcquireExceptionInfo();
3966     perl_exception=newSVpv("",0);
3967     sv=NULL;
3968     if (sv_isobject(ST(0)) == 0)
3969       {
3970         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3971           PackageName);
3972         goto PerlException;
3973       }
3974     reference=SvRV(ST(0));
3975     hv=SvSTASH(reference);
3976     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3977     if (image == (Image *) NULL)
3978       {
3979         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3980           PackageName);
3981         goto PerlException;
3982       }
3983     op=MeanEvaluateOperator;
3984     if (items == 2)
3985       {
3986         ssize_t
3987           in;
3988
3989         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3990           SvPV(ST(1),na));
3991         if (in < 0)
3992           {
3993             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3994               SvPV(ST(1),na));
3995             return;
3996           }
3997         op=(MagickEvaluateOperator) in;
3998       }
3999     else
4000       for (i=2; i < items; i+=2)
4001       {
4002         attribute=(char *) SvPV(ST(i-1),na);
4003         switch (*attribute)
4004         {
4005           case 'O':
4006           case 'o':
4007           {
4008             if (LocaleCompare(attribute,"operator") == 0)
4009               {
4010                 ssize_t
4011                   in;
4012
4013                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4014                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4015                 if (in < 0)
4016                   {
4017                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4018                       SvPV(ST(i),na));
4019                     return;
4020                   }
4021                 op=(MagickEvaluateOperator) in;
4022                 break;
4023               }
4024             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4025               attribute);
4026             break;
4027           }
4028           default:
4029           {
4030             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4031               attribute);
4032             break;
4033           }
4034         }
4035       }
4036     image=EvaluateImages(image,op,exception);
4037     if (image == (Image *) NULL)
4038       goto PerlException;
4039     /*
4040       Create blessed Perl array for the returned image.
4041     */
4042     av=newAV();
4043     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4044     SvREFCNT_dec(av);
4045     AddImageToRegistry(sv,image);
4046     rv=newRV(sv);
4047     av_push(av,sv_bless(rv,hv));
4048     SvREFCNT_dec(sv);
4049     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4050     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4051       "evaluate-%.*s",(int) (MagickPathExtent-9),
4052       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4053     (void) CopyMagickString(image->filename,info->image_info->filename,
4054       MagickPathExtent);
4055     SetImageInfo(info->image_info,0,exception);
4056     exception=DestroyExceptionInfo(exception);
4057     SvREFCNT_dec(perl_exception);
4058     XSRETURN(1);
4059
4060   PerlException:
4061     InheritPerlException(exception,perl_exception);
4062     exception=DestroyExceptionInfo(exception);
4063     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4064     SvPOK_on(perl_exception);
4065     ST(0)=sv_2mortal(perl_exception);
4066     XSRETURN(1);
4067   }
4068 \f
4069 #
4070 ###############################################################################
4071 #                                                                             #
4072 #                                                                             #
4073 #                                                                             #
4074 #   F e a t u r e s                                                           #
4075 #                                                                             #
4076 #                                                                             #
4077 #                                                                             #
4078 ###############################################################################
4079 #
4080 #
4081 void
4082 Features(ref,...)
4083   Image::Magick ref=NO_INIT
4084   ALIAS:
4085     FeaturesImage = 1
4086     features      = 2
4087     featuresimage = 3
4088   PPCODE:
4089   {
4090 #define ChannelFeatures(channel,direction) \
4091 { \
4092   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4093     channel_features[channel].angular_second_moment[direction]); \
4094   PUSHs(sv_2mortal(newSVpv(message,0))); \
4095   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4096     channel_features[channel].contrast[direction]); \
4097   PUSHs(sv_2mortal(newSVpv(message,0))); \
4098   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4099     channel_features[channel].contrast[direction]); \
4100   PUSHs(sv_2mortal(newSVpv(message,0))); \
4101   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4102     channel_features[channel].variance_sum_of_squares[direction]); \
4103   PUSHs(sv_2mortal(newSVpv(message,0))); \
4104   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4105     channel_features[channel].inverse_difference_moment[direction]); \
4106   PUSHs(sv_2mortal(newSVpv(message,0))); \
4107   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4108     channel_features[channel].sum_average[direction]); \
4109   PUSHs(sv_2mortal(newSVpv(message,0))); \
4110   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4111     channel_features[channel].sum_variance[direction]); \
4112   PUSHs(sv_2mortal(newSVpv(message,0))); \
4113   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4114     channel_features[channel].sum_entropy[direction]); \
4115   PUSHs(sv_2mortal(newSVpv(message,0))); \
4116   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4117     channel_features[channel].entropy[direction]); \
4118   PUSHs(sv_2mortal(newSVpv(message,0))); \
4119   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4120     channel_features[channel].difference_variance[direction]); \
4121   PUSHs(sv_2mortal(newSVpv(message,0))); \
4122   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4123     channel_features[channel].difference_entropy[direction]); \
4124   PUSHs(sv_2mortal(newSVpv(message,0))); \
4125   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4126     channel_features[channel].measure_of_correlation_1[direction]); \
4127   PUSHs(sv_2mortal(newSVpv(message,0))); \
4128   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4129     channel_features[channel].measure_of_correlation_2[direction]); \
4130   PUSHs(sv_2mortal(newSVpv(message,0))); \
4131   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4132     channel_features[channel].maximum_correlation_coefficient[direction]); \
4133   PUSHs(sv_2mortal(newSVpv(message,0))); \
4134 }
4135
4136     AV
4137       *av;
4138
4139     char
4140       *attribute,
4141       message[MagickPathExtent];
4142
4143     ChannelFeatures
4144       *channel_features;
4145
4146     double
4147       distance;
4148
4149     ExceptionInfo
4150       *exception;
4151
4152     Image
4153       *image;
4154
4155     register ssize_t
4156       i;
4157
4158     ssize_t
4159       count;
4160
4161     struct PackageInfo
4162       *info;
4163
4164     SV
4165       *perl_exception,
4166       *reference;
4167
4168     PERL_UNUSED_VAR(ref);
4169     PERL_UNUSED_VAR(ix);
4170     exception=AcquireExceptionInfo();
4171     perl_exception=newSVpv("",0);
4172     av=NULL;
4173     if (sv_isobject(ST(0)) == 0)
4174       {
4175         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4176           PackageName);
4177         goto PerlException;
4178       }
4179     reference=SvRV(ST(0));
4180     av=newAV();
4181     SvREFCNT_dec(av);
4182     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4183     if (image == (Image *) NULL)
4184       {
4185         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4186           PackageName);
4187         goto PerlException;
4188       }
4189     distance=1.0;
4190     for (i=2; i < items; i+=2)
4191     {
4192       attribute=(char *) SvPV(ST(i-1),na);
4193       switch (*attribute)
4194       {
4195         case 'D':
4196         case 'd':
4197         {
4198           if (LocaleCompare(attribute,"distance") == 0)
4199             {
4200               distance=StringToLong((char *) SvPV(ST(1),na));
4201               break;
4202             }
4203           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4204             attribute);
4205           break;
4206         }
4207         default:
4208         {
4209           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4210             attribute);
4211           break;
4212         }
4213       }
4214     }
4215     count=0;
4216     for ( ; image; image=image->next)
4217     {
4218       channel_features=GetImageFeatures(image,distance,exception);
4219       if (channel_features == (ChannelFeatures *) NULL)
4220         continue;
4221       count++;
4222       EXTEND(sp,280*count);
4223       for (i=0; i < 4; i++)
4224       {
4225         ChannelFeatures(RedChannel,i);
4226         ChannelFeatures(GreenChannel,i);
4227         ChannelFeatures(BlueChannel,i);
4228         if (image->colorspace == CMYKColorspace)
4229           ChannelFeatures(BlackChannel,i);
4230         if (image->alpha_trait != UndefinedPixelTrait)
4231           ChannelFeatures(AlphaChannel,i);
4232       }
4233       channel_features=(ChannelFeatures *)
4234         RelinquishMagickMemory(channel_features);
4235     }
4236
4237   PerlException:
4238     InheritPerlException(exception,perl_exception);
4239     exception=DestroyExceptionInfo(exception);
4240     SvREFCNT_dec(perl_exception);
4241   }
4242 \f
4243 #
4244 ###############################################################################
4245 #                                                                             #
4246 #                                                                             #
4247 #                                                                             #
4248 #   F l a t t e n                                                             #
4249 #                                                                             #
4250 #                                                                             #
4251 #                                                                             #
4252 ###############################################################################
4253 #
4254 #
4255 void
4256 Flatten(ref)
4257   Image::Magick ref=NO_INIT
4258   ALIAS:
4259     FlattenImage   = 1
4260     flatten        = 2
4261     flattenimage   = 3
4262   PPCODE:
4263   {
4264     AV
4265       *av;
4266
4267     char
4268       *attribute,
4269       *p;
4270
4271     ExceptionInfo
4272       *exception;
4273
4274     HV
4275       *hv;
4276
4277     Image
4278       *image;
4279
4280     PixelInfo
4281       background_color;
4282
4283     register ssize_t
4284       i;
4285
4286     struct PackageInfo
4287       *info;
4288
4289     SV
4290       *perl_exception,
4291       *reference,
4292       *rv,
4293       *sv;
4294
4295     PERL_UNUSED_VAR(ref);
4296     PERL_UNUSED_VAR(ix);
4297     exception=AcquireExceptionInfo();
4298     perl_exception=newSVpv("",0);
4299     sv=NULL;
4300     if (sv_isobject(ST(0)) == 0)
4301       {
4302         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4303           PackageName);
4304         goto PerlException;
4305       }
4306     reference=SvRV(ST(0));
4307     hv=SvSTASH(reference);
4308     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4309     if (image == (Image *) NULL)
4310       {
4311         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4312           PackageName);
4313         goto PerlException;
4314       }
4315     background_color=image->background_color;
4316     if (items == 2)
4317       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4318         &background_color,exception);
4319     else
4320       for (i=2; i < items; i+=2)
4321       {
4322         attribute=(char *) SvPV(ST(i-1),na);
4323         switch (*attribute)
4324         {
4325           case 'B':
4326           case 'b':
4327           {
4328             if (LocaleCompare(attribute,"background") == 0)
4329               {
4330                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4331                   AllCompliance,&background_color,exception);
4332                 break;
4333               }
4334             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4335               attribute);
4336             break;
4337           }
4338           default:
4339           {
4340             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4341               attribute);
4342             break;
4343           }
4344         }
4345       }
4346     image->background_color=background_color;
4347     image=MergeImageLayers(image,FlattenLayer,exception);
4348     if (image == (Image *) NULL)
4349       goto PerlException;
4350     /*
4351       Create blessed Perl array for the returned image.
4352     */
4353     av=newAV();
4354     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4355     SvREFCNT_dec(av);
4356     AddImageToRegistry(sv,image);
4357     rv=newRV(sv);
4358     av_push(av,sv_bless(rv,hv));
4359     SvREFCNT_dec(sv);
4360     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4361     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4362       "flatten-%.*s",(int) (MagickPathExtent-9),
4363       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4364     (void) CopyMagickString(image->filename,info->image_info->filename,
4365       MagickPathExtent);
4366     SetImageInfo(info->image_info,0,exception);
4367     exception=DestroyExceptionInfo(exception);
4368     SvREFCNT_dec(perl_exception);
4369     XSRETURN(1);
4370
4371   PerlException:
4372     InheritPerlException(exception,perl_exception);
4373     exception=DestroyExceptionInfo(exception);
4374     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4375     SvPOK_on(perl_exception);  /* return messages in string context */
4376     ST(0)=sv_2mortal(perl_exception);
4377     XSRETURN(1);
4378   }
4379 \f
4380 #
4381 ###############################################################################
4382 #                                                                             #
4383 #                                                                             #
4384 #                                                                             #
4385 #   F x                                                                       #
4386 #                                                                             #
4387 #                                                                             #
4388 #                                                                             #
4389 ###############################################################################
4390 #
4391 #
4392 void
4393 Fx(ref,...)
4394   Image::Magick ref=NO_INIT
4395   ALIAS:
4396     FxImage  = 1
4397     fx       = 2
4398     fximage  = 3
4399   PPCODE:
4400   {
4401     AV
4402       *av;
4403
4404     char
4405       *attribute,
4406       expression[MagickPathExtent];
4407
4408     ChannelType
4409       channel,
4410       channel_mask;
4411
4412     ExceptionInfo
4413       *exception;
4414
4415     HV
4416       *hv;
4417
4418     Image
4419       *image;
4420
4421     register ssize_t
4422       i;
4423
4424     struct PackageInfo
4425       *info;
4426
4427     SV
4428       *av_reference,
4429       *perl_exception,
4430       *reference,
4431       *rv,
4432       *sv;
4433
4434     PERL_UNUSED_VAR(ref);
4435     PERL_UNUSED_VAR(ix);
4436     exception=AcquireExceptionInfo();
4437     perl_exception=newSVpv("",0);
4438     sv=NULL;
4439     attribute=NULL;
4440     av=NULL;
4441     if (sv_isobject(ST(0)) == 0)
4442       {
4443         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4444           PackageName);
4445         goto PerlException;
4446       }
4447     reference=SvRV(ST(0));
4448     hv=SvSTASH(reference);
4449     av=newAV();
4450     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4451     SvREFCNT_dec(av);
4452     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4453     if (image == (Image *) NULL)
4454       {
4455         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4456           PackageName);
4457         goto PerlException;
4458       }
4459     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4460     /*
4461       Get options.
4462     */
4463     channel=DefaultChannels;
4464     (void) CopyMagickString(expression,"u",MagickPathExtent);
4465     if (items == 2)
4466       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4467     else
4468       for (i=2; i < items; i+=2)
4469       {
4470         attribute=(char *) SvPV(ST(i-1),na);
4471         switch (*attribute)
4472         {
4473           case 'C':
4474           case 'c':
4475           {
4476             if (LocaleCompare(attribute,"channel") == 0)
4477               {
4478                 ssize_t
4479                   option;
4480
4481                 option=ParseChannelOption(SvPV(ST(i),na));
4482                 if (option < 0)
4483                   {
4484                     ThrowPerlException(exception,OptionError,
4485                       "UnrecognizedType",SvPV(ST(i),na));
4486                     return;
4487                   }
4488                 channel=(ChannelType) option;
4489                 break;
4490               }
4491             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4492               attribute);
4493             break;
4494           }
4495           case 'E':
4496           case 'e':
4497           {
4498             if (LocaleCompare(attribute,"expression") == 0)
4499               {
4500                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4501                   MagickPathExtent);
4502                 break;
4503               }
4504             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4505               attribute);
4506             break;
4507           }
4508           default:
4509           {
4510             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4511               attribute);
4512             break;
4513           }
4514         }
4515       }
4516     channel_mask=SetImageChannelMask(image,channel);
4517     image=FxImage(image,expression,exception);
4518     if (image != (Image *) NULL)
4519       (void) SetImageChannelMask(image,channel_mask);
4520     if (image == (Image *) NULL)
4521       goto PerlException;
4522     for ( ; image; image=image->next)
4523     {
4524       AddImageToRegistry(sv,image);
4525       rv=newRV(sv);
4526       av_push(av,sv_bless(rv,hv));
4527       SvREFCNT_dec(sv);
4528     }
4529     exception=DestroyExceptionInfo(exception);
4530     ST(0)=av_reference;
4531     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4532     XSRETURN(1);
4533
4534   PerlException:
4535     InheritPerlException(exception,perl_exception);
4536     exception=DestroyExceptionInfo(exception);
4537     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4538     SvPOK_on(perl_exception);
4539     ST(0)=sv_2mortal(perl_exception);
4540     XSRETURN(1);
4541   }
4542 \f
4543 #
4544 ###############################################################################
4545 #                                                                             #
4546 #                                                                             #
4547 #                                                                             #
4548 #   G e t                                                                     #
4549 #                                                                             #
4550 #                                                                             #
4551 #                                                                             #
4552 ###############################################################################
4553 #
4554 #
4555 void
4556 Get(ref,...)
4557   Image::Magick ref=NO_INIT
4558   ALIAS:
4559     GetAttributes = 1
4560     GetAttribute  = 2
4561     get           = 3
4562     getattributes = 4
4563     getattribute  = 5
4564   PPCODE:
4565   {
4566     char
4567       *attribute,
4568       color[MagickPathExtent];
4569
4570     const char
4571       *value;
4572
4573     ExceptionInfo
4574       *exception;
4575
4576     Image
4577       *image;
4578
4579     long
4580       j;
4581
4582     register ssize_t
4583       i;
4584
4585     struct PackageInfo
4586       *info;
4587
4588     SV
4589       *perl_exception,
4590       *reference,
4591       *s;
4592
4593     PERL_UNUSED_VAR(ref);
4594     PERL_UNUSED_VAR(ix);
4595     exception=AcquireExceptionInfo();
4596     perl_exception=newSVpv("",0);
4597     if (sv_isobject(ST(0)) == 0)
4598       {
4599         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4600           PackageName);
4601         XSRETURN_EMPTY;
4602       }
4603     reference=SvRV(ST(0));
4604     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4605     if (image == (Image *) NULL && !info)
4606       XSRETURN_EMPTY;
4607     EXTEND(sp,items);
4608     for (i=1; i < items; i++)
4609     {
4610       attribute=(char *) SvPV(ST(i),na);
4611       s=NULL;
4612       switch (*attribute)
4613       {
4614         case 'A':
4615         case 'a':
4616         {
4617           if (LocaleCompare(attribute,"adjoin") == 0)
4618             {
4619               if (info)
4620                 s=newSViv((ssize_t) info->image_info->adjoin);
4621               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4622               continue;
4623             }
4624           if (LocaleCompare(attribute,"antialias") == 0)
4625             {
4626               if (info)
4627                 s=newSViv((ssize_t) info->image_info->antialias);
4628               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4629               continue;
4630             }
4631           if (LocaleCompare(attribute,"area") == 0)
4632             {
4633               s=newSViv(GetMagickResource(AreaResource));
4634               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4635               continue;
4636             }
4637           if (LocaleCompare(attribute,"attenuate") == 0)
4638             {
4639               const char
4640                 *value;
4641
4642               value=GetImageProperty(image,attribute,exception);
4643               if (value != (const char *) NULL)
4644                 s=newSVpv(value,0);
4645               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4646               continue;
4647             }
4648           if (LocaleCompare(attribute,"authenticate") == 0)
4649             {
4650               if (info)
4651                 {
4652                   const char
4653                     *option;
4654
4655                   option=GetImageOption(info->image_info,attribute);
4656                   if (option != (const char *) NULL)
4657                     s=newSVpv(option,0);
4658                 }
4659               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4660               continue;
4661             }
4662           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4663             attribute);
4664           break;
4665         }
4666         case 'B':
4667         case 'b':
4668         {
4669           if (LocaleCompare(attribute,"background") == 0)
4670             {
4671               if (image == (Image *) NULL)
4672                 break;
4673               (void) FormatLocaleString(color,MagickPathExtent,
4674                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4675                 (double) image->background_color.green,
4676                 (double) image->background_color.blue,
4677                 (double) image->background_color.alpha);
4678               s=newSVpv(color,0);
4679               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4680               continue;
4681             }
4682           if (LocaleCompare(attribute,"base-columns") == 0)
4683             {
4684               if (image != (Image *) NULL)
4685                 s=newSViv((ssize_t) image->magick_columns);
4686               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4687               continue;
4688             }
4689           if (LocaleCompare(attribute,"base-filename") == 0)
4690             {
4691               if (image != (Image *) NULL)
4692                 s=newSVpv(image->magick_filename,0);
4693               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4694               continue;
4695             }
4696           if (LocaleCompare(attribute,"base-height") == 0)
4697             {
4698               if (image != (Image *) NULL)
4699                 s=newSViv((ssize_t) image->magick_rows);
4700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701               continue;
4702             }
4703           if (LocaleCompare(attribute,"base-rows") == 0)
4704             {
4705               if (image != (Image *) NULL)
4706                 s=newSViv((ssize_t) image->magick_rows);
4707               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4708               continue;
4709             }
4710           if (LocaleCompare(attribute,"base-width") == 0)
4711             {
4712               if (image != (Image *) NULL)
4713                 s=newSViv((ssize_t) image->magick_columns);
4714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4715               continue;
4716             }
4717           if (LocaleCompare(attribute,"blue-primary") == 0)
4718             {
4719               if (image == (Image *) NULL)
4720                 break;
4721               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4722                 image->chromaticity.blue_primary.x,
4723                 image->chromaticity.blue_primary.y);
4724               s=newSVpv(color,0);
4725               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4726               continue;
4727             }
4728           if (LocaleCompare(attribute,"bordercolor") == 0)
4729             {
4730               if (image == (Image *) NULL)
4731                 break;
4732               (void) FormatLocaleString(color,MagickPathExtent,
4733                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4734                 (double) image->border_color.green,
4735                 (double) image->border_color.blue,
4736                 (double) image->border_color.alpha);
4737               s=newSVpv(color,0);
4738               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4739               continue;
4740             }
4741           if (LocaleCompare(attribute,"bounding-box") == 0)
4742             {
4743               char
4744                 geometry[MagickPathExtent];
4745
4746               RectangleInfo
4747                 page;
4748
4749               if (image == (Image *) NULL)
4750                 break;
4751               page=GetImageBoundingBox(image,exception);
4752               (void) FormatLocaleString(geometry,MagickPathExtent,
4753                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4754                 page.height,(double) page.x,(double) page.y);
4755               s=newSVpv(geometry,0);
4756               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4757               continue;
4758             }
4759           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4760             attribute);
4761           break;
4762         }
4763         case 'C':
4764         case 'c':
4765         {
4766           if (LocaleCompare(attribute,"class") == 0)
4767             {
4768               if (image == (Image *) NULL)
4769                 break;
4770               s=newSViv(image->storage_class);
4771               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4772                 image->storage_class));
4773               SvIOK_on(s);
4774               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4775               continue;
4776             }
4777           if (LocaleCompare(attribute,"clip-mask") == 0)
4778             {
4779               if (image != (Image *) NULL)
4780                 {
4781                   Image
4782                     *mask_image;
4783
4784                   SV
4785                     *sv;
4786
4787                   sv=NULL;
4788                   if (image->read_mask == MagickFalse)
4789                     ClipImage(image,exception);
4790                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4791                   if (mask_image != (Image *) NULL)
4792                     {
4793                       AddImageToRegistry(sv,mask_image);
4794                       s=sv_bless(newRV(sv),SvSTASH(reference));
4795                     }
4796                 }
4797               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4798               continue;
4799             }
4800           if (LocaleCompare(attribute,"clip-path") == 0)
4801             {
4802               if (image != (Image *) NULL)
4803                 {
4804                   Image
4805                     *mask_image;
4806
4807                   SV
4808                     *sv;
4809
4810                   sv=NULL;
4811                   if (image->read_mask != MagickFalse)
4812                     ClipImage(image,exception);
4813                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4814                   if (mask_image != (Image *) NULL)
4815                     {
4816                       AddImageToRegistry(sv,mask_image);
4817                       s=sv_bless(newRV(sv),SvSTASH(reference));
4818                     }
4819                 }
4820               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4821               continue;
4822             }
4823           if (LocaleCompare(attribute,"compression") == 0)
4824             {
4825               j=info ? info->image_info->compression : image ?
4826                 image->compression : UndefinedCompression;
4827               if (info)
4828                 if (info->image_info->compression == UndefinedCompression)
4829                   j=image->compression;
4830               s=newSViv(j);
4831               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4832                 j));
4833               SvIOK_on(s);
4834               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4835               continue;
4836             }
4837           if (LocaleCompare(attribute,"colorspace") == 0)
4838             {
4839               j=image ? image->colorspace : RGBColorspace;
4840               s=newSViv(j);
4841               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4842                 j));
4843               SvIOK_on(s);
4844               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4845               continue;
4846             }
4847           if (LocaleCompare(attribute,"colors") == 0)
4848             {
4849               if (image != (Image *) NULL)
4850                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4851                   exception));
4852               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4853               continue;
4854             }
4855           if (LocaleNCompare(attribute,"colormap",8) == 0)
4856             {
4857               int
4858                 items;
4859
4860               if (image == (Image *) NULL || !image->colormap)
4861                 break;
4862               j=0;
4863               items=sscanf(attribute,"%*[^[][%ld",&j);
4864               (void) items;
4865               if (j > (ssize_t) image->colors)
4866                 j%=image->colors;
4867               (void) FormatLocaleString(color,MagickPathExtent,
4868                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4869                 (double) image->colormap[j].green,
4870                 (double) image->colormap[j].blue,
4871                 (double) image->colormap[j].alpha);
4872               s=newSVpv(color,0);
4873               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4874               continue;
4875             }
4876           if (LocaleCompare(attribute,"columns") == 0)
4877             {
4878               if (image != (Image *) NULL)
4879                 s=newSViv((ssize_t) image->columns);
4880               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4881               continue;
4882             }
4883           if (LocaleCompare(attribute,"comment") == 0)
4884             {
4885               const char
4886                 *value;
4887
4888               value=GetImageProperty(image,attribute,exception);
4889               if (value != (const char *) NULL)
4890                 s=newSVpv(value,0);
4891               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4892               continue;
4893             }
4894           if (LocaleCompare(attribute,"copyright") == 0)
4895             {
4896               s=newSVpv(GetMagickCopyright(),0);
4897               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4898               continue;
4899             }
4900           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4901             attribute);
4902           break;
4903         }
4904         case 'D':
4905         case 'd':
4906         {
4907           if (LocaleCompare(attribute,"density") == 0)
4908             {
4909               char
4910                 geometry[MagickPathExtent];
4911
4912               if (image == (Image *) NULL)
4913                 break;
4914               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4915                 image->resolution.x,image->resolution.y);
4916               s=newSVpv(geometry,0);
4917               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4918               continue;
4919             }
4920           if (LocaleCompare(attribute,"delay") == 0)
4921             {
4922               if (image != (Image *) NULL)
4923                 s=newSViv((ssize_t) image->delay);
4924               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4925               continue;
4926             }
4927           if (LocaleCompare(attribute,"depth") == 0)
4928             {
4929               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4930               if (image != (Image *) NULL)
4931                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4932               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4933               continue;
4934             }
4935           if (LocaleCompare(attribute,"directory") == 0)
4936             {
4937               if (image && image->directory)
4938                 s=newSVpv(image->directory,0);
4939               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4940               continue;
4941             }
4942           if (LocaleCompare(attribute,"dispose") == 0)
4943             {
4944               if (image == (Image *) NULL)
4945                 break;
4946
4947               s=newSViv(image->dispose);
4948               (void) sv_setpv(s,
4949                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4950               SvIOK_on(s);
4951               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4952               continue;
4953             }
4954           if (LocaleCompare(attribute,"disk") == 0)
4955             {
4956               s=newSViv(GetMagickResource(DiskResource));
4957               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4958               continue;
4959             }
4960           if (LocaleCompare(attribute,"dither") == 0)
4961             {
4962               if (info)
4963                 s=newSViv((ssize_t) info->image_info->dither);
4964               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4965               continue;
4966             }
4967           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4968             {
4969               if (info && info->image_info->server_name)
4970                 s=newSVpv(info->image_info->server_name,0);
4971               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4972               continue;
4973             }
4974           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4975             attribute);
4976           break;
4977         }
4978         case 'E':
4979         case 'e':
4980         {
4981           if (LocaleCompare(attribute,"elapsed-time") == 0)
4982             {
4983               if (image != (Image *) NULL)
4984                 s=newSVnv(GetElapsedTime(&image->timer));
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleCompare(attribute,"endian") == 0)
4989             {
4990               j=info ? info->image_info->endian : image ? image->endian :
4991                 UndefinedEndian;
4992               s=newSViv(j);
4993               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4994               SvIOK_on(s);
4995               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4996               continue;
4997             }
4998           if (LocaleCompare(attribute,"error") == 0)
4999             {
5000               if (image != (Image *) NULL)
5001                 s=newSVnv(image->error.mean_error_per_pixel);
5002               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5003               continue;
5004             }
5005           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5006             attribute);
5007           break;
5008         }
5009         case 'F':
5010         case 'f':
5011         {
5012           if (LocaleCompare(attribute,"filesize") == 0)
5013             {
5014               if (image != (Image *) NULL)
5015                 s=newSViv((ssize_t) GetBlobSize(image));
5016               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5017               continue;
5018             }
5019           if (LocaleCompare(attribute,"filename") == 0)
5020             {
5021               if (info && info->image_info->filename &&
5022                   *info->image_info->filename)
5023                 s=newSVpv(info->image_info->filename,0);
5024               if (image != (Image *) NULL)
5025                 s=newSVpv(image->filename,0);
5026               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5027               continue;
5028             }
5029           if (LocaleCompare(attribute,"filter") == 0)
5030             {
5031               s=image ? newSViv(image->filter) : newSViv(0);
5032               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5033                 image->filter));
5034               SvIOK_on(s);
5035               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5036               continue;
5037             }
5038           if (LocaleCompare(attribute,"font") == 0)
5039             {
5040               if (info && info->image_info->font)
5041                 s=newSVpv(info->image_info->font,0);
5042               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5043               continue;
5044             }
5045           if (LocaleCompare(attribute,"foreground") == 0)
5046             continue;
5047           if (LocaleCompare(attribute,"format") == 0)
5048             {
5049               const MagickInfo
5050                 *magick_info;
5051
5052               magick_info=(const MagickInfo *) NULL;
5053               if (info && (*info->image_info->magick != '\0'))
5054                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5055               if (image != (Image *) NULL)
5056                 magick_info=GetMagickInfo(image->magick,exception);
5057               if ((magick_info != (const MagickInfo *) NULL) &&
5058                   (*magick_info->description != '\0'))
5059                 s=newSVpv((char *) magick_info->description,0);
5060               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5061               continue;
5062             }
5063           if (LocaleCompare(attribute,"fuzz") == 0)
5064             {
5065               if (info)
5066                 s=newSVnv(info->image_info->fuzz);
5067               if (image != (Image *) NULL)
5068                 s=newSVnv(image->fuzz);
5069               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5070               continue;
5071             }
5072           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5073             attribute);
5074           break;
5075         }
5076         case 'G':
5077         case 'g':
5078         {
5079           if (LocaleCompare(attribute,"gamma") == 0)
5080             {
5081               if (image != (Image *) NULL)
5082                 s=newSVnv(image->gamma);
5083               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5084               continue;
5085             }
5086           if (LocaleCompare(attribute,"geometry") == 0)
5087             {
5088               if (image && image->geometry)
5089                 s=newSVpv(image->geometry,0);
5090               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5091               continue;
5092             }
5093           if (LocaleCompare(attribute,"gravity") == 0)
5094             {
5095               s=image ? newSViv(image->gravity) : newSViv(0);
5096               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5097                 image->gravity));
5098               SvIOK_on(s);
5099               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5100               continue;
5101             }
5102           if (LocaleCompare(attribute,"green-primary") == 0)
5103             {
5104               if (image == (Image *) NULL)
5105                 break;
5106               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5107                 image->chromaticity.green_primary.x,
5108                 image->chromaticity.green_primary.y);
5109               s=newSVpv(color,0);
5110               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5111               continue;
5112             }
5113           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5114             attribute);
5115           break;
5116         }
5117         case 'H':
5118         case 'h':
5119         {
5120           if (LocaleCompare(attribute,"height") == 0)
5121             {
5122               if (image != (Image *) NULL)
5123                 s=newSViv((ssize_t) image->rows);
5124               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5125               continue;
5126             }
5127           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5128             attribute);
5129           break;
5130         }
5131         case 'I':
5132         case 'i':
5133         {
5134           if (LocaleCompare(attribute,"icc") == 0)
5135             {
5136               if (image != (Image *) NULL)
5137                 {
5138                   const StringInfo
5139                     *profile;
5140
5141                   profile=GetImageProfile(image,"icc");
5142                   if (profile != (StringInfo *) NULL)
5143                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5144                       GetStringInfoLength(profile));
5145                 }
5146               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5147               continue;
5148             }
5149           if (LocaleCompare(attribute,"icm") == 0)
5150             {
5151               if (image != (Image *) NULL)
5152                 {
5153                   const StringInfo
5154                     *profile;
5155
5156                   profile=GetImageProfile(image,"icm");
5157                   if (profile != (const StringInfo *) NULL)
5158                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5159                       GetStringInfoLength(profile));
5160                 }
5161               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5162               continue;
5163             }
5164           if (LocaleCompare(attribute,"id") == 0)
5165             {
5166               if (image != (Image *) NULL)
5167                 {
5168                   char
5169                     key[MagickPathExtent];
5170
5171                   MagickBooleanType
5172                     status;
5173
5174                   static ssize_t
5175                     id = 0;
5176
5177                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5178                     id);
5179                   status=SetImageRegistry(ImageRegistryType,key,image,
5180                     exception);
5181                   (void) status;
5182                   s=newSViv(id++);
5183                 }
5184               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5185               continue;
5186             }
5187           if (LocaleNCompare(attribute,"index",5) == 0)
5188             {
5189               char
5190                 name[MagickPathExtent];
5191
5192               int
5193                 items;
5194
5195               long
5196                 x,
5197                 y;
5198
5199               register const Quantum
5200                 *p;
5201
5202               CacheView
5203                 *image_view;
5204
5205               if (image == (Image *) NULL)
5206                 break;
5207               if (image->storage_class != PseudoClass)
5208                 break;
5209               x=0;
5210               y=0;
5211               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5212               (void) items;
5213               image_view=AcquireVirtualCacheView(image,exception);
5214               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5215               if (p != (const Quantum *) NULL)
5216                 {
5217                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5218                     GetPixelIndex(image,p));
5219                   s=newSVpv(name,0);
5220                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5221                 }
5222               image_view=DestroyCacheView(image_view);
5223               continue;
5224             }
5225           if (LocaleCompare(attribute,"iptc") == 0)
5226             {
5227               if (image != (Image *) NULL)
5228                 {
5229                   const StringInfo
5230                     *profile;
5231
5232                   profile=GetImageProfile(image,"iptc");
5233                   if (profile != (const StringInfo *) NULL)
5234                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5235                       GetStringInfoLength(profile));
5236                 }
5237               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5238               continue;
5239             }
5240           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5241             {
5242               if (image != (Image *) NULL)
5243                 s=newSViv((ssize_t) image->iterations);
5244               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5245               continue;
5246             }
5247           if (LocaleCompare(attribute,"interlace") == 0)
5248             {
5249               j=info ? info->image_info->interlace : image ? image->interlace :
5250                 UndefinedInterlace;
5251               s=newSViv(j);
5252               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5253                 j));
5254               SvIOK_on(s);
5255               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5256               continue;
5257             }
5258           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5259             attribute);
5260           break;
5261         }
5262         case 'L':
5263         case 'l':
5264         {
5265           if (LocaleCompare(attribute,"label") == 0)
5266             {
5267               const char
5268                 *value;
5269
5270               if (image == (Image *) NULL)
5271                 break;
5272               value=GetImageProperty(image,"Label",exception);
5273               if (value != (const char *) NULL)
5274                 s=newSVpv(value,0);
5275               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5276               continue;
5277             }
5278           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5279             {
5280               if (image != (Image *) NULL)
5281                 s=newSViv((ssize_t) image->iterations);
5282               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5283               continue;
5284             }
5285           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5286             attribute);
5287           break;
5288         }
5289         case 'M':
5290         case 'm':
5291         {
5292           if (LocaleCompare(attribute,"magick") == 0)
5293             {
5294               if (info && *info->image_info->magick)
5295                 s=newSVpv(info->image_info->magick,0);
5296               if (image != (Image *) NULL)
5297                 s=newSVpv(image->magick,0);
5298               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5299               continue;
5300             }
5301           if (LocaleCompare(attribute,"map") == 0)
5302             {
5303               s=newSViv(GetMagickResource(MapResource));
5304               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5305               continue;
5306             }
5307           if (LocaleCompare(attribute,"maximum-error") == 0)
5308             {
5309               if (image != (Image *) NULL)
5310                 s=newSVnv(image->error.normalized_maximum_error);
5311               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5312               continue;
5313             }
5314           if (LocaleCompare(attribute,"memory") == 0)
5315             {
5316               s=newSViv(GetMagickResource(MemoryResource));
5317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5318               continue;
5319             }
5320           if (LocaleCompare(attribute,"mean-error") == 0)
5321             {
5322               if (image != (Image *) NULL)
5323                 s=newSVnv(image->error.normalized_mean_error);
5324               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5325               continue;
5326             }
5327           if (LocaleCompare(attribute,"mime") == 0)
5328             {
5329               if (info && *info->image_info->magick)
5330                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5331               if (image != (Image *) NULL)
5332                 s=newSVpv(MagickToMime(image->magick),0);
5333               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5334               continue;
5335             }
5336           if (LocaleCompare(attribute,"mattecolor") == 0)
5337             {
5338               if (image == (Image *) NULL)
5339                 break;
5340               (void) FormatLocaleString(color,MagickPathExtent,
5341                 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5342                 (double) image->alpha_color.green,
5343                 (double) image->alpha_color.blue,
5344                 (double) image->alpha_color.alpha);
5345               s=newSVpv(color,0);
5346               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5347               continue;
5348             }
5349           if (LocaleCompare(attribute,"matte") == 0)
5350             {
5351               if (image != (Image *) NULL)
5352                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5353                   1 : 0);
5354               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5355               continue;
5356             }
5357           if (LocaleCompare(attribute,"mime") == 0)
5358             {
5359               const char
5360                 *magick;
5361
5362               magick=NULL;
5363               if (info && *info->image_info->magick)
5364                 magick=info->image_info->magick;
5365               if (image != (Image *) NULL)
5366                 magick=image->magick;
5367               if (magick)
5368                 {
5369                   char
5370                     *mime;
5371
5372                   mime=MagickToMime(magick);
5373                   s=newSVpv(mime,0);
5374                   mime=(char *) RelinquishMagickMemory(mime);
5375                 }
5376               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5377               continue;
5378             }
5379           if (LocaleCompare(attribute,"monochrome") == 0)
5380             {
5381               if (image == (Image *) NULL)
5382                 continue;
5383               j=info ? info->image_info->monochrome :
5384                 SetImageMonochrome(image,exception);
5385               s=newSViv(j);
5386               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5387               continue;
5388             }
5389           if (LocaleCompare(attribute,"montage") == 0)
5390             {
5391               if (image && image->montage)
5392                 s=newSVpv(image->montage,0);
5393               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5394               continue;
5395             }
5396           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5397             attribute);
5398           break;
5399         }
5400         case 'O':
5401         case 'o':
5402         {
5403           if (LocaleCompare(attribute,"orientation") == 0)
5404             {
5405               j=info ? info->image_info->orientation : image ?
5406                 image->orientation : UndefinedOrientation;
5407               s=newSViv(j);
5408               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5409                 j));
5410               SvIOK_on(s);
5411               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5412               continue;
5413             }
5414           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5415             attribute);
5416           break;
5417         }
5418         case 'P':
5419         case 'p':
5420         {
5421           if (LocaleCompare(attribute,"page") == 0)
5422             {
5423               if (info && info->image_info->page)
5424                 s=newSVpv(info->image_info->page,0);
5425               if (image != (Image *) NULL)
5426                 {
5427                   char
5428                     geometry[MagickPathExtent];
5429
5430                   (void) FormatLocaleString(geometry,MagickPathExtent,
5431                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5432                     (double) image->page.height,(double) image->page.x,(double)
5433                     image->page.y);
5434                   s=newSVpv(geometry,0);
5435                 }
5436               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5437               continue;
5438             }
5439           if (LocaleCompare(attribute,"page.x") == 0)
5440             {
5441               if (image != (Image *) NULL)
5442                 s=newSViv((ssize_t) image->page.x);
5443               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5444               continue;
5445             }
5446           if (LocaleCompare(attribute,"page.y") == 0)
5447             {
5448               if (image != (Image *) NULL)
5449                 s=newSViv((ssize_t) image->page.y);
5450               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5451               continue;
5452             }
5453           if (LocaleNCompare(attribute,"pixel",5) == 0)
5454             {
5455               char
5456                 tuple[MagickPathExtent];
5457
5458               int
5459                 items;
5460
5461               long
5462                 x,
5463                 y;
5464
5465               register const Quantum
5466                 *p;
5467
5468               if (image == (Image *) NULL)
5469                 break;
5470               x=0;
5471               y=0;
5472               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5473               (void) items;
5474               p=GetVirtualPixels(image,x,y,1,1,exception);
5475               if (image->colorspace != CMYKColorspace)
5476                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5477                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5478                   GetPixelRed(image,p),GetPixelGreen(image,p),
5479                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5480               else
5481                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5482                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5483                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5484                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5485                   GetPixelAlpha(image,p));
5486               s=newSVpv(tuple,0);
5487               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5488               continue;
5489             }
5490           if (LocaleCompare(attribute,"pointsize") == 0)
5491             {
5492               if (info)
5493                 s=newSViv((ssize_t) info->image_info->pointsize);
5494               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5495               continue;
5496             }
5497           if (LocaleCompare(attribute,"preview") == 0)
5498             {
5499               s=newSViv(info->image_info->preview_type);
5500               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5501                 info->image_info->preview_type));
5502               SvIOK_on(s);
5503               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5504               continue;
5505             }
5506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5507             attribute);
5508           break;
5509         }
5510         case 'Q':
5511         case 'q':
5512         {
5513           if (LocaleCompare(attribute,"quality") == 0)
5514             {
5515               if (info)
5516                 s=newSViv((ssize_t) info->image_info->quality);
5517               if (image != (Image *) NULL)
5518                 s=newSViv((ssize_t) image->quality);
5519               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5520               continue;
5521             }
5522           if (LocaleCompare(attribute,"quantum") == 0)
5523             {
5524               if (info)
5525                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5526               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5527               continue;
5528             }
5529           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5530             attribute);
5531           break;
5532         }
5533         case 'R':
5534         case 'r':
5535         {
5536           if (LocaleCompare(attribute,"rendering-intent") == 0)
5537             {
5538               s=newSViv(image->rendering_intent);
5539               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5540                 image->rendering_intent));
5541               SvIOK_on(s);
5542               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5543               continue;
5544             }
5545           if (LocaleCompare(attribute,"red-primary") == 0)
5546             {
5547               if (image == (Image *) NULL)
5548                 break;
5549               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5550                 image->chromaticity.red_primary.x,
5551                 image->chromaticity.red_primary.y);
5552               s=newSVpv(color,0);
5553               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5554               continue;
5555             }
5556           if (LocaleCompare(attribute,"rows") == 0)
5557             {
5558               if (image != (Image *) NULL)
5559                 s=newSViv((ssize_t) image->rows);
5560               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5561               continue;
5562             }
5563           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5564             attribute);
5565           break;
5566         }
5567         case 'S':
5568         case 's':
5569         {
5570           if (LocaleCompare(attribute,"sampling-factor") == 0)
5571             {
5572               if (info && info->image_info->sampling_factor)
5573                 s=newSVpv(info->image_info->sampling_factor,0);
5574               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5575               continue;
5576             }
5577           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5578             {
5579               if (info && info->image_info->server_name)
5580                 s=newSVpv(info->image_info->server_name,0);
5581               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5582               continue;
5583             }
5584           if (LocaleCompare(attribute,"size") == 0)
5585             {
5586               if (info && info->image_info->size)
5587                 s=newSVpv(info->image_info->size,0);
5588               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5589               continue;
5590             }
5591           if (LocaleCompare(attribute,"scene") == 0)
5592             {
5593               if (image != (Image *) NULL)
5594                 s=newSViv((ssize_t) image->scene);
5595               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5596               continue;
5597             }
5598           if (LocaleCompare(attribute,"scenes") == 0)
5599             {
5600               if (image != (Image *) NULL)
5601                 s=newSViv((ssize_t) info->image_info->number_scenes);
5602               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5603               continue;
5604             }
5605           if (LocaleCompare(attribute,"signature") == 0)
5606             {
5607               const char
5608                 *value;
5609
5610               if (image == (Image *) NULL)
5611                 break;
5612               (void) SignatureImage(image,exception);
5613               value=GetImageProperty(image,"Signature",exception);
5614               if (value != (const char *) NULL)
5615                 s=newSVpv(value,0);
5616               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5617               continue;
5618             }
5619           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5620             attribute);
5621           break;
5622         }
5623         case 'T':
5624         case 't':
5625         {
5626           if (LocaleCompare(attribute,"taint") == 0)
5627             {
5628               if (image != (Image *) NULL)
5629                 s=newSViv((ssize_t) IsTaintImage(image));
5630               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5631               continue;
5632             }
5633           if (LocaleCompare(attribute,"texture") == 0)
5634             {
5635               if (info && info->image_info->texture)
5636                 s=newSVpv(info->image_info->texture,0);
5637               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5638               continue;
5639             }
5640           if (LocaleCompare(attribute,"total-ink-density") == 0)
5641             {
5642               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5643               if (image != (Image *) NULL)
5644                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5645               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5646               continue;
5647             }
5648           if (LocaleCompare(attribute,"transparent-color") == 0)
5649             {
5650               if (image == (Image *) NULL)
5651                 break;
5652               (void) FormatLocaleString(color,MagickPathExtent,
5653                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5654                 (double) image->transparent_color.green,
5655                 (double) image->transparent_color.blue,
5656                 (double) image->transparent_color.alpha);
5657               s=newSVpv(color,0);
5658               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5659               continue;
5660             }
5661           if (LocaleCompare(attribute,"type") == 0)
5662             {
5663               if (image == (Image *) NULL)
5664                 break;
5665               j=(ssize_t) GetImageType(image);
5666               s=newSViv(j);
5667               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5668               SvIOK_on(s);
5669               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5670               continue;
5671             }
5672           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5673             attribute);
5674           break;
5675         }
5676         case 'U':
5677         case 'u':
5678         {
5679           if (LocaleCompare(attribute,"units") == 0)
5680             {
5681               j=info ? info->image_info->units : image ? image->units :
5682                 UndefinedResolution;
5683               if (info && (info->image_info->units == UndefinedResolution))
5684                 if (image)
5685                   j=image->units;
5686               if (j == UndefinedResolution)
5687                 s=newSVpv("undefined units",0);
5688               else
5689                 if (j == PixelsPerInchResolution)
5690                   s=newSVpv("pixels / inch",0);
5691                 else
5692                   s=newSVpv("pixels / centimeter",0);
5693               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5694               continue;
5695             }
5696           if (LocaleCompare(attribute,"user-time") == 0)
5697             {
5698               if (image != (Image *) NULL)
5699                 s=newSVnv(GetUserTime(&image->timer));
5700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5701               continue;
5702             }
5703           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5704             attribute);
5705           break;
5706         }
5707         case 'V':
5708         case 'v':
5709         {
5710           if (LocaleCompare(attribute,"verbose") == 0)
5711             {
5712               if (info)
5713                 s=newSViv((ssize_t) info->image_info->verbose);
5714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5715               continue;
5716             }
5717           if (LocaleCompare(attribute,"version") == 0)
5718             {
5719               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5720               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5721               continue;
5722             }
5723           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5724             {
5725               if (image == (Image *) NULL)
5726                 break;
5727               j=(ssize_t) GetImageVirtualPixelMethod(image);
5728               s=newSViv(j);
5729               (void) sv_setpv(s,CommandOptionToMnemonic(
5730                 MagickVirtualPixelOptions,j));
5731               SvIOK_on(s);
5732               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5733               continue;
5734             }
5735           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5736             attribute);
5737           break;
5738         }
5739         case 'W':
5740         case 'w':
5741         {
5742           if (LocaleCompare(attribute,"white-point") == 0)
5743             {
5744               if (image == (Image *) NULL)
5745                 break;
5746               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5747                 image->chromaticity.white_point.x,
5748                 image->chromaticity.white_point.y);
5749               s=newSVpv(color,0);
5750               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5751               continue;
5752             }
5753           if (LocaleCompare(attribute,"width") == 0)
5754             {
5755               if (image != (Image *) NULL)
5756                 s=newSViv((ssize_t) image->columns);
5757               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5758               continue;
5759             }
5760           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5761              attribute);
5762           break;
5763         }
5764         case 'X':
5765         case 'x':
5766         {
5767           if (LocaleCompare(attribute,"xmp") == 0)
5768             {
5769               if (image != (Image *) NULL)
5770                 {
5771                   const StringInfo
5772                     *profile;
5773
5774                   profile=GetImageProfile(image,"xmp");
5775                   if (profile != (StringInfo *) NULL)
5776                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5777                       GetStringInfoLength(profile));
5778                 }
5779               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5780               continue;
5781             }
5782           if (LocaleCompare(attribute,"x-resolution") == 0)
5783             {
5784               if (image != (Image *) NULL)
5785                 s=newSVnv(image->resolution.x);
5786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5787               continue;
5788             }
5789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5790             attribute);
5791           break;
5792         }
5793         case 'Y':
5794         case 'y':
5795         {
5796           if (LocaleCompare(attribute,"y-resolution") == 0)
5797             {
5798               if (image != (Image *) NULL)
5799                 s=newSVnv(image->resolution.y);
5800               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5801               continue;
5802             }
5803           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5804             attribute);
5805           break;
5806         }
5807         default:
5808           break;
5809       }
5810       if (image == (Image *) NULL)
5811         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5812           attribute)
5813       else
5814         {
5815           value=GetImageProperty(image,attribute,exception);
5816           if (value != (const char *) NULL)
5817             {
5818               s=newSVpv(value,0);
5819               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5820             }
5821           else
5822             if (*attribute != '%')
5823               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5824                 attribute)
5825             else
5826               {
5827                  char
5828                    *meta;
5829
5830                  meta=InterpretImageProperties(info ? info->image_info :
5831                    (ImageInfo *) NULL,image,attribute,exception);
5832                  s=newSVpv(meta,0);
5833                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5834                  meta=(char *) RelinquishMagickMemory(meta);
5835               }
5836         }
5837     }
5838     exception=DestroyExceptionInfo(exception);
5839     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5840   }
5841 \f
5842 #
5843 ###############################################################################
5844 #                                                                             #
5845 #                                                                             #
5846 #                                                                             #
5847 #   G e t A u t h e n t i c P i x e l s                                       #
5848 #                                                                             #
5849 #                                                                             #
5850 #                                                                             #
5851 ###############################################################################
5852 #
5853 #
5854 void *
5855 GetAuthenticPixels(ref,...)
5856   Image::Magick ref = NO_INIT
5857   ALIAS:
5858     getauthenticpixels = 1
5859     GetImagePixels = 2
5860     getimagepixels = 3
5861   CODE:
5862   {
5863     char
5864       *attribute;
5865
5866     ExceptionInfo
5867       *exception;
5868
5869     Image
5870       *image;
5871
5872     RectangleInfo
5873       region;
5874
5875     ssize_t
5876       i;
5877
5878     struct PackageInfo
5879       *info;
5880
5881     SV
5882       *perl_exception,
5883       *reference;
5884
5885     void
5886       *blob = NULL;
5887
5888     PERL_UNUSED_VAR(ref);
5889     PERL_UNUSED_VAR(ix);
5890     exception=AcquireExceptionInfo();
5891     perl_exception=newSVpv("",0);
5892     if (sv_isobject(ST(0)) == 0)
5893       {
5894         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5895           PackageName);
5896         goto PerlException;
5897       }
5898     reference=SvRV(ST(0));
5899
5900     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5901     if (image == (Image *) NULL)
5902       {
5903         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5904           PackageName);
5905         goto PerlException;
5906       }
5907
5908     region.x=0;
5909     region.y=0;
5910     region.width=image->columns;
5911     region.height=1;
5912     if (items == 1)
5913       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5914     for (i=2; i < items; i+=2)
5915     {
5916       attribute=(char *) SvPV(ST(i-1),na);
5917       switch (*attribute)
5918       {
5919         case 'g':
5920         case 'G':
5921         {
5922           if (LocaleCompare(attribute,"geometry") == 0)
5923             {
5924               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5925               break;
5926             }
5927           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5928             attribute);
5929           break;
5930         }
5931         case 'H':
5932         case 'h':
5933         {
5934           if (LocaleCompare(attribute,"height") == 0)
5935             {
5936               region.height=SvIV(ST(i));
5937               continue;
5938             }
5939           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5940             attribute);
5941           break;
5942         }
5943         case 'X':
5944         case 'x':
5945         {
5946           if (LocaleCompare(attribute,"x") == 0)
5947             {
5948               region.x=SvIV(ST(i));
5949               continue;
5950             }
5951           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5952             attribute);
5953           break;
5954         }
5955         case 'Y':
5956         case 'y':
5957         {
5958           if (LocaleCompare(attribute,"y") == 0)
5959             {
5960               region.y=SvIV(ST(i));
5961               continue;
5962             }
5963           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5964             attribute);
5965           break;
5966         }
5967         case 'W':
5968         case 'w':
5969         {
5970           if (LocaleCompare(attribute,"width") == 0)
5971             {
5972               region.width=SvIV(ST(i));
5973               continue;
5974             }
5975           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5976             attribute);
5977           break;
5978         }
5979       }
5980     }
5981     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5982       region.height,exception);
5983     if (blob != (void *) NULL)
5984       goto PerlEnd;
5985
5986   PerlException:
5987     InheritPerlException(exception,perl_exception);
5988     exception=DestroyExceptionInfo(exception);
5989     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5990
5991   PerlEnd:
5992     RETVAL = blob;
5993   }
5994   OUTPUT:
5995     RETVAL
5996 \f
5997 #
5998 ###############################################################################
5999 #                                                                             #
6000 #                                                                             #
6001 #                                                                             #
6002 #   G e t V i r t u a l P i x e l s                                           #
6003 #                                                                             #
6004 #                                                                             #
6005 #                                                                             #
6006 ###############################################################################
6007 #
6008 #
6009 void *
6010 GetVirtualPixels(ref,...)
6011   Image::Magick ref = NO_INIT
6012   ALIAS:
6013     getvirtualpixels = 1
6014     AcquireImagePixels = 2
6015     acquireimagepixels = 3
6016   CODE:
6017   {
6018     char
6019       *attribute;
6020
6021     const void
6022       *blob = NULL;
6023
6024     ExceptionInfo
6025       *exception;
6026
6027     Image
6028       *image;
6029
6030     RectangleInfo
6031       region;
6032
6033     ssize_t
6034       i;
6035
6036     struct PackageInfo
6037       *info;
6038
6039     SV
6040       *perl_exception,
6041       *reference;
6042
6043     PERL_UNUSED_VAR(ref);
6044     PERL_UNUSED_VAR(ix);
6045     exception=AcquireExceptionInfo();
6046     perl_exception=newSVpv("",0);
6047     if (sv_isobject(ST(0)) == 0)
6048       {
6049         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6050           PackageName);
6051         goto PerlException;
6052       }
6053     reference=SvRV(ST(0));
6054
6055     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6056     if (image == (Image *) NULL)
6057       {
6058         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6059           PackageName);
6060         goto PerlException;
6061       }
6062
6063     region.x=0;
6064     region.y=0;
6065     region.width=image->columns;
6066     region.height=1;
6067     if (items == 1)
6068       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6069     for (i=2; i < items; i+=2)
6070     {
6071       attribute=(char *) SvPV(ST(i-1),na);
6072       switch (*attribute)
6073       {
6074         case 'g':
6075         case 'G':
6076         {
6077           if (LocaleCompare(attribute,"geometry") == 0)
6078             {
6079               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6080               break;
6081             }
6082           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6083             attribute);
6084           break;
6085         }
6086         case 'H':
6087         case 'h':
6088         {
6089           if (LocaleCompare(attribute,"height") == 0)
6090             {
6091               region.height=SvIV(ST(i));
6092               continue;
6093             }
6094           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6095             attribute);
6096           break;
6097         }
6098         case 'X':
6099         case 'x':
6100         {
6101           if (LocaleCompare(attribute,"x") == 0)
6102             {
6103               region.x=SvIV(ST(i));
6104               continue;
6105             }
6106           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6107             attribute);
6108           break;
6109         }
6110         case 'Y':
6111         case 'y':
6112         {
6113           if (LocaleCompare(attribute,"y") == 0)
6114             {
6115               region.y=SvIV(ST(i));
6116               continue;
6117             }
6118           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6119             attribute);
6120           break;
6121         }
6122         case 'W':
6123         case 'w':
6124         {
6125           if (LocaleCompare(attribute,"width") == 0)
6126             {
6127               region.width=SvIV(ST(i));
6128               continue;
6129             }
6130           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6131             attribute);
6132           break;
6133         }
6134       }
6135     }
6136     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6137       region.height,exception);
6138     if (blob != (void *) NULL)
6139       goto PerlEnd;
6140
6141   PerlException:
6142     InheritPerlException(exception,perl_exception);
6143     exception=DestroyExceptionInfo(exception);
6144     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6145
6146   PerlEnd:
6147     RETVAL = (void *) blob;
6148   }
6149   OUTPUT:
6150     RETVAL
6151 \f
6152 #
6153 ###############################################################################
6154 #                                                                             #
6155 #                                                                             #
6156 #                                                                             #
6157 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6158 #                                                                             #
6159 #                                                                             #
6160 #                                                                             #
6161 ###############################################################################
6162 #
6163 #
6164 void *
6165 GetAuthenticMetacontent(ref,...)
6166   Image::Magick ref = NO_INIT
6167   ALIAS:
6168     getauthenticmetacontent = 1
6169     GetMetacontent = 2
6170     getmetacontent = 3
6171   CODE:
6172   {
6173     ExceptionInfo
6174       *exception;
6175
6176     Image
6177       *image;
6178
6179     struct PackageInfo
6180       *info;
6181
6182     SV
6183       *perl_exception,
6184       *reference;
6185
6186     void
6187       *blob = NULL;
6188
6189     PERL_UNUSED_VAR(ref);
6190     PERL_UNUSED_VAR(ix);
6191     exception=AcquireExceptionInfo();
6192     perl_exception=newSVpv("",0);
6193     if (sv_isobject(ST(0)) == 0)
6194       {
6195         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6196           PackageName);
6197         goto PerlException;
6198       }
6199     reference=SvRV(ST(0));
6200
6201     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6202     if (image == (Image *) NULL)
6203       {
6204         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6205           PackageName);
6206         goto PerlException;
6207       }
6208
6209     blob=(void *) GetAuthenticMetacontent(image);
6210     if (blob != (void *) NULL)
6211       goto PerlEnd;
6212
6213   PerlException:
6214     InheritPerlException(exception,perl_exception);
6215     exception=DestroyExceptionInfo(exception);
6216     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6217
6218   PerlEnd:
6219     RETVAL = blob;
6220   }
6221   OUTPUT:
6222     RETVAL
6223 \f
6224 #
6225 ###############################################################################
6226 #                                                                             #
6227 #                                                                             #
6228 #                                                                             #
6229 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6230 #                                                                             #
6231 #                                                                             #
6232 #                                                                             #
6233 ###############################################################################
6234 #
6235 #
6236 void *
6237 GetVirtualMetacontent(ref,...)
6238   Image::Magick ref = NO_INIT
6239   ALIAS:
6240     getvirtualmetacontent = 1
6241   CODE:
6242   {
6243     ExceptionInfo
6244       *exception;
6245
6246     Image
6247       *image;
6248
6249     struct PackageInfo
6250       *info;
6251
6252     SV
6253       *perl_exception,
6254       *reference;
6255
6256     void
6257       *blob = NULL;
6258
6259     PERL_UNUSED_VAR(ref);
6260     PERL_UNUSED_VAR(ix);
6261     exception=AcquireExceptionInfo();
6262     perl_exception=newSVpv("",0);
6263     if (sv_isobject(ST(0)) == 0)
6264       {
6265         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6266           PackageName);
6267         goto PerlException;
6268       }
6269     reference=SvRV(ST(0));
6270
6271     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6272     if (image == (Image *) NULL)
6273       {
6274         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6275           PackageName);
6276         goto PerlException;
6277       }
6278
6279     blob=(void *) GetVirtualMetacontent(image);
6280     if (blob != (void *) NULL)
6281       goto PerlEnd;
6282
6283   PerlException:
6284     InheritPerlException(exception,perl_exception);
6285     exception=DestroyExceptionInfo(exception);
6286     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6287
6288   PerlEnd:
6289     RETVAL = blob;
6290   }
6291   OUTPUT:
6292     RETVAL
6293 \f
6294 #
6295 ###############################################################################
6296 #                                                                             #
6297 #                                                                             #
6298 #                                                                             #
6299 #   H i s t o g r a m                                                         #
6300 #                                                                             #
6301 #                                                                             #
6302 #                                                                             #
6303 ###############################################################################
6304 #
6305 #
6306 void
6307 Histogram(ref,...)
6308   Image::Magick ref=NO_INIT
6309   ALIAS:
6310     HistogramImage = 1
6311     histogram      = 2
6312     histogramimage = 3
6313   PPCODE:
6314   {
6315     AV
6316       *av;
6317
6318     char
6319       message[MagickPathExtent];
6320
6321     PixelInfo
6322       *histogram;
6323
6324     ExceptionInfo
6325       *exception;
6326
6327     Image
6328       *image;
6329
6330     register ssize_t
6331       i;
6332
6333     ssize_t
6334       count;
6335
6336     struct PackageInfo
6337       *info;
6338
6339     SV
6340       *perl_exception,
6341       *reference;
6342
6343     size_t
6344       number_colors;
6345
6346     PERL_UNUSED_VAR(ref);
6347     PERL_UNUSED_VAR(ix);
6348     exception=AcquireExceptionInfo();
6349     perl_exception=newSVpv("",0);
6350     av=NULL;
6351     if (sv_isobject(ST(0)) == 0)
6352       {
6353         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6354           PackageName);
6355         goto PerlException;
6356       }
6357     reference=SvRV(ST(0));
6358     av=newAV();
6359     SvREFCNT_dec(av);
6360     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6361     if (image == (Image *) NULL)
6362       {
6363         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6364           PackageName);
6365         goto PerlException;
6366       }
6367     count=0;
6368     for ( ; image; image=image->next)
6369     {
6370       histogram=GetImageHistogram(image,&number_colors,exception);
6371       if (histogram == (PixelInfo *) NULL)
6372         continue;
6373       count+=(ssize_t) number_colors;
6374       EXTEND(sp,6*count);
6375       for (i=0; i < (ssize_t) number_colors; i++)
6376       {
6377         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6378           histogram[i].red);
6379         PUSHs(sv_2mortal(newSVpv(message,0)));
6380         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6381           histogram[i].green);
6382         PUSHs(sv_2mortal(newSVpv(message,0)));
6383         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6384           histogram[i].blue);
6385         PUSHs(sv_2mortal(newSVpv(message,0)));
6386         if (image->colorspace == CMYKColorspace)
6387           {
6388             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6389               histogram[i].black);
6390             PUSHs(sv_2mortal(newSVpv(message,0)));
6391           }
6392         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6393           histogram[i].alpha);
6394         PUSHs(sv_2mortal(newSVpv(message,0)));
6395         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6396           histogram[i].count);
6397         PUSHs(sv_2mortal(newSVpv(message,0)));
6398       }
6399       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6400     }
6401
6402   PerlException:
6403     InheritPerlException(exception,perl_exception);
6404     exception=DestroyExceptionInfo(exception);
6405     SvREFCNT_dec(perl_exception);
6406   }
6407 \f
6408 #
6409 ###############################################################################
6410 #                                                                             #
6411 #                                                                             #
6412 #                                                                             #
6413 #   G e t P i x e l                                                           #
6414 #                                                                             #
6415 #                                                                             #
6416 #                                                                             #
6417 ###############################################################################
6418 #
6419 #
6420 void
6421 GetPixel(ref,...)
6422   Image::Magick ref=NO_INIT
6423   ALIAS:
6424     getpixel = 1
6425     getPixel = 2
6426   PPCODE:
6427   {
6428     AV
6429       *av;
6430
6431     char
6432       *attribute;
6433
6434     ExceptionInfo
6435       *exception;
6436
6437     Image
6438       *image;
6439
6440     MagickBooleanType
6441       normalize;
6442
6443     RectangleInfo
6444       region;
6445
6446     register const Quantum
6447       *p;
6448
6449     register ssize_t
6450       i;
6451
6452     ssize_t
6453       option;
6454
6455     struct PackageInfo
6456       *info;
6457
6458     SV
6459       *perl_exception,
6460       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6461
6462     PERL_UNUSED_VAR(ref);
6463     PERL_UNUSED_VAR(ix);
6464     exception=AcquireExceptionInfo();
6465     perl_exception=newSVpv("",0);
6466     reference=SvRV(ST(0));
6467     av=(AV *) reference;
6468     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6469       exception);
6470     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6471     if (image == (Image *) NULL)
6472       {
6473         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6474           PackageName);
6475         goto PerlException;
6476       }
6477     normalize=MagickTrue;
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 'C':
6490         case 'c':
6491         {
6492           if (LocaleCompare(attribute,"channel") == 0)
6493             {
6494               ssize_t
6495                 option;
6496
6497               option=ParseChannelOption(SvPV(ST(i),na));
6498               if (option < 0)
6499                 {
6500                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6501                     SvPV(ST(i),na));
6502                   return;
6503                 }
6504               (void) SetPixelChannelMask(image,(ChannelType) option);
6505               break;
6506             }
6507           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6508             attribute);
6509           break;
6510         }
6511         case 'g':
6512         case 'G':
6513         {
6514           if (LocaleCompare(attribute,"geometry") == 0)
6515             {
6516               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6517               break;
6518             }
6519           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6520             attribute);
6521           break;
6522         }
6523         case 'N':
6524         case 'n':
6525         {
6526           if (LocaleCompare(attribute,"normalize") == 0)
6527             {
6528               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6529                 SvPV(ST(i),na));
6530               if (option < 0)
6531                 {
6532                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6533                     SvPV(ST(i),na));
6534                   break;
6535                 }
6536              normalize=option != 0 ? MagickTrue : MagickFalse;
6537              break;
6538             }
6539           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6540             attribute);
6541           break;
6542         }
6543         case 'x':
6544         case 'X':
6545         {
6546           if (LocaleCompare(attribute,"x") == 0)
6547             {
6548               region.x=SvIV(ST(i));
6549               break;
6550             }
6551           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6552             attribute);
6553           break;
6554         }
6555         case 'y':
6556         case 'Y':
6557         {
6558           if (LocaleCompare(attribute,"y") == 0)
6559             {
6560               region.y=SvIV(ST(i));
6561               break;
6562             }
6563           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6564             attribute);
6565           break;
6566         }
6567         default:
6568         {
6569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6570             attribute);
6571           break;
6572         }
6573       }
6574     }
6575     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6576     if (p == (const Quantum *) NULL)
6577       PUSHs(&sv_undef);
6578     else
6579       {
6580         double
6581           scale;
6582
6583         scale=1.0;
6584         if (normalize != MagickFalse)
6585           scale=1.0/QuantumRange;
6586         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6587           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6588         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6589           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6590         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6591           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6592         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6593             (image->colorspace == CMYKColorspace))
6594           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6595         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6596           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6597       }
6598
6599   PerlException:
6600     InheritPerlException(exception,perl_exception);
6601     exception=DestroyExceptionInfo(exception);
6602     SvREFCNT_dec(perl_exception);
6603   }
6604 \f
6605 #
6606 ###############################################################################
6607 #                                                                             #
6608 #                                                                             #
6609 #                                                                             #
6610 #   G e t P i x e l s                                                         #
6611 #                                                                             #
6612 #                                                                             #
6613 #                                                                             #
6614 ###############################################################################
6615 #
6616 #
6617 void
6618 GetPixels(ref,...)
6619   Image::Magick ref=NO_INIT
6620   ALIAS:
6621     getpixels = 1
6622     getPixels = 2
6623   PPCODE:
6624   {
6625     AV
6626       *av;
6627
6628     char
6629       *attribute;
6630
6631     const char
6632       *map;
6633
6634     ExceptionInfo
6635       *exception;
6636
6637     Image
6638       *image;
6639
6640     MagickBooleanType
6641       normalize,
6642       status;
6643
6644     RectangleInfo
6645       region;
6646
6647     register ssize_t
6648       i;
6649
6650     ssize_t
6651       option;
6652
6653     struct PackageInfo
6654       *info;
6655
6656     SV
6657       *perl_exception,
6658       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6659
6660     PERL_UNUSED_VAR(ref);
6661     PERL_UNUSED_VAR(ix);
6662     exception=AcquireExceptionInfo();
6663     perl_exception=newSVpv("",0);
6664     reference=SvRV(ST(0));
6665     av=(AV *) reference;
6666     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6667       exception);
6668     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6669     if (image == (Image *) NULL)
6670       {
6671         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6672           PackageName);
6673         goto PerlException;
6674       }
6675     map="RGB";
6676     if (image->alpha_trait != UndefinedPixelTrait)
6677       map="RGBA";
6678     if (image->colorspace == CMYKColorspace)
6679       {
6680         map="CMYK";
6681         if (image->alpha_trait != UndefinedPixelTrait)
6682           map="CMYKA";
6683       }
6684     normalize=MagickFalse;
6685     region.x=0;
6686     region.y=0;
6687     region.width=image->columns;
6688     region.height=1;
6689     if (items == 1)
6690       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6691     for (i=2; i < items; i+=2)
6692     {
6693       attribute=(char *) SvPV(ST(i-1),na);
6694       switch (*attribute)
6695       {
6696         case 'g':
6697         case 'G':
6698         {
6699           if (LocaleCompare(attribute,"geometry") == 0)
6700             {
6701               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6702               break;
6703             }
6704           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6705             attribute);
6706           break;
6707         }
6708         case 'H':
6709         case 'h':
6710         {
6711           if (LocaleCompare(attribute,"height") == 0)
6712             {
6713               region.height=SvIV(ST(i));
6714               break;
6715             }
6716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6717             attribute);
6718           break;
6719         }
6720         case 'M':
6721         case 'm':
6722         {
6723           if (LocaleCompare(attribute,"map") == 0)
6724             {
6725               map=SvPV(ST(i),na);
6726               break;
6727             }
6728           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6729             attribute);
6730           break;
6731         }
6732         case 'N':
6733         case 'n':
6734         {
6735           if (LocaleCompare(attribute,"normalize") == 0)
6736             {
6737               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6738                 SvPV(ST(i),na));
6739               if (option < 0)
6740                 {
6741                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6742                     SvPV(ST(i),na));
6743                   break;
6744                 }
6745              normalize=option != 0 ? MagickTrue : MagickFalse;
6746              break;
6747             }
6748           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6749             attribute);
6750           break;
6751         }
6752         case 'W':
6753         case 'w':
6754         {
6755           if (LocaleCompare(attribute,"width") == 0)
6756             {
6757               region.width=SvIV(ST(i));
6758               break;
6759             }
6760           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6761             attribute);
6762           break;
6763         }
6764         case 'x':
6765         case 'X':
6766         {
6767           if (LocaleCompare(attribute,"x") == 0)
6768             {
6769               region.x=SvIV(ST(i));
6770               break;
6771             }
6772           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6773             attribute);
6774           break;
6775         }
6776         case 'y':
6777         case 'Y':
6778         {
6779           if (LocaleCompare(attribute,"y") == 0)
6780             {
6781               region.y=SvIV(ST(i));
6782               break;
6783             }
6784           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6785             attribute);
6786           break;
6787         }
6788         default:
6789         {
6790           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6791             attribute);
6792           break;
6793         }
6794       }
6795     }
6796     if (normalize != MagickFalse)
6797       {
6798         float
6799           *pixels;
6800
6801         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6802           region.height*sizeof(*pixels));
6803         if (pixels == (float *) NULL)
6804           {
6805             ThrowPerlException(exception,ResourceLimitError,
6806               "MemoryAllocationFailed",PackageName);
6807             goto PerlException;
6808           }
6809         status=ExportImagePixels(image,region.x,region.y,region.width,
6810           region.height,map,FloatPixel,pixels,exception);
6811         if (status == MagickFalse)
6812           PUSHs(&sv_undef);
6813         else
6814           {
6815             EXTEND(sp,strlen(map)*region.width*region.height);
6816             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6817               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6818           }
6819         pixels=(float *) RelinquishMagickMemory(pixels);
6820       }
6821     else
6822       {
6823         Quantum
6824           *pixels;
6825
6826         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6827           region.height*sizeof(*pixels));
6828         if (pixels == (Quantum *) NULL)
6829           {
6830             ThrowPerlException(exception,ResourceLimitError,
6831               "MemoryAllocationFailed",PackageName);
6832             goto PerlException;
6833           }
6834         status=ExportImagePixels(image,region.x,region.y,region.width,
6835           region.height,map,QuantumPixel,pixels,exception);
6836         if (status == MagickFalse)
6837           PUSHs(&sv_undef);
6838         else
6839           {
6840             EXTEND(sp,strlen(map)*region.width*region.height);
6841             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6842               PUSHs(sv_2mortal(newSViv(pixels[i])));
6843           }
6844         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6845       }
6846
6847   PerlException:
6848     InheritPerlException(exception,perl_exception);
6849     exception=DestroyExceptionInfo(exception);
6850     SvREFCNT_dec(perl_exception);
6851   }
6852 \f
6853 #
6854 ###############################################################################
6855 #                                                                             #
6856 #                                                                             #
6857 #                                                                             #
6858 #   I m a g e T o B l o b                                                     #
6859 #                                                                             #
6860 #                                                                             #
6861 #                                                                             #
6862 ###############################################################################
6863 #
6864 #
6865 void
6866 ImageToBlob(ref,...)
6867   Image::Magick ref=NO_INIT
6868   ALIAS:
6869     ImageToBlob  = 1
6870     imagetoblob  = 2
6871     toblob       = 3
6872     blob         = 4
6873   PPCODE:
6874   {
6875     char
6876       filename[MagickPathExtent];
6877
6878     ExceptionInfo
6879       *exception;
6880
6881     Image
6882       *image,
6883       *next;
6884
6885     register ssize_t
6886       i;
6887
6888     struct PackageInfo
6889       *info,
6890       *package_info;
6891
6892     size_t
6893       length;
6894
6895     ssize_t
6896       scene;
6897
6898     SV
6899       *perl_exception,
6900       *reference;
6901
6902     void
6903       *blob;
6904
6905     PERL_UNUSED_VAR(ref);
6906     PERL_UNUSED_VAR(ix);
6907     exception=AcquireExceptionInfo();
6908     perl_exception=newSVpv("",0);
6909     package_info=(struct PackageInfo *) NULL;
6910     if (sv_isobject(ST(0)) == 0)
6911       {
6912         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6913           PackageName);
6914         goto PerlException;
6915       }
6916     reference=SvRV(ST(0));
6917     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6918     if (image == (Image *) NULL)
6919       {
6920         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6921           PackageName);
6922         goto PerlException;
6923       }
6924     package_info=ClonePackageInfo(info,exception);
6925     for (i=2; i < items; i+=2)
6926       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6927     (void) CopyMagickString(filename,package_info->image_info->filename,
6928       MagickPathExtent);
6929     scene=0;
6930     for (next=image; next; next=next->next)
6931     {
6932       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6933       next->scene=scene++;
6934     }
6935     SetImageInfo(package_info->image_info,(unsigned int)
6936       GetImageListLength(image),exception);
6937     EXTEND(sp,(ssize_t) GetImageListLength(image));
6938     for ( ; image; image=image->next)
6939     {
6940       length=0;
6941       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6942       if (blob != (char *) NULL)
6943         {
6944           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6945           blob=(unsigned char *) RelinquishMagickMemory(blob);
6946         }
6947       if (package_info->image_info->adjoin)
6948         break;
6949     }
6950
6951   PerlException:
6952     if (package_info != (struct PackageInfo *) NULL)
6953       DestroyPackageInfo(package_info);
6954     InheritPerlException(exception,perl_exception);
6955     exception=DestroyExceptionInfo(exception);
6956     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6957   }
6958 \f
6959 #
6960 ###############################################################################
6961 #                                                                             #
6962 #                                                                             #
6963 #                                                                             #
6964 #   L a y e r s                                                               #
6965 #                                                                             #
6966 #                                                                             #
6967 #                                                                             #
6968 ###############################################################################
6969 #
6970 #
6971 void
6972 Layers(ref,...)
6973   Image::Magick ref=NO_INIT
6974   ALIAS:
6975     Layers                = 1
6976     layers           = 2
6977     OptimizeImageLayers   = 3
6978     optimizelayers        = 4
6979     optimizeimagelayers   = 5
6980   PPCODE:
6981   {
6982     AV
6983       *av;
6984
6985     char
6986       *attribute;
6987
6988     CompositeOperator
6989       compose;
6990
6991     ExceptionInfo
6992       *exception;
6993
6994     HV
6995       *hv;
6996
6997     Image
6998       *image,
6999       *layers;
7000
7001     LayerMethod
7002       method;
7003
7004     register ssize_t
7005       i;
7006
7007     ssize_t
7008       option,
7009       sp;
7010
7011     struct PackageInfo
7012       *info;
7013
7014     SV
7015       *av_reference,
7016       *perl_exception,
7017       *reference,
7018       *rv,
7019       *sv;
7020
7021     PERL_UNUSED_VAR(ref);
7022     PERL_UNUSED_VAR(ix);
7023     exception=AcquireExceptionInfo();
7024     perl_exception=newSVpv("",0);
7025     sv=NULL;
7026     if (sv_isobject(ST(0)) == 0)
7027       {
7028         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7029           PackageName);
7030         goto PerlException;
7031       }
7032     reference=SvRV(ST(0));
7033     hv=SvSTASH(reference);
7034     av=newAV();
7035     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7036     SvREFCNT_dec(av);
7037     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7038     if (image == (Image *) NULL)
7039       {
7040         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7041           PackageName);
7042         goto PerlException;
7043       }
7044     compose=image->compose;
7045     method=OptimizeLayer;
7046     for (i=2; i < items; i+=2)
7047     {
7048       attribute=(char *) SvPV(ST(i-1),na);
7049       switch (*attribute)
7050       {
7051         case 'C':
7052         case 'c':
7053         {
7054           if (LocaleCompare(attribute,"compose") == 0)
7055             {
7056               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7057                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7058               if (sp < 0)
7059                 {
7060                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7061                     SvPV(ST(i),na));
7062                   break;
7063                 }
7064               compose=(CompositeOperator) sp;
7065               break;
7066             }
7067           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7068             attribute);
7069           break;
7070         }
7071         case 'M':
7072         case 'm':
7073         {
7074           if (LocaleCompare(attribute,"method") == 0)
7075             {
7076               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7077                 SvPV(ST(i),na));
7078               if (option < 0)
7079                 {
7080                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7081                     SvPV(ST(i),na));
7082                   break;
7083                 }
7084               method=(LayerMethod) option;
7085               break;
7086             }
7087           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7088             attribute);
7089           break;
7090         }
7091         default:
7092         {
7093           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7094             attribute);
7095           break;
7096         }
7097       }
7098     }
7099     layers=(Image *) NULL;
7100     switch (method)
7101     {
7102       case CompareAnyLayer:
7103       case CompareClearLayer:
7104       case CompareOverlayLayer:
7105       default:
7106       {
7107         layers=CompareImagesLayers(image,method,exception);
7108         break;
7109       }
7110       case MergeLayer:
7111       case FlattenLayer:
7112       case MosaicLayer:
7113       {
7114         layers=MergeImageLayers(image,method,exception);
7115         break;
7116       }
7117       case DisposeLayer:
7118       {
7119         layers=DisposeImages(image,exception);
7120         break;
7121       }
7122       case OptimizeImageLayer:
7123       {
7124         layers=OptimizeImageLayers(image,exception);
7125         break;
7126       }
7127       case OptimizePlusLayer:
7128       {
7129         layers=OptimizePlusImageLayers(image,exception);
7130         break;
7131       }
7132       case OptimizeTransLayer:
7133       {
7134         OptimizeImageTransparency(image,exception);
7135         break;
7136       }
7137       case RemoveDupsLayer:
7138       {
7139         RemoveDuplicateLayers(&image,exception);
7140         break;
7141       }
7142       case RemoveZeroLayer:
7143       {
7144         RemoveZeroDelayLayers(&image,exception);
7145         break;
7146       }
7147       case OptimizeLayer:
7148       {
7149         QuantizeInfo
7150           *quantize_info;
7151
7152         /*
7153           General Purpose, GIF Animation Optimizer.
7154         */
7155         layers=CoalesceImages(image,exception);
7156         if (layers == (Image *) NULL)
7157           break;
7158         image=layers;
7159         layers=OptimizeImageLayers(image,exception);
7160         if (layers == (Image *) NULL)
7161           break;
7162         image=DestroyImageList(image);
7163         image=layers;
7164         layers=(Image *) NULL;
7165         OptimizeImageTransparency(image,exception);
7166         quantize_info=AcquireQuantizeInfo(info->image_info);
7167         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7168         quantize_info=DestroyQuantizeInfo(quantize_info);
7169         break;
7170       }
7171       case CompositeLayer:
7172       {
7173         Image
7174           *source;
7175
7176         RectangleInfo
7177           geometry;
7178
7179         /*
7180           Split image sequence at the first 'NULL:' image.
7181         */
7182         source=image;
7183         while (source != (Image *) NULL)
7184         {
7185           source=GetNextImageInList(source);
7186           if ((source != (Image *) NULL) &&
7187               (LocaleCompare(source->magick,"NULL") == 0))
7188             break;
7189         }
7190         if (source != (Image *) NULL)
7191           {
7192             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7193                 (GetNextImageInList(source) == (Image *) NULL))
7194               source=(Image *) NULL;
7195             else
7196               {
7197                 /*
7198                   Separate the two lists, junk the null: image.
7199                 */
7200                 source=SplitImageList(source->previous);
7201                 DeleteImageFromList(&source);
7202               }
7203           }
7204         if (source == (Image *) NULL)
7205           {
7206             (void) ThrowMagickException(exception,GetMagickModule(),
7207               OptionError,"MissingNullSeparator","layers Composite");
7208             break;
7209           }
7210         /*
7211           Adjust offset with gravity and virtual canvas.
7212         */
7213         SetGeometry(image,&geometry);
7214         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7215         geometry.width=source->page.width != 0 ? source->page.width :
7216           source->columns;
7217         geometry.height=source->page.height != 0 ? source->page.height :
7218           source->rows;
7219         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7220           image->columns,image->page.height != 0 ? image->page.height :
7221           image->rows,image->gravity,&geometry);
7222         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7223         source=DestroyImageList(source);
7224         break;
7225       }
7226     }
7227     if (layers != (Image *) NULL)
7228       image=layers;
7229     else
7230       image=CloneImage(image,0,0,MagickTrue,exception);
7231     if (image == (Image *) NULL)
7232       goto PerlException;
7233     for ( ; image; image=image->next)
7234     {
7235       AddImageToRegistry(sv,image);
7236       rv=newRV(sv);
7237       av_push(av,sv_bless(rv,hv));
7238       SvREFCNT_dec(sv);
7239     }
7240     exception=DestroyExceptionInfo(exception);
7241     ST(0)=av_reference;
7242     SvREFCNT_dec(perl_exception);
7243     XSRETURN(1);
7244
7245   PerlException:
7246     InheritPerlException(exception,perl_exception);
7247     exception=DestroyExceptionInfo(exception);
7248     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7249     SvPOK_on(perl_exception);
7250     ST(0)=sv_2mortal(perl_exception);
7251     XSRETURN(1);
7252   }
7253 \f
7254 #
7255 ###############################################################################
7256 #                                                                             #
7257 #                                                                             #
7258 #                                                                             #
7259 #   M a g i c k T o M i m e                                                   #
7260 #                                                                             #
7261 #                                                                             #
7262 #                                                                             #
7263 ###############################################################################
7264 #
7265 #
7266 SV *
7267 MagickToMime(ref,name)
7268   Image::Magick ref=NO_INIT
7269   char *name
7270   ALIAS:
7271     magicktomime = 1
7272   CODE:
7273   {
7274     char
7275       *mime;
7276
7277     PERL_UNUSED_VAR(ref);
7278     PERL_UNUSED_VAR(ix);
7279     mime=MagickToMime(name);
7280     RETVAL=newSVpv(mime,0);
7281     mime=(char *) RelinquishMagickMemory(mime);
7282   }
7283   OUTPUT:
7284     RETVAL
7285 \f
7286 #
7287 ###############################################################################
7288 #                                                                             #
7289 #                                                                             #
7290 #                                                                             #
7291 #   M o g r i f y                                                             #
7292 #                                                                             #
7293 #                                                                             #
7294 #                                                                             #
7295 ###############################################################################
7296 #
7297 #
7298 void
7299 Mogrify(ref,...)
7300   Image::Magick ref=NO_INIT
7301   ALIAS:
7302     Comment            =   1
7303     CommentImage       =   2
7304     Label              =   3
7305     LabelImage         =   4
7306     AddNoise           =   5
7307     AddNoiseImage      =   6
7308     Colorize           =   7
7309     ColorizeImage      =   8
7310     Border             =   9
7311     BorderImage        =  10
7312     Blur               =  11
7313     BlurImage          =  12
7314     Chop               =  13
7315     ChopImage          =  14
7316     Crop               =  15
7317     CropImage          =  16
7318     Despeckle          =  17
7319     DespeckleImage     =  18
7320     Edge               =  19
7321     EdgeImage          =  20
7322     Emboss             =  21
7323     EmbossImage        =  22
7324     Enhance            =  23
7325     EnhanceImage       =  24
7326     Flip               =  25
7327     FlipImage          =  26
7328     Flop               =  27
7329     FlopImage          =  28
7330     Frame              =  29
7331     FrameImage         =  30
7332     Implode            =  31
7333     ImplodeImage       =  32
7334     Magnify            =  33
7335     MagnifyImage       =  34
7336     MedianFilter       =  35
7337     MedianConvolveImage  =  36
7338     Minify             =  37
7339     MinifyImage        =  38
7340     OilPaint           =  39
7341     OilPaintImage      =  40
7342     ReduceNoise        =  41
7343     ReduceNoiseImage   =  42
7344     Roll               =  43
7345     RollImage          =  44
7346     Rotate             =  45
7347     RotateImage        =  46
7348     Sample             =  47
7349     SampleImage        =  48
7350     Scale              =  49
7351     ScaleImage         =  50
7352     Shade              =  51
7353     ShadeImage         =  52
7354     Sharpen            =  53
7355     SharpenImage       =  54
7356     Shear              =  55
7357     ShearImage         =  56
7358     Spread             =  57
7359     SpreadImage        =  58
7360     Swirl              =  59
7361     SwirlImage         =  60
7362     Resize             =  61
7363     ResizeImage        =  62
7364     Zoom               =  63
7365     ZoomImage          =  64
7366     Annotate           =  65
7367     AnnotateImage      =  66
7368     ColorFloodfill     =  67
7369     ColorFloodfillImage=  68
7370     Composite          =  69
7371     CompositeImage     =  70
7372     Contrast           =  71
7373     ContrastImage      =  72
7374     CycleColormap      =  73
7375     CycleColormapImage =  74
7376     Draw               =  75
7377     DrawImage          =  76
7378     Equalize           =  77
7379     EqualizeImage      =  78
7380     Gamma              =  79
7381     GammaImage         =  80
7382     Map                =  81
7383     MapImage           =  82
7384     MatteFloodfill     =  83
7385     MatteFloodfillImage=  84
7386     Modulate           =  85
7387     ModulateImage      =  86
7388     Negate             =  87
7389     NegateImage        =  88
7390     Normalize          =  89
7391     NormalizeImage     =  90
7392     NumberColors       =  91
7393     NumberColorsImage  =  92
7394     Opaque             =  93
7395     OpaqueImage        =  94
7396     Quantize           =  95
7397     QuantizeImage      =  96
7398     Raise              =  97
7399     RaiseImage         =  98
7400     Segment            =  99
7401     SegmentImage       = 100
7402     Signature          = 101
7403     SignatureImage     = 102
7404     Solarize           = 103
7405     SolarizeImage      = 104
7406     Sync               = 105
7407     SyncImage          = 106
7408     Texture            = 107
7409     TextureImage       = 108
7410     Evaluate           = 109
7411     EvaluateImage      = 110
7412     Transparent        = 111
7413     TransparentImage   = 112
7414     Threshold          = 113
7415     ThresholdImage     = 114
7416     Charcoal           = 115
7417     CharcoalImage      = 116
7418     Trim               = 117
7419     TrimImage          = 118
7420     Wave               = 119
7421     WaveImage          = 120
7422     Separate           = 121
7423     SeparateImage      = 122
7424     Stereo             = 125
7425     StereoImage        = 126
7426     Stegano            = 127
7427     SteganoImage       = 128
7428     Deconstruct        = 129
7429     DeconstructImage   = 130
7430     GaussianBlur       = 131
7431     GaussianBlurImage  = 132
7432     Convolve           = 133
7433     ConvolveImage      = 134
7434     Profile            = 135
7435     ProfileImage       = 136
7436     UnsharpMask        = 137
7437     UnsharpMaskImage   = 138
7438     MotionBlur         = 139
7439     MotionBlurImage    = 140
7440     OrderedDither      = 141
7441     OrderedDitherImage = 142
7442     Shave              = 143
7443     ShaveImage         = 144
7444     Level              = 145
7445     LevelImage         = 146
7446     Clip               = 147
7447     ClipImage          = 148
7448     AffineTransform    = 149
7449     AffineTransformImage = 150
7450     Difference         = 151
7451     DifferenceImage    = 152
7452     AdaptiveThreshold  = 153
7453     AdaptiveThresholdImage = 154
7454     Resample           = 155
7455     ResampleImage      = 156
7456     Describe           = 157
7457     DescribeImage      = 158
7458     BlackThreshold     = 159
7459     BlackThresholdImage= 160
7460     WhiteThreshold     = 161
7461     WhiteThresholdImage= 162
7462     RotationalBlur     = 163
7463     RotationalBlurImage= 164
7464     Thumbnail          = 165
7465     ThumbnailImage     = 166
7466     Strip              = 167
7467     StripImage         = 168
7468     Tint               = 169
7469     TintImage          = 170
7470     Channel            = 171
7471     ChannelImage       = 172
7472     Splice             = 173
7473     SpliceImage        = 174
7474     Posterize          = 175
7475     PosterizeImage     = 176
7476     Shadow             = 177
7477     ShadowImage        = 178
7478     Identify           = 179
7479     IdentifyImage      = 180
7480     SepiaTone          = 181
7481     SepiaToneImage     = 182
7482     SigmoidalContrast  = 183
7483     SigmoidalContrastImage = 184
7484     Extent             = 185
7485     ExtentImage        = 186
7486     Vignette           = 187
7487     VignetteImage      = 188
7488     ContrastStretch    = 189
7489     ContrastStretchImage = 190
7490     Sans0              = 191
7491     Sans0Image         = 192
7492     Sans1              = 193
7493     Sans1Image         = 194
7494     AdaptiveSharpen    = 195
7495     AdaptiveSharpenImage = 196
7496     Transpose          = 197
7497     TransposeImage     = 198
7498     Transverse         = 199
7499     TransverseImage    = 200
7500     AutoOrient         = 201
7501     AutoOrientImage    = 202
7502     AdaptiveBlur       = 203
7503     AdaptiveBlurImage  = 204
7504     Sketch             = 205
7505     SketchImage        = 206
7506     UniqueColors       = 207
7507     UniqueColorsImage  = 208
7508     AdaptiveResize     = 209
7509     AdaptiveResizeImage= 210
7510     ClipMask           = 211
7511     ClipMaskImage      = 212
7512     LinearStretch      = 213
7513     LinearStretchImage = 214
7514     ColorMatrix        = 215
7515     ColorMatrixImage   = 216
7516     Mask               = 217
7517     MaskImage          = 218
7518     Polaroid           = 219
7519     PolaroidImage      = 220
7520     FloodfillPaint     = 221
7521     FloodfillPaintImage= 222
7522     Distort            = 223
7523     DistortImage       = 224
7524     Clut               = 225
7525     ClutImage          = 226
7526     LiquidRescale      = 227
7527     LiquidRescaleImage = 228
7528     Encipher           = 229
7529     EncipherImage      = 230
7530     Decipher           = 231
7531     DecipherImage      = 232
7532     Deskew             = 233
7533     DeskewImage        = 234
7534     Remap              = 235
7535     RemapImage         = 236
7536     SparseColor        = 237
7537     SparseColorImage   = 238
7538     Function           = 239
7539     FunctionImage      = 240
7540     SelectiveBlur      = 241
7541     SelectiveBlurImage = 242
7542     HaldClut           = 243
7543     HaldClutImage      = 244
7544     BlueShift          = 245
7545     BlueShiftImage     = 246
7546     ForwardFourierTransform  = 247
7547     ForwardFourierTransformImage = 248
7548     InverseFourierTransform = 249
7549     InverseFourierTransformImage = 250
7550     ColorDecisionList  = 251
7551     ColorDecisionListImage = 252
7552     AutoGamma          = 253
7553     AutoGammaImage     = 254
7554     AutoLevel          = 255
7555     AutoLevelImage     = 256
7556     LevelColors        = 257
7557     LevelImageColors   = 258
7558     Clamp              = 259
7559     ClampImage         = 260
7560     BrightnessContrast = 261
7561     BrightnessContrastImage = 262
7562     Morphology         = 263
7563     MorphologyImage    = 264
7564     Mode               = 265
7565     ModeImage          = 266
7566     Statistic          = 267
7567     StatisticImage     = 268
7568     Perceptible        = 269
7569     PerceptibleImage   = 270
7570     Poly               = 271
7571     PolyImage          = 272
7572     Grayscale          = 273
7573     GrayscaleImage     = 274
7574     CannyEdge          = 275
7575     CannyEdgeImage     = 276
7576     HoughLine          = 277
7577     HoughLineImage     = 278
7578     MeanShift          = 279
7579     MeanShiftImage     = 280
7580     Kuwahara           = 281
7581     KuwaharaImage      = 282
7582     ConnectedComponent = 283
7583     ConnectedComponentImage = 284
7584     CopyPixels         = 285
7585     CopyImagePixels    = 286
7586     Color              = 287
7587     ColorImage         = 288
7588     WaveletDenoise     = 289
7589     WaveletDenoiseImage= 290
7590     MogrifyRegion      = 666
7591   PPCODE:
7592   {
7593     AffineMatrix
7594       affine,
7595       current;
7596
7597     char
7598       attribute_flag[MaxArguments],
7599       message[MagickPathExtent];
7600
7601     ChannelType
7602       channel,
7603       channel_mask;
7604
7605     CompositeOperator
7606       compose;
7607
7608     const char
7609       *attribute,
7610       *value;
7611
7612     double
7613       angle;
7614
7615     ExceptionInfo
7616       *exception;
7617
7618     GeometryInfo
7619       geometry_info;
7620
7621     Image
7622       *image,
7623       *next,
7624       *region_image;
7625
7626     MagickBooleanType
7627       status;
7628
7629     MagickStatusType
7630       flags;
7631
7632     PixelInfo
7633       fill_color;
7634
7635     RectangleInfo
7636       geometry,
7637       region_info;
7638
7639     register ssize_t
7640       i;
7641
7642     ssize_t
7643       base,
7644       j,
7645       number_images;
7646
7647     struct Methods
7648       *rp;
7649
7650     struct PackageInfo
7651       *info;
7652
7653     SV
7654       *perl_exception,
7655       **pv,
7656       *reference,
7657       **reference_vector;
7658
7659     struct ArgumentList
7660       argument_list[MaxArguments];
7661
7662     PERL_UNUSED_VAR(ref);
7663     PERL_UNUSED_VAR(ix);
7664     exception=AcquireExceptionInfo();
7665     perl_exception=newSVpv("",0);
7666     reference_vector=NULL;
7667     region_image=NULL;
7668     number_images=0;
7669     base=2;
7670     if (sv_isobject(ST(0)) == 0)
7671       {
7672         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7673           PackageName);
7674         goto PerlException;
7675       }
7676     reference=SvRV(ST(0));
7677     region_info.width=0;
7678     region_info.height=0;
7679     region_info.x=0;
7680     region_info.y=0;
7681     region_image=(Image *) NULL;
7682     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7683     if (ix && (ix != 666))
7684       {
7685         /*
7686           Called as Method(...)
7687         */
7688         ix=(ix+1)/2;
7689         rp=(&Methods[ix-1]);
7690         attribute=rp->name;
7691       }
7692     else
7693       {
7694         /*
7695           Called as Mogrify("Method",...)
7696         */
7697         attribute=(char *) SvPV(ST(1),na);
7698         if (ix)
7699           {
7700             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7701             attribute=(char *) SvPV(ST(2),na);
7702             base++;
7703           }
7704         for (rp=Methods; ; rp++)
7705         {
7706           if (rp >= EndOf(Methods))
7707             {
7708               ThrowPerlException(exception,OptionError,
7709                 "UnrecognizedPerlMagickMethod",attribute);
7710               goto PerlException;
7711             }
7712           if (strEQcase(attribute,rp->name))
7713             break;
7714         }
7715         ix=rp-Methods+1;
7716         base++;
7717       }
7718     if (image == (Image *) NULL)
7719       {
7720         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7721         goto PerlException;
7722       }
7723     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7724     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7725     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7726     {
7727       Arguments
7728         *pp,
7729         *qq;
7730
7731       ssize_t
7732         ssize_test;
7733
7734       struct ArgumentList
7735         *al;
7736
7737       SV
7738         *sv;
7739
7740       sv=NULL;
7741       ssize_test=0;
7742       pp=(Arguments *) NULL;
7743       qq=rp->arguments;
7744       if (i == items)
7745         {
7746           pp=rp->arguments,
7747           sv=ST(i-1);
7748         }
7749       else
7750         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7751         {
7752           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7753             break;
7754           if (strEQcase(attribute,qq->method) > ssize_test)
7755             {
7756               pp=qq;
7757               ssize_test=strEQcase(attribute,qq->method);
7758             }
7759         }
7760       if (pp == (Arguments *) NULL)
7761         {
7762           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7763             attribute);
7764           goto continue_outer_loop;
7765         }
7766       al=(&argument_list[pp-rp->arguments]);
7767       switch (pp->type)
7768       {
7769         case ArrayReference:
7770         {
7771           if (SvTYPE(sv) != SVt_RV)
7772             {
7773               (void) FormatLocaleString(message,MagickPathExtent,
7774                 "invalid %.60s value",pp->method);
7775               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7776               goto continue_outer_loop;
7777             }
7778           al->array_reference=SvRV(sv);
7779           break;
7780         }
7781         case RealReference:
7782         {
7783           al->real_reference=SvNV(sv);
7784           break;
7785         }
7786         case FileReference:
7787         {
7788           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7789           break;
7790         }
7791         case ImageReference:
7792         {
7793           if (!sv_isobject(sv) ||
7794               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7795                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7796             {
7797               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7798                 PackageName);
7799               goto PerlException;
7800             }
7801           break;
7802         }
7803         case IntegerReference:
7804         {
7805           al->integer_reference=SvIV(sv);
7806           break;
7807         }
7808         case StringReference:
7809         {
7810           al->string_reference=(char *) SvPV(sv,al->length);
7811           if (sv_isobject(sv))
7812             al->image_reference=SetupList(aTHX_ SvRV(sv),
7813               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7814           break;
7815         }
7816         default:
7817         {
7818           /*
7819             Is a string; look up name.
7820           */
7821           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7822             {
7823               al->string_reference=(char *) SvPV(sv,al->length);
7824               al->integer_reference=(-1);
7825               break;
7826             }
7827           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7828             MagickFalse,SvPV(sv,na));
7829           if (pp->type == MagickChannelOptions)
7830             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7831           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7832             {
7833               (void) FormatLocaleString(message,MagickPathExtent,
7834                 "invalid %.60s value",pp->method);
7835               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7836               goto continue_outer_loop;
7837             }
7838           break;
7839         }
7840       }
7841       attribute_flag[pp-rp->arguments]++;
7842       continue_outer_loop: ;
7843     }
7844     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7845     pv=reference_vector;
7846     SetGeometryInfo(&geometry_info);
7847     channel=DefaultChannels;
7848     for (next=image; next; next=next->next)
7849     {
7850       image=next;
7851       SetGeometry(image,&geometry);
7852       if ((region_info.width*region_info.height) != 0)
7853         {
7854           region_image=image;
7855           image=CropImage(image,&region_info,exception);
7856         }
7857       switch (ix)
7858       {
7859         default:
7860         {
7861           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7862           ThrowPerlException(exception,OptionError,
7863             "UnrecognizedPerlMagickMethod",message);
7864           goto PerlException;
7865         }
7866         case 1:  /* Comment */
7867         {
7868           if (attribute_flag[0] == 0)
7869             argument_list[0].string_reference=(char *) NULL;
7870           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7871             info ? info->image_info : (ImageInfo *) NULL,image,
7872             argument_list[0].string_reference,exception),exception);
7873           break;
7874         }
7875         case 2:  /* Label */
7876         {
7877           if (attribute_flag[0] == 0)
7878             argument_list[0].string_reference=(char *) NULL;
7879           (void) SetImageProperty(image,"label",InterpretImageProperties(
7880             info ? info->image_info : (ImageInfo *) NULL,image,
7881             argument_list[0].string_reference,exception),exception);
7882           break;
7883         }
7884         case 3:  /* AddNoise */
7885         {
7886           double
7887             attenuate;
7888
7889           if (attribute_flag[0] == 0)
7890             argument_list[0].integer_reference=UniformNoise;
7891           attenuate=1.0;
7892           if (attribute_flag[1] != 0)
7893             attenuate=argument_list[1].real_reference;
7894           if (attribute_flag[2] != 0)
7895             channel=(ChannelType) argument_list[2].integer_reference;
7896           channel_mask=SetImageChannelMask(image,channel);
7897           image=AddNoiseImage(image,(NoiseType)
7898             argument_list[0].integer_reference,attenuate,exception);
7899           if (image != (Image *) NULL)
7900             (void) SetImageChannelMask(image,channel_mask);
7901           break;
7902         }
7903         case 4:  /* Colorize */
7904         {
7905           PixelInfo
7906             target;
7907
7908           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7909             0,0,&target,exception);
7910           if (attribute_flag[0] != 0)
7911             (void) QueryColorCompliance(argument_list[0].string_reference,
7912               AllCompliance,&target,exception);
7913           if (attribute_flag[1] == 0)
7914             argument_list[1].string_reference="100%";
7915           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7916             exception);
7917           break;
7918         }
7919         case 5:  /* Border */
7920         {
7921           CompositeOperator
7922             compose;
7923
7924           geometry.width=0;
7925           geometry.height=0;
7926           if (attribute_flag[0] != 0)
7927             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7928               &geometry,exception);
7929           if (attribute_flag[1] != 0)
7930             geometry.width=argument_list[1].integer_reference;
7931           if (attribute_flag[2] != 0)
7932             geometry.height=argument_list[2].integer_reference;
7933           if (attribute_flag[3] != 0)
7934             QueryColorCompliance(argument_list[3].string_reference,
7935               AllCompliance,&image->border_color,exception);
7936           if (attribute_flag[4] != 0)
7937             QueryColorCompliance(argument_list[4].string_reference,
7938               AllCompliance,&image->border_color,exception);
7939           if (attribute_flag[5] != 0)
7940             QueryColorCompliance(argument_list[5].string_reference,
7941               AllCompliance,&image->border_color,exception);
7942           compose=image->compose;
7943           if (attribute_flag[6] != 0)
7944             compose=(CompositeOperator) argument_list[6].integer_reference;
7945           image=BorderImage(image,&geometry,compose,exception);
7946           break;
7947         }
7948         case 6:  /* Blur */
7949         {
7950           if (attribute_flag[0] != 0)
7951             {
7952               flags=ParseGeometry(argument_list[0].string_reference,
7953                 &geometry_info);
7954               if ((flags & SigmaValue) == 0)
7955                 geometry_info.sigma=1.0;
7956             }
7957           if (attribute_flag[1] != 0)
7958             geometry_info.rho=argument_list[1].real_reference;
7959           if (attribute_flag[2] != 0)
7960             geometry_info.sigma=argument_list[2].real_reference;
7961           if (attribute_flag[3] != 0)
7962             channel=(ChannelType) argument_list[3].integer_reference;
7963           channel_mask=SetImageChannelMask(image,channel);
7964           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7965             exception);
7966           if (image != (Image *) NULL)
7967             (void) SetImageChannelMask(image,channel_mask);
7968           break;
7969         }
7970         case 7:  /* Chop */
7971         {
7972           if (attribute_flag[5] != 0)
7973             image->gravity=(GravityType) argument_list[5].integer_reference;
7974           if (attribute_flag[0] != 0)
7975             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7976               &geometry,exception);
7977           if (attribute_flag[1] != 0)
7978             geometry.width=argument_list[1].integer_reference;
7979           if (attribute_flag[2] != 0)
7980             geometry.height=argument_list[2].integer_reference;
7981           if (attribute_flag[3] != 0)
7982             geometry.x=argument_list[3].integer_reference;
7983           if (attribute_flag[4] != 0)
7984             geometry.y=argument_list[4].integer_reference;
7985           image=ChopImage(image,&geometry,exception);
7986           break;
7987         }
7988         case 8:  /* Crop */
7989         {
7990           if (attribute_flag[6] != 0)
7991             image->gravity=(GravityType) argument_list[6].integer_reference;
7992           if (attribute_flag[0] != 0)
7993             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7994               &geometry,exception);
7995           if (attribute_flag[1] != 0)
7996             geometry.width=argument_list[1].integer_reference;
7997           if (attribute_flag[2] != 0)
7998             geometry.height=argument_list[2].integer_reference;
7999           if (attribute_flag[3] != 0)
8000             geometry.x=argument_list[3].integer_reference;
8001           if (attribute_flag[4] != 0)
8002             geometry.y=argument_list[4].integer_reference;
8003           if (attribute_flag[5] != 0)
8004             image->fuzz=StringToDoubleInterval(
8005               argument_list[5].string_reference,(double) QuantumRange+1.0);
8006           image=CropImage(image,&geometry,exception);
8007           break;
8008         }
8009         case 9:  /* Despeckle */
8010         {
8011           image=DespeckleImage(image,exception);
8012           break;
8013         }
8014         case 10:  /* Edge */
8015         {
8016           if (attribute_flag[0] != 0)
8017             geometry_info.rho=argument_list[0].real_reference;
8018           image=EdgeImage(image,geometry_info.rho,exception);
8019           break;
8020         }
8021         case 11:  /* Emboss */
8022         {
8023           if (attribute_flag[0] != 0)
8024             {
8025               flags=ParseGeometry(argument_list[0].string_reference,
8026                 &geometry_info);
8027               if ((flags & SigmaValue) == 0)
8028                 geometry_info.sigma=1.0;
8029             }
8030           if (attribute_flag[1] != 0)
8031             geometry_info.rho=argument_list[1].real_reference;
8032           if (attribute_flag[2] != 0)
8033             geometry_info.sigma=argument_list[2].real_reference;
8034           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8035             exception);
8036           break;
8037         }
8038         case 12:  /* Enhance */
8039         {
8040           image=EnhanceImage(image,exception);
8041           break;
8042         }
8043         case 13:  /* Flip */
8044         {
8045           image=FlipImage(image,exception);
8046           break;
8047         }
8048         case 14:  /* Flop */
8049         {
8050           image=FlopImage(image,exception);
8051           break;
8052         }
8053         case 15:  /* Frame */
8054         {
8055           CompositeOperator
8056             compose;
8057
8058           FrameInfo
8059             frame_info;
8060
8061           if (attribute_flag[0] != 0)
8062             {
8063               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8064                 &geometry,exception);
8065               frame_info.width=geometry.width;
8066               frame_info.height=geometry.height;
8067               frame_info.outer_bevel=geometry.x;
8068               frame_info.inner_bevel=geometry.y;
8069             }
8070           if (attribute_flag[1] != 0)
8071             frame_info.width=argument_list[1].integer_reference;
8072           if (attribute_flag[2] != 0)
8073             frame_info.height=argument_list[2].integer_reference;
8074           if (attribute_flag[3] != 0)
8075             frame_info.inner_bevel=argument_list[3].integer_reference;
8076           if (attribute_flag[4] != 0)
8077             frame_info.outer_bevel=argument_list[4].integer_reference;
8078           if (attribute_flag[5] != 0)
8079             QueryColorCompliance(argument_list[5].string_reference,
8080               AllCompliance,&fill_color,exception);
8081           if (attribute_flag[6] != 0)
8082             QueryColorCompliance(argument_list[6].string_reference,
8083               AllCompliance,&fill_color,exception);
8084           frame_info.x=(ssize_t) frame_info.width;
8085           frame_info.y=(ssize_t) frame_info.height;
8086           frame_info.width=image->columns+2*frame_info.x;
8087           frame_info.height=image->rows+2*frame_info.y;
8088           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8089             image->alpha_color=fill_color;
8090           compose=image->compose;
8091           if (attribute_flag[7] != 0)
8092             compose=(CompositeOperator) argument_list[7].integer_reference;
8093           image=FrameImage(image,&frame_info,compose,exception);
8094           break;
8095         }
8096         case 16:  /* Implode */
8097         {
8098           PixelInterpolateMethod
8099             method;
8100
8101           if (attribute_flag[0] == 0)
8102             argument_list[0].real_reference=0.5;
8103           method=UndefinedInterpolatePixel;
8104           if (attribute_flag[1] != 0)
8105             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8106           image=ImplodeImage(image,argument_list[0].real_reference,
8107             method,exception);
8108           break;
8109         }
8110         case 17:  /* Magnify */
8111         {
8112           image=MagnifyImage(image,exception);
8113           break;
8114         }
8115         case 18:  /* MedianFilter */
8116         {
8117           if (attribute_flag[0] != 0)
8118             {
8119               flags=ParseGeometry(argument_list[0].string_reference,
8120                 &geometry_info);
8121               if ((flags & SigmaValue) == 0)
8122                 geometry_info.sigma=geometry_info.rho;
8123             }
8124           if (attribute_flag[1] != 0)
8125             geometry_info.rho=argument_list[1].real_reference;
8126           if (attribute_flag[2] != 0)
8127             geometry_info.sigma=argument_list[2].real_reference;
8128           if (attribute_flag[3] != 0)
8129             channel=(ChannelType) argument_list[3].integer_reference;
8130           channel_mask=SetImageChannelMask(image,channel);
8131           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8132             (size_t) geometry_info.sigma,exception);
8133           if (image != (Image *) NULL)
8134             (void) SetImageChannelMask(image,channel_mask);
8135           break;
8136         }
8137         case 19:  /* Minify */
8138         {
8139           image=MinifyImage(image,exception);
8140           break;
8141         }
8142         case 20:  /* OilPaint */
8143         {
8144           if (attribute_flag[0] == 0)
8145             argument_list[0].real_reference=0.0;
8146           if (attribute_flag[1] == 0)
8147             argument_list[1].real_reference=1.0;
8148           image=OilPaintImage(image,argument_list[0].real_reference,
8149             argument_list[1].real_reference,exception);
8150           break;
8151         }
8152         case 21:  /* ReduceNoise */
8153         {
8154           if (attribute_flag[0] != 0)
8155             {
8156               flags=ParseGeometry(argument_list[0].string_reference,
8157                 &geometry_info);
8158               if ((flags & SigmaValue) == 0)
8159                 geometry_info.sigma=1.0;
8160             }
8161           if (attribute_flag[1] != 0)
8162             geometry_info.rho=argument_list[1].real_reference;
8163           if (attribute_flag[2] != 0)
8164             geometry_info.sigma=argument_list[2].real_reference;
8165           if (attribute_flag[3] != 0)
8166             channel=(ChannelType) argument_list[3].integer_reference;
8167           channel_mask=SetImageChannelMask(image,channel);
8168           image=StatisticImage(image,NonpeakStatistic,(size_t)
8169             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8170           if (image != (Image *) NULL)
8171             (void) SetImageChannelMask(image,channel_mask);
8172           break;
8173         }
8174         case 22:  /* Roll */
8175         {
8176           if (attribute_flag[0] != 0)
8177             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8178               &geometry,exception);
8179           if (attribute_flag[1] != 0)
8180             geometry.x=argument_list[1].integer_reference;
8181           if (attribute_flag[2] != 0)
8182             geometry.y=argument_list[2].integer_reference;
8183           image=RollImage(image,geometry.x,geometry.y,exception);
8184           break;
8185         }
8186         case 23:  /* Rotate */
8187         {
8188           if (attribute_flag[0] == 0)
8189             argument_list[0].real_reference=90.0;
8190           if (attribute_flag[1] != 0)
8191             {
8192               QueryColorCompliance(argument_list[1].string_reference,
8193                 AllCompliance,&image->background_color,exception);
8194               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8195                   (image->alpha_trait == UndefinedPixelTrait))
8196                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8197             }
8198           image=RotateImage(image,argument_list[0].real_reference,exception);
8199           break;
8200         }
8201         case 24:  /* Sample */
8202         {
8203           if (attribute_flag[0] != 0)
8204             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8205               &geometry,exception);
8206           if (attribute_flag[1] != 0)
8207             geometry.width=argument_list[1].integer_reference;
8208           if (attribute_flag[2] != 0)
8209             geometry.height=argument_list[2].integer_reference;
8210           image=SampleImage(image,geometry.width,geometry.height,exception);
8211           break;
8212         }
8213         case 25:  /* Scale */
8214         {
8215           if (attribute_flag[0] != 0)
8216             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8217               &geometry,exception);
8218           if (attribute_flag[1] != 0)
8219             geometry.width=argument_list[1].integer_reference;
8220           if (attribute_flag[2] != 0)
8221             geometry.height=argument_list[2].integer_reference;
8222           image=ScaleImage(image,geometry.width,geometry.height,exception);
8223           break;
8224         }
8225         case 26:  /* Shade */
8226         {
8227           if (attribute_flag[0] != 0)
8228             {
8229               flags=ParseGeometry(argument_list[0].string_reference,
8230                 &geometry_info);
8231               if ((flags & SigmaValue) == 0)
8232                 geometry_info.sigma=0.0;
8233             }
8234           if (attribute_flag[1] != 0)
8235             geometry_info.rho=argument_list[1].real_reference;
8236           if (attribute_flag[2] != 0)
8237             geometry_info.sigma=argument_list[2].real_reference;
8238           image=ShadeImage(image,
8239             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8240             geometry_info.rho,geometry_info.sigma,exception);
8241           break;
8242         }
8243         case 27:  /* Sharpen */
8244         {
8245           if (attribute_flag[0] != 0)
8246             {
8247               flags=ParseGeometry(argument_list[0].string_reference,
8248                 &geometry_info);
8249               if ((flags & SigmaValue) == 0)
8250                 geometry_info.sigma=1.0;
8251             }
8252           if (attribute_flag[1] != 0)
8253             geometry_info.rho=argument_list[1].real_reference;
8254           if (attribute_flag[2] != 0)
8255             geometry_info.sigma=argument_list[2].real_reference;
8256           if (attribute_flag[3] != 0)
8257             channel=(ChannelType) argument_list[3].integer_reference;
8258           channel_mask=SetImageChannelMask(image,channel);
8259           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8260             exception);
8261           if (image != (Image *) NULL)
8262             (void) SetImageChannelMask(image,channel_mask);
8263           break;
8264         }
8265         case 28:  /* Shear */
8266         {
8267           if (attribute_flag[0] != 0)
8268             {
8269               flags=ParseGeometry(argument_list[0].string_reference,
8270                 &geometry_info);
8271               if ((flags & SigmaValue) == 0)
8272                 geometry_info.sigma=geometry_info.rho;
8273             }
8274           if (attribute_flag[1] != 0)
8275             geometry_info.rho=argument_list[1].real_reference;
8276           if (attribute_flag[2] != 0)
8277             geometry_info.sigma=argument_list[2].real_reference;
8278           if (attribute_flag[3] != 0)
8279             QueryColorCompliance(argument_list[3].string_reference,
8280               AllCompliance,&image->background_color,exception);
8281           if (attribute_flag[4] != 0)
8282             QueryColorCompliance(argument_list[4].string_reference,
8283               AllCompliance,&image->background_color,exception);
8284           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8285             exception);
8286           break;
8287         }
8288         case 29:  /* Spread */
8289         {
8290           PixelInterpolateMethod
8291             method;
8292
8293           if (attribute_flag[0] == 0)
8294             argument_list[0].real_reference=1.0;
8295           method=UndefinedInterpolatePixel;
8296           if (attribute_flag[1] != 0)
8297             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8298           image=SpreadImage(image,method,argument_list[0].real_reference,
8299             exception);
8300           break;
8301         }
8302         case 30:  /* Swirl */
8303         {
8304           PixelInterpolateMethod
8305             method;
8306
8307           if (attribute_flag[0] == 0)
8308             argument_list[0].real_reference=50.0;
8309           method=UndefinedInterpolatePixel;
8310           if (attribute_flag[1] != 0)
8311             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8312           image=SwirlImage(image,argument_list[0].real_reference,
8313             method,exception);
8314           break;
8315         }
8316         case 31:  /* Resize */
8317         case 32:  /* Zoom */
8318         {
8319           if (attribute_flag[0] != 0)
8320             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8321               &geometry,exception);
8322           if (attribute_flag[1] != 0)
8323             geometry.width=argument_list[1].integer_reference;
8324           if (attribute_flag[2] != 0)
8325             geometry.height=argument_list[2].integer_reference;
8326           if (attribute_flag[3] == 0)
8327             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8328           if (attribute_flag[4] != 0)
8329             SetImageArtifact(image,"filter:support",
8330               argument_list[4].string_reference);
8331           image=ResizeImage(image,geometry.width,geometry.height,
8332             (FilterType) argument_list[3].integer_reference,
8333             exception);
8334           break;
8335         }
8336         case 33:  /* Annotate */
8337         {
8338           DrawInfo
8339             *draw_info;
8340
8341           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8342             (DrawInfo *) NULL);
8343           if (attribute_flag[0] != 0)
8344             {
8345               char
8346                 *text;
8347
8348               text=InterpretImageProperties(info ? info->image_info :
8349                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8350                 exception);
8351               (void) CloneString(&draw_info->text,text);
8352               text=DestroyString(text);
8353             }
8354           if (attribute_flag[1] != 0)
8355             (void) CloneString(&draw_info->font,
8356               argument_list[1].string_reference);
8357           if (attribute_flag[2] != 0)
8358             draw_info->pointsize=argument_list[2].real_reference;
8359           if (attribute_flag[3] != 0)
8360             (void) CloneString(&draw_info->density,
8361               argument_list[3].string_reference);
8362           if (attribute_flag[4] != 0)
8363             (void) QueryColorCompliance(argument_list[4].string_reference,
8364               AllCompliance,&draw_info->undercolor,exception);
8365           if (attribute_flag[5] != 0)
8366             {
8367               (void) QueryColorCompliance(argument_list[5].string_reference,
8368                 AllCompliance,&draw_info->stroke,exception);
8369               if (argument_list[5].image_reference != (Image *) NULL)
8370                 draw_info->stroke_pattern=CloneImage(
8371                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8372             }
8373           if (attribute_flag[6] != 0)
8374             {
8375               (void) QueryColorCompliance(argument_list[6].string_reference,
8376                 AllCompliance,&draw_info->fill,exception);
8377               if (argument_list[6].image_reference != (Image *) NULL)
8378                 draw_info->fill_pattern=CloneImage(
8379                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8380             }
8381           if (attribute_flag[7] != 0)
8382             {
8383               (void) CloneString(&draw_info->geometry,
8384                 argument_list[7].string_reference);
8385               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8386                 &geometry,exception);
8387               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8388                 geometry_info.sigma=geometry_info.xi;
8389             }
8390           if (attribute_flag[8] != 0)
8391             (void) QueryColorCompliance(argument_list[8].string_reference,
8392               AllCompliance,&draw_info->fill,exception);
8393           if (attribute_flag[11] != 0)
8394             draw_info->gravity=(GravityType)
8395               argument_list[11].integer_reference;
8396           if (attribute_flag[25] != 0)
8397             {
8398               AV
8399                 *av;
8400
8401               av=(AV *) argument_list[25].array_reference;
8402               if ((av_len(av) != 3) && (av_len(av) != 5))
8403                 {
8404                   ThrowPerlException(exception,OptionError,
8405                     "affine matrix must have 4 or 6 elements",PackageName);
8406                   goto PerlException;
8407                 }
8408               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8409               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8410               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8411               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8412               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8413                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8414                 {
8415                   ThrowPerlException(exception,OptionError,
8416                     "affine matrix is singular",PackageName);
8417                    goto PerlException;
8418                 }
8419               if (av_len(av) == 5)
8420                 {
8421                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8422                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8423                 }
8424             }
8425           for (j=12; j < 17; j++)
8426           {
8427             if (attribute_flag[j] == 0)
8428               continue;
8429             value=argument_list[j].string_reference;
8430             angle=argument_list[j].real_reference;
8431             current=draw_info->affine;
8432             GetAffineMatrix(&affine);
8433             switch (j)
8434             {
8435               case 12:
8436               {
8437                 /*
8438                   Translate.
8439                 */
8440                 flags=ParseGeometry(value,&geometry_info);
8441                 affine.tx=geometry_info.xi;
8442                 affine.ty=geometry_info.psi;
8443                 if ((flags & PsiValue) == 0)
8444                   affine.ty=affine.tx;
8445                 break;
8446               }
8447               case 13:
8448               {
8449                 /*
8450                   Scale.
8451                 */
8452                 flags=ParseGeometry(value,&geometry_info);
8453                 affine.sx=geometry_info.rho;
8454                 affine.sy=geometry_info.sigma;
8455                 if ((flags & SigmaValue) == 0)
8456                   affine.sy=affine.sx;
8457                 break;
8458               }
8459               case 14:
8460               {
8461                 /*
8462                   Rotate.
8463                 */
8464                 if (angle == 0.0)
8465                   break;
8466                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8467                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8468                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8469                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8470                 break;
8471               }
8472               case 15:
8473               {
8474                 /*
8475                   SkewX.
8476                 */
8477                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8478                 break;
8479               }
8480               case 16:
8481               {
8482                 /*
8483                   SkewY.
8484                 */
8485                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8486                 break;
8487               }
8488             }
8489             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8490             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8491             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8492             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8493             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8494               current.tx;
8495             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8496               current.ty;
8497           }
8498           if (attribute_flag[9] == 0)
8499             argument_list[9].real_reference=0.0;
8500           if (attribute_flag[10] == 0)
8501             argument_list[10].real_reference=0.0;
8502           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8503             {
8504               char
8505                 geometry[MagickPathExtent];
8506
8507               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8508                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8509                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8510               (void) CloneString(&draw_info->geometry,geometry);
8511             }
8512           if (attribute_flag[17] != 0)
8513             draw_info->stroke_width=argument_list[17].real_reference;
8514           if (attribute_flag[18] != 0)
8515             {
8516               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8517                 MagickTrue : MagickFalse;
8518               draw_info->stroke_antialias=draw_info->text_antialias;
8519             }
8520           if (attribute_flag[19] != 0)
8521             (void) CloneString(&draw_info->family,
8522               argument_list[19].string_reference);
8523           if (attribute_flag[20] != 0)
8524             draw_info->style=(StyleType) argument_list[20].integer_reference;
8525           if (attribute_flag[21] != 0)
8526             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8527           if (attribute_flag[22] != 0)
8528             draw_info->weight=argument_list[22].integer_reference;
8529           if (attribute_flag[23] != 0)
8530             draw_info->align=(AlignType) argument_list[23].integer_reference;
8531           if (attribute_flag[24] != 0)
8532             (void) CloneString(&draw_info->encoding,
8533               argument_list[24].string_reference);
8534           if (attribute_flag[25] != 0)
8535             draw_info->fill_pattern=CloneImage(
8536               argument_list[25].image_reference,0,0,MagickTrue,exception);
8537           if (attribute_flag[26] != 0)
8538             draw_info->fill_pattern=CloneImage(
8539               argument_list[26].image_reference,0,0,MagickTrue,exception);
8540           if (attribute_flag[27] != 0)
8541             draw_info->stroke_pattern=CloneImage(
8542               argument_list[27].image_reference,0,0,MagickTrue,exception);
8543           if (attribute_flag[29] != 0)
8544             draw_info->kerning=argument_list[29].real_reference;
8545           if (attribute_flag[30] != 0)
8546             draw_info->interline_spacing=argument_list[30].real_reference;
8547           if (attribute_flag[31] != 0)
8548             draw_info->interword_spacing=argument_list[31].real_reference;
8549           if (attribute_flag[32] != 0)
8550             draw_info->direction=(DirectionType)
8551               argument_list[32].integer_reference;
8552           (void) AnnotateImage(image,draw_info,exception);
8553           draw_info=DestroyDrawInfo(draw_info);
8554           break;
8555         }
8556         case 34:  /* ColorFloodfill */
8557         {
8558           DrawInfo
8559             *draw_info;
8560
8561           MagickBooleanType
8562             invert;
8563
8564           PixelInfo
8565             target;
8566
8567           draw_info=CloneDrawInfo(info ? info->image_info :
8568             (ImageInfo *) NULL,(DrawInfo *) NULL);
8569           if (attribute_flag[0] != 0)
8570             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8571               &geometry,exception);
8572           if (attribute_flag[1] != 0)
8573             geometry.x=argument_list[1].integer_reference;
8574           if (attribute_flag[2] != 0)
8575             geometry.y=argument_list[2].integer_reference;
8576           if (attribute_flag[3] != 0)
8577             (void) QueryColorCompliance(argument_list[3].string_reference,
8578               AllCompliance,&draw_info->fill,exception);
8579           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8580             geometry.x,geometry.y,&target,exception);
8581           invert=MagickFalse;
8582           if (attribute_flag[4] != 0)
8583             {
8584               QueryColorCompliance(argument_list[4].string_reference,
8585                 AllCompliance,&target,exception);
8586               invert=MagickTrue;
8587             }
8588           if (attribute_flag[5] != 0)
8589             image->fuzz=StringToDoubleInterval(
8590               argument_list[5].string_reference,(double) QuantumRange+1.0);
8591           if (attribute_flag[6] != 0)
8592             invert=(MagickBooleanType) argument_list[6].integer_reference;
8593           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8594             geometry.y,invert,exception);
8595           draw_info=DestroyDrawInfo(draw_info);
8596           break;
8597         }
8598         case 35:  /* Composite */
8599         {
8600           char
8601             composite_geometry[MagickPathExtent];
8602
8603           Image
8604             *composite_image,
8605             *rotate_image;
8606
8607           MagickBooleanType
8608             clip_to_self;
8609
8610           compose=OverCompositeOp;
8611           if (attribute_flag[0] != 0)
8612             composite_image=argument_list[0].image_reference;
8613           else
8614             {
8615               ThrowPerlException(exception,OptionError,
8616                 "CompositeImageRequired",PackageName);
8617               goto PerlException;
8618             }
8619           /*
8620             Parameter Handling used for BOTH normal and tiled composition.
8621           */
8622           if (attribute_flag[1] != 0) /* compose */
8623             compose=(CompositeOperator) argument_list[1].integer_reference;
8624           if (attribute_flag[6] != 0) /* opacity  */
8625             {
8626               if (compose != DissolveCompositeOp)
8627                 (void) SetImageAlpha(composite_image,(Quantum)
8628                   StringToDoubleInterval(argument_list[6].string_reference,
8629                   (double) QuantumRange+1.0),exception);
8630               else
8631                 {
8632                   CacheView
8633                     *composite_view;
8634
8635                   double
8636                     opacity;
8637
8638                   MagickBooleanType
8639                     sync;
8640
8641                   register ssize_t
8642                     x;
8643
8644                   register Quantum
8645                     *q;
8646
8647                   ssize_t
8648                     y;
8649
8650                   /*
8651                     Handle dissolve composite operator (patch by
8652                     Kevin A. McGrail).
8653                   */
8654                   (void) CloneString(&image->geometry,
8655                     argument_list[6].string_reference);
8656                   opacity=(Quantum) StringToDoubleInterval(
8657                     argument_list[6].string_reference,(double) QuantumRange+
8658                     1.0);
8659                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8660                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8661                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8662                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8663                   {
8664                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8665                       composite_image->columns,1,exception);
8666                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8667                     {
8668                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8669                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8670                           q);
8671                       q+=GetPixelChannels(composite_image);
8672                     }
8673                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8674                     if (sync == MagickFalse)
8675                       break;
8676                   }
8677                   composite_view=DestroyCacheView(composite_view);
8678                 }
8679             }
8680           if (attribute_flag[9] != 0)    /* "color=>" */
8681             QueryColorCompliance(argument_list[9].string_reference,
8682               AllCompliance,&composite_image->background_color,exception);
8683           if (attribute_flag[12] != 0) /* "interpolate=>" */
8684             image->interpolate=(PixelInterpolateMethod)
8685               argument_list[12].integer_reference;
8686           if (attribute_flag[13] != 0)   /* "args=>" */
8687             (void) SetImageArtifact(composite_image,"compose:args",
8688               argument_list[13].string_reference);
8689           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8690             (void) SetImageArtifact(composite_image,"compose:args",
8691               argument_list[14].string_reference);
8692           clip_to_self=MagickTrue;
8693           if (attribute_flag[15] != 0)
8694             clip_to_self=(MagickBooleanType)
8695               argument_list[15].integer_reference;
8696           /*
8697             Tiling Composition (with orthogonal rotate).
8698           */
8699           rotate_image=(Image *) NULL;
8700           if (attribute_flag[8] != 0)   /* "rotate=>" */
8701             {
8702                /*
8703                  Rotate image.
8704                */
8705                rotate_image=RotateImage(composite_image,
8706                  argument_list[8].real_reference,exception);
8707                if (rotate_image == (Image *) NULL)
8708                  break;
8709             }
8710           if ((attribute_flag[7] != 0) &&
8711               (argument_list[7].integer_reference != 0)) /* tile */
8712             {
8713               ssize_t
8714                 x,
8715                 y;
8716
8717               /*
8718                 Tile the composite image.
8719               */
8720              if (attribute_flag[8] != 0)   /* "tile=>" */
8721                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8722                  "false");
8723              else
8724                (void) SetImageArtifact(composite_image,
8725                  "compose:outside-overlay","false");
8726              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8727                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8728                 {
8729                   if (attribute_flag[8] != 0) /* rotate */
8730                     (void) CompositeImage(image,rotate_image,compose,
8731                       MagickTrue,x,y,exception);
8732                   else
8733                     (void) CompositeImage(image,composite_image,compose,
8734                       MagickTrue,x,y,exception);
8735                 }
8736               if (attribute_flag[8] != 0) /* rotate */
8737                 rotate_image=DestroyImage(rotate_image);
8738               break;
8739             }
8740           /*
8741             Parameter Handling used used ONLY for normal composition.
8742           */
8743           if (attribute_flag[5] != 0) /* gravity */
8744             image->gravity=(GravityType) argument_list[5].integer_reference;
8745           if (attribute_flag[2] != 0) /* geometry offset */
8746             {
8747               SetGeometry(image,&geometry);
8748               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8749                 &geometry);
8750               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8751                 &geometry);
8752             }
8753           if (attribute_flag[3] != 0) /* x offset */
8754             geometry.x=argument_list[3].integer_reference;
8755           if (attribute_flag[4] != 0) /* y offset */
8756             geometry.y=argument_list[4].integer_reference;
8757           if (attribute_flag[10] != 0) /* mask */
8758             {
8759               if ((image->compose == DisplaceCompositeOp) ||
8760                   (image->compose == DistortCompositeOp))
8761                 {
8762                   /*
8763                     Merge Y displacement into X displacement image.
8764                   */
8765                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8766                     exception);
8767                   (void) CompositeImage(composite_image,
8768                     argument_list[10].image_reference,CopyGreenCompositeOp,
8769                     MagickTrue,0,0,exception);
8770                 }
8771               else
8772                 {
8773                   Image
8774                     *mask_image;
8775
8776                   /*
8777                     Set a blending mask for the composition.
8778                   */
8779                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8780                     MagickTrue,exception);
8781                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8782                     exception);
8783                   mask_image=DestroyImage(mask_image);
8784                 }
8785             }
8786           if (attribute_flag[11] != 0) /* channel */
8787             channel=(ChannelType) argument_list[11].integer_reference;
8788           /*
8789             Composite two images (normal composition).
8790           */
8791           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8792             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8793             (double) composite_image->rows,(double) geometry.x,(double)
8794             geometry.y);
8795           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8796             exception);
8797           channel_mask=SetImageChannelMask(image,channel);
8798           if (attribute_flag[8] == 0) /* no rotate */
8799             CompositeImage(image,composite_image,compose,clip_to_self,
8800               geometry.x,geometry.y,exception);
8801           else
8802             {
8803               /*
8804                 Position adjust rotated image then composite.
8805               */
8806               geometry.x-=(ssize_t) (rotate_image->columns-
8807                 composite_image->columns)/2;
8808               geometry.y-=(ssize_t) (rotate_image->rows-
8809                 composite_image->rows)/2;
8810               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8811                 geometry.y,exception);
8812               rotate_image=DestroyImage(rotate_image);
8813             }
8814           if (attribute_flag[10] != 0) /* mask */
8815             {
8816               if ((image->compose == DisplaceCompositeOp) ||
8817                   (image->compose == DistortCompositeOp))
8818                 composite_image=DestroyImage(composite_image);
8819               else
8820                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8821                   exception);
8822             }
8823           (void) SetImageChannelMask(image,channel_mask);
8824           break;
8825         }
8826         case 36:  /* Contrast */
8827         {
8828           if (attribute_flag[0] == 0)
8829             argument_list[0].integer_reference=0;
8830           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8831             MagickTrue : MagickFalse,exception);
8832           break;
8833         }
8834         case 37:  /* CycleColormap */
8835         {
8836           if (attribute_flag[0] == 0)
8837             argument_list[0].integer_reference=6;
8838           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8839             exception);
8840           break;
8841         }
8842         case 38:  /* Draw */
8843         {
8844           DrawInfo
8845             *draw_info;
8846
8847           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8848             (DrawInfo *) NULL);
8849           (void) CloneString(&draw_info->primitive,"point");
8850           if (attribute_flag[0] != 0)
8851             {
8852               if (argument_list[0].integer_reference < 0)
8853                 (void) CloneString(&draw_info->primitive,
8854                   argument_list[0].string_reference);
8855               else
8856                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8857                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8858             }
8859           if (attribute_flag[1] != 0)
8860             {
8861               if (LocaleCompare(draw_info->primitive,"path") == 0)
8862                 {
8863                   (void) ConcatenateString(&draw_info->primitive," '");
8864                   ConcatenateString(&draw_info->primitive,
8865                     argument_list[1].string_reference);
8866                   (void) ConcatenateString(&draw_info->primitive,"'");
8867                 }
8868               else
8869                 {
8870                   (void) ConcatenateString(&draw_info->primitive," ");
8871                   ConcatenateString(&draw_info->primitive,
8872                     argument_list[1].string_reference);
8873                 }
8874             }
8875           if (attribute_flag[2] != 0)
8876             {
8877               (void) ConcatenateString(&draw_info->primitive," ");
8878               (void) ConcatenateString(&draw_info->primitive,
8879                 CommandOptionToMnemonic(MagickMethodOptions,
8880                 argument_list[2].integer_reference));
8881             }
8882           if (attribute_flag[3] != 0)
8883             {
8884               (void) QueryColorCompliance(argument_list[3].string_reference,
8885                 AllCompliance,&draw_info->stroke,exception);
8886               if (argument_list[3].image_reference != (Image *) NULL)
8887                 draw_info->stroke_pattern=CloneImage(
8888                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8889             }
8890           if (attribute_flag[4] != 0)
8891             {
8892               (void) QueryColorCompliance(argument_list[4].string_reference,
8893                 AllCompliance,&draw_info->fill,exception);
8894               if (argument_list[4].image_reference != (Image *) NULL)
8895                 draw_info->fill_pattern=CloneImage(
8896                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8897             }
8898           if (attribute_flag[5] != 0)
8899             draw_info->stroke_width=argument_list[5].real_reference;
8900           if (attribute_flag[6] != 0)
8901             (void) CloneString(&draw_info->font,
8902               argument_list[6].string_reference);
8903           if (attribute_flag[7] != 0)
8904             (void) QueryColorCompliance(argument_list[7].string_reference,
8905               AllCompliance,&draw_info->border_color,exception);
8906           if (attribute_flag[8] != 0)
8907             draw_info->affine.tx=argument_list[8].real_reference;
8908           if (attribute_flag[9] != 0)
8909             draw_info->affine.ty=argument_list[9].real_reference;
8910           if (attribute_flag[20] != 0)
8911             {
8912               AV
8913                 *av;
8914
8915               av=(AV *) argument_list[20].array_reference;
8916               if ((av_len(av) != 3) && (av_len(av) != 5))
8917                 {
8918                   ThrowPerlException(exception,OptionError,
8919                     "affine matrix must have 4 or 6 elements",PackageName);
8920                   goto PerlException;
8921                 }
8922               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8923               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8924               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8925               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8926               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8927                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8928                 {
8929                   ThrowPerlException(exception,OptionError,
8930                     "affine matrix is singular",PackageName);
8931                    goto PerlException;
8932                 }
8933               if (av_len(av) == 5)
8934                 {
8935                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8936                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8937                 }
8938             }
8939           for (j=10; j < 15; j++)
8940           {
8941             if (attribute_flag[j] == 0)
8942               continue;
8943             value=argument_list[j].string_reference;
8944             angle=argument_list[j].real_reference;
8945             current=draw_info->affine;
8946             GetAffineMatrix(&affine);
8947             switch (j)
8948             {
8949               case 10:
8950               {
8951                 /*
8952                   Translate.
8953                 */
8954                 flags=ParseGeometry(value,&geometry_info);
8955                 affine.tx=geometry_info.xi;
8956                 affine.ty=geometry_info.psi;
8957                 if ((flags & PsiValue) == 0)
8958                   affine.ty=affine.tx;
8959                 break;
8960               }
8961               case 11:
8962               {
8963                 /*
8964                   Scale.
8965                 */
8966                 flags=ParseGeometry(value,&geometry_info);
8967                 affine.sx=geometry_info.rho;
8968                 affine.sy=geometry_info.sigma;
8969                 if ((flags & SigmaValue) == 0)
8970                   affine.sy=affine.sx;
8971                 break;
8972               }
8973               case 12:
8974               {
8975                 /*
8976                   Rotate.
8977                 */
8978                 if (angle == 0.0)
8979                   break;
8980                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8981                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8982                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8983                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8984                 break;
8985               }
8986               case 13:
8987               {
8988                 /*
8989                   SkewX.
8990                 */
8991                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8992                 break;
8993               }
8994               case 14:
8995               {
8996                 /*
8997                   SkewY.
8998                 */
8999                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9000                 break;
9001               }
9002             }
9003             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9004             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9005             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9006             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9007             draw_info->affine.tx=
9008               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9009             draw_info->affine.ty=
9010               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9011           }
9012           if (attribute_flag[15] != 0)
9013             draw_info->fill_pattern=CloneImage(
9014               argument_list[15].image_reference,0,0,MagickTrue,exception);
9015           if (attribute_flag[16] != 0)
9016             draw_info->pointsize=argument_list[16].real_reference;
9017           if (attribute_flag[17] != 0)
9018             {
9019               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9020                 ? MagickTrue : MagickFalse;
9021               draw_info->text_antialias=draw_info->stroke_antialias;
9022             }
9023           if (attribute_flag[18] != 0)
9024             (void) CloneString(&draw_info->density,
9025               argument_list[18].string_reference);
9026           if (attribute_flag[19] != 0)
9027             draw_info->stroke_width=argument_list[19].real_reference;
9028           if (attribute_flag[21] != 0)
9029             draw_info->dash_offset=argument_list[21].real_reference;
9030           if (attribute_flag[22] != 0)
9031             {
9032               AV
9033                 *av;
9034
9035               av=(AV *) argument_list[22].array_reference;
9036               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9037                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9038               if (draw_info->dash_pattern != (double *) NULL)
9039                 {
9040                   for (i=0; i <= av_len(av); i++)
9041                     draw_info->dash_pattern[i]=(double)
9042                       SvNV(*(av_fetch(av,i,0)));
9043                   draw_info->dash_pattern[i]=0.0;
9044                 }
9045             }
9046           if (attribute_flag[23] != 0)
9047             image->interpolate=(PixelInterpolateMethod)
9048               argument_list[23].integer_reference;
9049           if ((attribute_flag[24] != 0) &&
9050               (draw_info->fill_pattern != (Image *) NULL))
9051             flags=ParsePageGeometry(draw_info->fill_pattern,
9052               argument_list[24].string_reference,
9053               &draw_info->fill_pattern->tile_offset,exception);
9054           if (attribute_flag[25] != 0)
9055             {
9056               (void) ConcatenateString(&draw_info->primitive," '");
9057               (void) ConcatenateString(&draw_info->primitive,
9058                 argument_list[25].string_reference);
9059               (void) ConcatenateString(&draw_info->primitive,"'");
9060             }
9061           if (attribute_flag[26] != 0)
9062             draw_info->fill_pattern=CloneImage(
9063               argument_list[26].image_reference,0,0,MagickTrue,exception);
9064           if (attribute_flag[27] != 0)
9065             draw_info->stroke_pattern=CloneImage(
9066               argument_list[27].image_reference,0,0,MagickTrue,exception);
9067           if (attribute_flag[28] != 0)
9068             (void) CloneString(&draw_info->primitive,
9069               argument_list[28].string_reference);
9070           if (attribute_flag[29] != 0)
9071             draw_info->kerning=argument_list[29].real_reference;
9072           if (attribute_flag[30] != 0)
9073             draw_info->interline_spacing=argument_list[30].real_reference;
9074           if (attribute_flag[31] != 0)
9075             draw_info->interword_spacing=argument_list[31].real_reference;
9076           if (attribute_flag[32] != 0)
9077             draw_info->direction=(DirectionType)
9078               argument_list[32].integer_reference;
9079           DrawImage(image,draw_info,exception);
9080           draw_info=DestroyDrawInfo(draw_info);
9081           break;
9082         }
9083         case 39:  /* Equalize */
9084         {
9085           if (attribute_flag[0] != 0)
9086             channel=(ChannelType) argument_list[0].integer_reference;
9087           channel_mask=SetImageChannelMask(image,channel);
9088           EqualizeImage(image,exception);
9089           (void) SetImageChannelMask(image,channel_mask);
9090           break;
9091         }
9092         case 40:  /* Gamma */
9093         {
9094           if (attribute_flag[1] != 0)
9095             channel=(ChannelType) argument_list[1].integer_reference;
9096           if (attribute_flag[2] == 0)
9097             argument_list[2].real_reference=1.0;
9098           if (attribute_flag[3] == 0)
9099             argument_list[3].real_reference=1.0;
9100           if (attribute_flag[4] == 0)
9101             argument_list[4].real_reference=1.0;
9102           if (attribute_flag[0] == 0)
9103             {
9104               (void) FormatLocaleString(message,MagickPathExtent,
9105                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9106                 (double) argument_list[3].real_reference,
9107                 (double) argument_list[4].real_reference);
9108               argument_list[0].string_reference=message;
9109             }
9110           (void) GammaImage(image,StringToDouble(
9111             argument_list[0].string_reference,(char **) NULL),exception);
9112           break;
9113         }
9114         case 41:  /* Map */
9115         {
9116           QuantizeInfo
9117             *quantize_info;
9118
9119           if (attribute_flag[0] == 0)
9120             {
9121               ThrowPerlException(exception,OptionError,"MapImageRequired",
9122                 PackageName);
9123               goto PerlException;
9124             }
9125           quantize_info=AcquireQuantizeInfo(info->image_info);
9126           if (attribute_flag[1] != 0)
9127             quantize_info->dither_method=(DitherMethod)
9128               argument_list[1].integer_reference;
9129           (void) RemapImages(quantize_info,image,
9130             argument_list[0].image_reference,exception);
9131           quantize_info=DestroyQuantizeInfo(quantize_info);
9132           break;
9133         }
9134         case 42:  /* MatteFloodfill */
9135         {
9136           DrawInfo
9137             *draw_info;
9138
9139           MagickBooleanType
9140             invert;
9141
9142           PixelInfo
9143             target;
9144
9145           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9146             (DrawInfo *) NULL);
9147           if (attribute_flag[0] != 0)
9148             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9149               &geometry,exception);
9150           if (attribute_flag[1] != 0)
9151             geometry.x=argument_list[1].integer_reference;
9152           if (attribute_flag[2] != 0)
9153             geometry.y=argument_list[2].integer_reference;
9154           if (image->alpha_trait == UndefinedPixelTrait)
9155             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9156           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9157             geometry.x,geometry.y,&target,exception);
9158           if (attribute_flag[4] != 0)
9159             QueryColorCompliance(argument_list[4].string_reference,
9160               AllCompliance,&target,exception);
9161           if (attribute_flag[3] != 0)
9162             target.alpha=StringToDoubleInterval(
9163               argument_list[3].string_reference,(double) (double) QuantumRange+
9164               1.0);
9165           if (attribute_flag[5] != 0)
9166             image->fuzz=StringToDoubleInterval(
9167               argument_list[5].string_reference,(double) QuantumRange+1.0);
9168           invert=MagickFalse;
9169           if (attribute_flag[6] != 0)
9170             invert=(MagickBooleanType) argument_list[6].integer_reference;
9171           channel_mask=SetImageChannelMask(image,AlphaChannel);
9172           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9173             geometry.y,invert,exception);
9174           (void) SetImageChannelMask(image,channel_mask);
9175           draw_info=DestroyDrawInfo(draw_info);
9176           break;
9177         }
9178         case 43:  /* Modulate */
9179         {
9180           char
9181             modulate[MagickPathExtent];
9182
9183           geometry_info.rho=100.0;
9184           geometry_info.sigma=100.0;
9185           geometry_info.xi=100.0;
9186           if (attribute_flag[0] != 0)
9187             (void)ParseGeometry(argument_list[0].string_reference,
9188               &geometry_info);
9189           if (attribute_flag[1] != 0)
9190             geometry_info.xi=argument_list[1].real_reference;
9191           if (attribute_flag[2] != 0)
9192             geometry_info.sigma=argument_list[2].real_reference;
9193           if (attribute_flag[3] != 0)
9194             {
9195               geometry_info.sigma=argument_list[3].real_reference;
9196               SetImageArtifact(image,"modulate:colorspace","HWB");
9197             }
9198           if (attribute_flag[4] != 0)
9199             {
9200               geometry_info.rho=argument_list[4].real_reference;
9201               SetImageArtifact(image,"modulate:colorspace","HSB");
9202             }
9203           if (attribute_flag[5] != 0)
9204             {
9205               geometry_info.sigma=argument_list[5].real_reference;
9206               SetImageArtifact(image,"modulate:colorspace","HSL");
9207             }
9208           if (attribute_flag[6] != 0)
9209             {
9210               geometry_info.rho=argument_list[6].real_reference;
9211               SetImageArtifact(image,"modulate:colorspace","HWB");
9212             }
9213           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9214             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9215           (void) ModulateImage(image,modulate,exception);
9216           break;
9217         }
9218         case 44:  /* Negate */
9219         {
9220           if (attribute_flag[0] == 0)
9221             argument_list[0].integer_reference=0;
9222           if (attribute_flag[1] != 0)
9223             channel=(ChannelType) argument_list[1].integer_reference;
9224           channel_mask=SetImageChannelMask(image,channel);
9225           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9226             MagickTrue : MagickFalse,exception);
9227           (void) SetImageChannelMask(image,channel_mask);
9228           break;
9229         }
9230         case 45:  /* Normalize */
9231         {
9232           if (attribute_flag[0] != 0)
9233             channel=(ChannelType) argument_list[0].integer_reference;
9234           channel_mask=SetImageChannelMask(image,channel);
9235           NormalizeImage(image,exception);
9236           (void) SetImageChannelMask(image,channel_mask);
9237           break;
9238         }
9239         case 46:  /* NumberColors */
9240           break;
9241         case 47:  /* Opaque */
9242         {
9243           MagickBooleanType
9244             invert;
9245
9246           PixelInfo
9247             fill_color,
9248             target;
9249
9250           (void) QueryColorCompliance("none",AllCompliance,&target,
9251              exception);
9252           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9253             exception);
9254           if (attribute_flag[0] != 0)
9255             (void) QueryColorCompliance(argument_list[0].string_reference,
9256               AllCompliance,&target,exception);
9257           if (attribute_flag[1] != 0)
9258             (void) QueryColorCompliance(argument_list[1].string_reference,
9259               AllCompliance,&fill_color,exception);
9260           if (attribute_flag[2] != 0)
9261             image->fuzz=StringToDoubleInterval(
9262               argument_list[2].string_reference,(double) QuantumRange+1.0);
9263           if (attribute_flag[3] != 0)
9264             channel=(ChannelType) argument_list[3].integer_reference;
9265           invert=MagickFalse;
9266           if (attribute_flag[4] != 0)
9267             invert=(MagickBooleanType) argument_list[4].integer_reference;
9268           channel_mask=SetImageChannelMask(image,channel);
9269           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9270           (void) SetImageChannelMask(image,channel_mask);
9271           break;
9272         }
9273         case 48:  /* Quantize */
9274         {
9275           QuantizeInfo
9276             *quantize_info;
9277
9278           quantize_info=AcquireQuantizeInfo(info->image_info);
9279           if (attribute_flag[0] != 0)
9280             quantize_info->number_colors=(size_t)
9281               argument_list[0].integer_reference;
9282           if (attribute_flag[1] != 0)
9283             quantize_info->tree_depth=(size_t)
9284               argument_list[1].integer_reference;
9285           if (attribute_flag[2] != 0)
9286             quantize_info->colorspace=(ColorspaceType)
9287               argument_list[2].integer_reference;
9288           if (attribute_flag[3] != 0)
9289             quantize_info->dither_method=(DitherMethod)
9290               argument_list[3].integer_reference;
9291           if (attribute_flag[4] != 0)
9292             quantize_info->measure_error=
9293               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9294           if (attribute_flag[6] != 0)
9295             (void) QueryColorCompliance(argument_list[6].string_reference,
9296               AllCompliance,&image->transparent_color,exception);
9297           if (attribute_flag[7] != 0)
9298             quantize_info->dither_method=(DitherMethod)
9299               argument_list[7].integer_reference;
9300           if (attribute_flag[5] && argument_list[5].integer_reference)
9301             (void) QuantizeImages(quantize_info,image,exception);
9302           else
9303             if ((image->storage_class == DirectClass) ||
9304                (image->colors > quantize_info->number_colors) ||
9305                (quantize_info->colorspace == GRAYColorspace))
9306              (void) QuantizeImage(quantize_info,image,exception);
9307            else
9308              CompressImageColormap(image,exception);
9309           quantize_info=DestroyQuantizeInfo(quantize_info);
9310           break;
9311         }
9312         case 49:  /* Raise */
9313         {
9314           if (attribute_flag[0] != 0)
9315             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9316               &geometry,exception);
9317           if (attribute_flag[1] != 0)
9318             geometry.width=argument_list[1].integer_reference;
9319           if (attribute_flag[2] != 0)
9320             geometry.height=argument_list[2].integer_reference;
9321           if (attribute_flag[3] == 0)
9322             argument_list[3].integer_reference=1;
9323           (void) RaiseImage(image,&geometry,
9324             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9325             exception);
9326           break;
9327         }
9328         case 50:  /* Segment */
9329         {
9330           ColorspaceType
9331             colorspace;
9332
9333           double
9334             cluster_threshold,
9335             smoothing_threshold;
9336
9337           MagickBooleanType
9338             verbose;
9339
9340           cluster_threshold=1.0;
9341           smoothing_threshold=1.5;
9342           colorspace=sRGBColorspace;
9343           verbose=MagickFalse;
9344           if (attribute_flag[0] != 0)
9345             {
9346               flags=ParseGeometry(argument_list[0].string_reference,
9347                 &geometry_info);
9348               cluster_threshold=geometry_info.rho;
9349               if (flags & SigmaValue)
9350                 smoothing_threshold=geometry_info.sigma;
9351             }
9352           if (attribute_flag[1] != 0)
9353             cluster_threshold=argument_list[1].real_reference;
9354           if (attribute_flag[2] != 0)
9355             smoothing_threshold=argument_list[2].real_reference;
9356           if (attribute_flag[3] != 0)
9357             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9358           if (attribute_flag[4] != 0)
9359             verbose=argument_list[4].integer_reference != 0 ?
9360               MagickTrue : MagickFalse;
9361           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9362             smoothing_threshold,exception);
9363           break;
9364         }
9365         case 51:  /* Signature */
9366         {
9367           (void) SignatureImage(image,exception);
9368           break;
9369         }
9370         case 52:  /* Solarize */
9371         {
9372           geometry_info.rho=QuantumRange/2.0;
9373           if (attribute_flag[0] != 0)
9374             flags=ParseGeometry(argument_list[0].string_reference,
9375               &geometry_info);
9376           if (attribute_flag[1] != 0)
9377             geometry_info.rho=StringToDoubleInterval(
9378               argument_list[1].string_reference,(double) QuantumRange+1.0);
9379           (void) SolarizeImage(image,geometry_info.rho,exception);
9380           break;
9381         }
9382         case 53:  /* Sync */
9383         {
9384           (void) SyncImage(image,exception);
9385           break;
9386         }
9387         case 54:  /* Texture */
9388         {
9389           if (attribute_flag[0] == 0)
9390             break;
9391           TextureImage(image,argument_list[0].image_reference,exception);
9392           break;
9393         }
9394         case 55:  /* Evalute */
9395         {
9396           MagickEvaluateOperator
9397             op;
9398
9399           op=SetEvaluateOperator;
9400           if (attribute_flag[0] == MagickFalse)
9401             argument_list[0].real_reference=0.0;
9402           if (attribute_flag[1] != MagickFalse)
9403             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9404           if (attribute_flag[2] != MagickFalse)
9405             channel=(ChannelType) argument_list[2].integer_reference;
9406           channel_mask=SetImageChannelMask(image,channel);
9407           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9408             exception);
9409           (void) SetImageChannelMask(image,channel_mask);
9410           break;
9411         }
9412         case 56:  /* Transparent */
9413         {
9414           double
9415             opacity;
9416
9417           MagickBooleanType
9418             invert;
9419
9420           PixelInfo
9421             target;
9422
9423           (void) QueryColorCompliance("none",AllCompliance,&target,
9424             exception);
9425           if (attribute_flag[0] != 0)
9426             (void) QueryColorCompliance(argument_list[0].string_reference,
9427               AllCompliance,&target,exception);
9428           opacity=TransparentAlpha;
9429           if (attribute_flag[1] != 0)
9430             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9431               (double) QuantumRange+1.0);
9432           if (attribute_flag[2] != 0)
9433             image->fuzz=StringToDoubleInterval(
9434               argument_list[2].string_reference,(double) QuantumRange+1.0);
9435           if (attribute_flag[3] == 0)
9436             argument_list[3].integer_reference=0;
9437           invert=MagickFalse;
9438           if (attribute_flag[3] != 0)
9439             invert=(MagickBooleanType) argument_list[3].integer_reference;
9440           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9441             invert,exception);
9442           break;
9443         }
9444         case 57:  /* Threshold */
9445         {
9446           double
9447             threshold;
9448
9449           if (attribute_flag[0] == 0)
9450             argument_list[0].string_reference="50%";
9451           if (attribute_flag[1] != 0)
9452             channel=(ChannelType) argument_list[1].integer_reference;
9453           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9454             (double) QuantumRange+1.0);
9455           channel_mask=SetImageChannelMask(image,channel);
9456           (void) BilevelImage(image,threshold,exception);
9457           (void) SetImageChannelMask(image,channel_mask);
9458           break;
9459         }
9460         case 58:  /* Charcoal */
9461         {
9462           if (attribute_flag[0] != 0)
9463             {
9464               flags=ParseGeometry(argument_list[0].string_reference,
9465                 &geometry_info);
9466               if ((flags & SigmaValue) == 0)
9467                 geometry_info.sigma=1.0;
9468             }
9469           if (attribute_flag[1] != 0)
9470             geometry_info.rho=argument_list[1].real_reference;
9471           if (attribute_flag[2] != 0)
9472             geometry_info.sigma=argument_list[2].real_reference;
9473           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9474             exception);
9475           break;
9476         }
9477         case 59:  /* Trim */
9478         {
9479           if (attribute_flag[0] != 0)
9480             image->fuzz=StringToDoubleInterval(
9481               argument_list[0].string_reference,(double) QuantumRange+1.0);
9482           image=TrimImage(image,exception);
9483           break;
9484         }
9485         case 60:  /* Wave */
9486         {
9487           PixelInterpolateMethod
9488             method;
9489
9490           if (attribute_flag[0] != 0)
9491             {
9492               flags=ParseGeometry(argument_list[0].string_reference,
9493                 &geometry_info);
9494               if ((flags & SigmaValue) == 0)
9495                 geometry_info.sigma=1.0;
9496             }
9497           if (attribute_flag[1] != 0)
9498             geometry_info.rho=argument_list[1].real_reference;
9499           if (attribute_flag[2] != 0)
9500             geometry_info.sigma=argument_list[2].real_reference;
9501           method=UndefinedInterpolatePixel;
9502           if (attribute_flag[3] != 0)
9503             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9504           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9505             method,exception);
9506           break;
9507         }
9508         case 61:  /* Separate */
9509         {
9510           if (attribute_flag[0] != 0)
9511             channel=(ChannelType) argument_list[0].integer_reference;
9512           image=SeparateImage(image,channel,exception);
9513           break;
9514         }
9515         case 63:  /* Stereo */
9516         {
9517           if (attribute_flag[0] == 0)
9518             {
9519               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9520                 PackageName);
9521               goto PerlException;
9522             }
9523           if (attribute_flag[1] != 0)
9524             geometry.x=argument_list[1].integer_reference;
9525           if (attribute_flag[2] != 0)
9526             geometry.y=argument_list[2].integer_reference;
9527           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9528             geometry.x,geometry.y,exception);
9529           break;
9530         }
9531         case 64:  /* Stegano */
9532         {
9533           if (attribute_flag[0] == 0)
9534             {
9535               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9536                 PackageName);
9537               goto PerlException;
9538             }
9539           if (attribute_flag[1] == 0)
9540             argument_list[1].integer_reference=0;
9541           image->offset=argument_list[1].integer_reference;
9542           image=SteganoImage(image,argument_list[0].image_reference,exception);
9543           break;
9544         }
9545         case 65:  /* Deconstruct */
9546         {
9547           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9548           break;
9549         }
9550         case 66:  /* GaussianBlur */
9551         {
9552           if (attribute_flag[0] != 0)
9553             {
9554               flags=ParseGeometry(argument_list[0].string_reference,
9555                 &geometry_info);
9556               if ((flags & SigmaValue) == 0)
9557                 geometry_info.sigma=1.0;
9558             }
9559           if (attribute_flag[1] != 0)
9560             geometry_info.rho=argument_list[1].real_reference;
9561           if (attribute_flag[2] != 0)
9562             geometry_info.sigma=argument_list[2].real_reference;
9563           if (attribute_flag[3] != 0)
9564             channel=(ChannelType) argument_list[3].integer_reference;
9565           channel_mask=SetImageChannelMask(image,channel);
9566           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9567             exception);
9568           if (image != (Image *) NULL)
9569             (void) SetImageChannelMask(image,channel_mask);
9570           break;
9571         }
9572         case 67:  /* Convolve */
9573         {
9574           KernelInfo
9575             *kernel;
9576
9577           kernel=(KernelInfo *) NULL;
9578           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9579             break;
9580           if (attribute_flag[0] != 0)
9581             {
9582               AV
9583                 *av;
9584
9585               size_t
9586                 order;
9587
9588               kernel=AcquireKernelInfo((const char *) NULL,exception);
9589               if (kernel == (KernelInfo *) NULL)
9590                 break;
9591               av=(AV *) argument_list[0].array_reference;
9592               order=(size_t) sqrt(av_len(av)+1);
9593               kernel->width=order;
9594               kernel->height=order;
9595               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9596                 order*sizeof(*kernel->values));
9597               if (kernel->values == (MagickRealType *) NULL)
9598                 {
9599                   kernel=DestroyKernelInfo(kernel);
9600                   ThrowPerlException(exception,ResourceLimitFatalError,
9601                     "MemoryAllocationFailed",PackageName);
9602                   goto PerlException;
9603                 }
9604               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9605                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9606               for ( ; j < (ssize_t) (order*order); j++)
9607                 kernel->values[j]=0.0;
9608             }
9609           if (attribute_flag[1] != 0)
9610             channel=(ChannelType) argument_list[1].integer_reference;
9611           if (attribute_flag[2] != 0)
9612             SetImageArtifact(image,"filter:blur",
9613               argument_list[2].string_reference);
9614           if (attribute_flag[3] != 0)
9615             {
9616               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9617                 exception);
9618               if (kernel == (KernelInfo *) NULL)
9619                 break;
9620             }
9621           channel_mask=SetImageChannelMask(image,channel);
9622           image=ConvolveImage(image,kernel,exception);
9623           if (image != (Image *) NULL)
9624             (void) SetImageChannelMask(image,channel_mask);
9625           kernel=DestroyKernelInfo(kernel);
9626           break;
9627         }
9628         case 68:  /* Profile */
9629         {
9630           const char
9631             *name;
9632
9633           Image
9634             *profile_image;
9635
9636           ImageInfo
9637             *profile_info;
9638
9639           StringInfo
9640             *profile;
9641
9642           name="*";
9643           if (attribute_flag[0] != 0)
9644             name=argument_list[0].string_reference;
9645           if (attribute_flag[2] != 0)
9646             image->rendering_intent=(RenderingIntent)
9647               argument_list[2].integer_reference;
9648           if (attribute_flag[3] != 0)
9649             image->black_point_compensation=
9650               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9651           if (attribute_flag[1] != 0)
9652             {
9653               if (argument_list[1].length == 0)
9654                 {
9655                   /*
9656                     Remove a profile from the image.
9657                   */
9658                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9659                     exception);
9660                   break;
9661                 }
9662               /*
9663                 Associate user supplied profile with the image.
9664               */
9665               profile=AcquireStringInfo(argument_list[1].length);
9666               SetStringInfoDatum(profile,(const unsigned char *)
9667                 argument_list[1].string_reference);
9668               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9669                 (size_t) GetStringInfoLength(profile),exception);
9670               profile=DestroyStringInfo(profile);
9671               break;
9672             }
9673           /*
9674             Associate a profile with the image.
9675           */
9676           profile_info=CloneImageInfo(info ? info->image_info :
9677             (ImageInfo *) NULL);
9678           profile_image=ReadImages(profile_info,name,exception);
9679           if (profile_image == (Image *) NULL)
9680             break;
9681           ResetImageProfileIterator(profile_image);
9682           name=GetNextImageProfile(profile_image);
9683           while (name != (const char *) NULL)
9684           {
9685             const StringInfo
9686               *profile;
9687
9688             profile=GetImageProfile(profile_image,name);
9689             if (profile != (const StringInfo *) NULL)
9690               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9691                 (size_t) GetStringInfoLength(profile),exception);
9692             name=GetNextImageProfile(profile_image);
9693           }
9694           profile_image=DestroyImage(profile_image);
9695           profile_info=DestroyImageInfo(profile_info);
9696           break;
9697         }
9698         case 69:  /* UnsharpMask */
9699         {
9700           if (attribute_flag[0] != 0)
9701             {
9702               flags=ParseGeometry(argument_list[0].string_reference,
9703                 &geometry_info);
9704               if ((flags & SigmaValue) == 0)
9705                 geometry_info.sigma=1.0;
9706               if ((flags & XiValue) == 0)
9707                 geometry_info.xi=1.0;
9708               if ((flags & PsiValue) == 0)
9709                 geometry_info.psi=0.5;
9710             }
9711           if (attribute_flag[1] != 0)
9712             geometry_info.rho=argument_list[1].real_reference;
9713           if (attribute_flag[2] != 0)
9714             geometry_info.sigma=argument_list[2].real_reference;
9715           if (attribute_flag[3] != 0)
9716             geometry_info.xi=argument_list[3].real_reference;
9717           if (attribute_flag[4] != 0)
9718             geometry_info.psi=argument_list[4].real_reference;
9719           if (attribute_flag[5] != 0)
9720             channel=(ChannelType) argument_list[5].integer_reference;
9721           channel_mask=SetImageChannelMask(image,channel);
9722           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9723             geometry_info.xi,geometry_info.psi,exception);
9724           if (image != (Image *) NULL)
9725             (void) SetImageChannelMask(image,channel_mask);
9726           break;
9727         }
9728         case 70:  /* MotionBlur */
9729         {
9730           if (attribute_flag[0] != 0)
9731             {
9732               flags=ParseGeometry(argument_list[0].string_reference,
9733                 &geometry_info);
9734               if ((flags & SigmaValue) == 0)
9735                 geometry_info.sigma=1.0;
9736               if ((flags & XiValue) == 0)
9737                 geometry_info.xi=1.0;
9738             }
9739           if (attribute_flag[1] != 0)
9740             geometry_info.rho=argument_list[1].real_reference;
9741           if (attribute_flag[2] != 0)
9742             geometry_info.sigma=argument_list[2].real_reference;
9743           if (attribute_flag[3] != 0)
9744             geometry_info.xi=argument_list[3].real_reference;
9745           if (attribute_flag[4] != 0)
9746             channel=(ChannelType) argument_list[4].integer_reference;
9747           channel_mask=SetImageChannelMask(image,channel);
9748           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9749             geometry_info.xi,exception);
9750           if (image != (Image *) NULL)
9751             (void) SetImageChannelMask(image,channel_mask);
9752           break;
9753         }
9754         case 71:  /* OrderedDither */
9755         {
9756           if (attribute_flag[0] == 0)
9757             argument_list[0].string_reference="o8x8";
9758           if (attribute_flag[1] != 0)
9759             channel=(ChannelType) argument_list[1].integer_reference;
9760           channel_mask=SetImageChannelMask(image,channel);
9761           (void) OrderedDitherImage(image,argument_list[0].string_reference,
9762             exception);
9763           (void) SetImageChannelMask(image,channel_mask);
9764           break;
9765         }
9766         case 72:  /* Shave */
9767         {
9768           if (attribute_flag[0] != 0)
9769             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9770               &geometry,exception);
9771           if (attribute_flag[1] != 0)
9772             geometry.width=argument_list[1].integer_reference;
9773           if (attribute_flag[2] != 0)
9774             geometry.height=argument_list[2].integer_reference;
9775           image=ShaveImage(image,&geometry,exception);
9776           break;
9777         }
9778         case 73:  /* Level */
9779         {
9780           double
9781             black_point,
9782             gamma,
9783             white_point;
9784
9785           black_point=0.0;
9786           white_point=(double) image->columns*image->rows;
9787           gamma=1.0;
9788           if (attribute_flag[0] != 0)
9789             {
9790               flags=ParseGeometry(argument_list[0].string_reference,
9791                 &geometry_info);
9792               black_point=geometry_info.rho;
9793               if ((flags & SigmaValue) != 0)
9794                 white_point=geometry_info.sigma;
9795               if ((flags & XiValue) != 0)
9796                 gamma=geometry_info.xi;
9797               if ((flags & PercentValue) != 0)
9798                 {
9799                   black_point*=(double) (QuantumRange/100.0);
9800                   white_point*=(double) (QuantumRange/100.0);
9801                 }
9802               if ((flags & SigmaValue) == 0)
9803                 white_point=(double) QuantumRange-black_point;
9804             }
9805           if (attribute_flag[1] != 0)
9806             black_point=argument_list[1].real_reference;
9807           if (attribute_flag[2] != 0)
9808             white_point=argument_list[2].real_reference;
9809           if (attribute_flag[3] != 0)
9810             gamma=argument_list[3].real_reference;
9811           if (attribute_flag[4] != 0)
9812             channel=(ChannelType) argument_list[4].integer_reference;
9813           if (attribute_flag[5] != 0)
9814             {
9815               argument_list[0].real_reference=argument_list[5].real_reference;
9816               attribute_flag[0]=attribute_flag[5];
9817             }
9818           channel_mask=SetImageChannelMask(image,channel);
9819           (void) LevelImage(image,black_point,white_point,gamma,exception);
9820           (void) SetImageChannelMask(image,channel_mask);
9821           break;
9822         }
9823         case 74:  /* Clip */
9824         {
9825           if (attribute_flag[0] == 0)
9826             argument_list[0].string_reference="#1";
9827           if (attribute_flag[1] == 0)
9828             argument_list[1].integer_reference=MagickTrue;
9829           (void) ClipImagePath(image,argument_list[0].string_reference,
9830             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9831             exception);
9832           break;
9833         }
9834         case 75:  /* AffineTransform */
9835         {
9836           DrawInfo
9837             *draw_info;
9838
9839           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9840             (DrawInfo *) NULL);
9841           if (attribute_flag[0] != 0)
9842             {
9843               AV
9844                 *av;
9845
9846               av=(AV *) argument_list[0].array_reference;
9847               if ((av_len(av) != 3) && (av_len(av) != 5))
9848                 {
9849                   ThrowPerlException(exception,OptionError,
9850                     "affine matrix must have 4 or 6 elements",PackageName);
9851                   goto PerlException;
9852                 }
9853               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9854               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9855               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9856               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9857               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9858                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9859                 {
9860                   ThrowPerlException(exception,OptionError,
9861                     "affine matrix is singular",PackageName);
9862                    goto PerlException;
9863                 }
9864               if (av_len(av) == 5)
9865                 {
9866                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9867                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9868                 }
9869             }
9870           for (j=1; j < 6; j++)
9871           {
9872             if (attribute_flag[j] == 0)
9873               continue;
9874             value=argument_list[j].string_reference;
9875             angle=argument_list[j].real_reference;
9876             current=draw_info->affine;
9877             GetAffineMatrix(&affine);
9878             switch (j)
9879             {
9880               case 1:
9881               {
9882                 /*
9883                   Translate.
9884                 */
9885                 flags=ParseGeometry(value,&geometry_info);
9886                 affine.tx=geometry_info.xi;
9887                 affine.ty=geometry_info.psi;
9888                 if ((flags & PsiValue) == 0)
9889                   affine.ty=affine.tx;
9890                 break;
9891               }
9892               case 2:
9893               {
9894                 /*
9895                   Scale.
9896                 */
9897                 flags=ParseGeometry(value,&geometry_info);
9898                 affine.sx=geometry_info.rho;
9899                 affine.sy=geometry_info.sigma;
9900                 if ((flags & SigmaValue) == 0)
9901                   affine.sy=affine.sx;
9902                 break;
9903               }
9904               case 3:
9905               {
9906                 /*
9907                   Rotate.
9908                 */
9909                 if (angle == 0.0)
9910                   break;
9911                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9912                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9913                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9914                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9915                 break;
9916               }
9917               case 4:
9918               {
9919                 /*
9920                   SkewX.
9921                 */
9922                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9923                 break;
9924               }
9925               case 5:
9926               {
9927                 /*
9928                   SkewY.
9929                 */
9930                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9931                 break;
9932               }
9933             }
9934             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9935             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9936             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9937             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9938             draw_info->affine.tx=
9939               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9940             draw_info->affine.ty=
9941               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9942           }
9943           if (attribute_flag[6] != 0)
9944             image->interpolate=(PixelInterpolateMethod)
9945               argument_list[6].integer_reference;
9946           if (attribute_flag[7] != 0)
9947             QueryColorCompliance(argument_list[7].string_reference,
9948               AllCompliance,&image->background_color,exception);
9949           image=AffineTransformImage(image,&draw_info->affine,exception);
9950           draw_info=DestroyDrawInfo(draw_info);
9951           break;
9952         }
9953         case 76:  /* Difference */
9954         {
9955           if (attribute_flag[0] == 0)
9956             {
9957               ThrowPerlException(exception,OptionError,
9958                 "ReferenceImageRequired",PackageName);
9959               goto PerlException;
9960             }
9961           if (attribute_flag[1] != 0)
9962             image->fuzz=StringToDoubleInterval(
9963               argument_list[1].string_reference,(double) QuantumRange+1.0);
9964           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9965             exception);
9966           break;
9967         }
9968         case 77:  /* AdaptiveThreshold */
9969         {
9970           if (attribute_flag[0] != 0)
9971             {
9972               flags=ParseGeometry(argument_list[0].string_reference,
9973                 &geometry_info);
9974               if ((flags & PercentValue) != 0)
9975                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9976             }
9977           if (attribute_flag[1] != 0)
9978             geometry_info.rho=argument_list[1].integer_reference;
9979           if (attribute_flag[2] != 0)
9980             geometry_info.sigma=argument_list[2].integer_reference;
9981           if (attribute_flag[3] != 0)
9982             geometry_info.xi=argument_list[3].integer_reference;;
9983           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9984             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9985           break;
9986         }
9987         case 78:  /* Resample */
9988         {
9989           size_t
9990             height,
9991             width;
9992
9993           if (attribute_flag[0] != 0)
9994             {
9995               flags=ParseGeometry(argument_list[0].string_reference,
9996                 &geometry_info);
9997               if ((flags & SigmaValue) == 0)
9998                 geometry_info.sigma=geometry_info.rho;
9999             }
10000           if (attribute_flag[1] != 0)
10001             geometry_info.rho=argument_list[1].real_reference;
10002           if (attribute_flag[2] != 0)
10003             geometry_info.sigma=argument_list[2].real_reference;
10004           if (attribute_flag[3] == 0)
10005             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10006           if (attribute_flag[4] == 0)
10007             SetImageArtifact(image,"filter:support",
10008               argument_list[4].string_reference);
10009           width=(size_t) (geometry_info.rho*image->columns/
10010             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10011           height=(size_t) (geometry_info.sigma*image->rows/
10012             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10013           image=ResizeImage(image,width,height,(FilterType)
10014             argument_list[3].integer_reference,exception);
10015           if (image != (Image *) NULL)
10016             {
10017               image->resolution.x=geometry_info.rho;
10018               image->resolution.y=geometry_info.sigma;
10019             }
10020           break;
10021         }
10022         case 79:  /* Describe */
10023         {
10024           if (attribute_flag[0] == 0)
10025             argument_list[0].file_reference=(FILE *) NULL;
10026           if (attribute_flag[1] != 0)
10027             (void) SetImageArtifact(image,"identify:features",
10028               argument_list[1].string_reference);
10029           (void) IdentifyImage(image,argument_list[0].file_reference,
10030             MagickTrue,exception);
10031           break;
10032         }
10033         case 80:  /* BlackThreshold */
10034         {
10035           if (attribute_flag[0] == 0)
10036             argument_list[0].string_reference="50%";
10037           if (attribute_flag[2] != 0)
10038             channel=(ChannelType) argument_list[2].integer_reference;
10039           channel_mask=SetImageChannelMask(image,channel);
10040           BlackThresholdImage(image,argument_list[0].string_reference,
10041             exception);
10042           (void) SetImageChannelMask(image,channel_mask);
10043           break;
10044         }
10045         case 81:  /* WhiteThreshold */
10046         {
10047           if (attribute_flag[0] == 0)
10048             argument_list[0].string_reference="50%";
10049           if (attribute_flag[2] != 0)
10050             channel=(ChannelType) argument_list[2].integer_reference;
10051           channel_mask=SetImageChannelMask(image,channel);
10052           WhiteThresholdImage(image,argument_list[0].string_reference,
10053             exception);
10054           (void) SetImageChannelMask(image,channel_mask);
10055           break;
10056         }
10057         case 82:  /* RotationalBlur */
10058         {
10059           if (attribute_flag[0] != 0)
10060             {
10061               flags=ParseGeometry(argument_list[0].string_reference,
10062                 &geometry_info);
10063             }
10064           if (attribute_flag[1] != 0)
10065             geometry_info.rho=argument_list[1].real_reference;
10066           if (attribute_flag[2] != 0)
10067             channel=(ChannelType) argument_list[2].integer_reference;
10068           channel_mask=SetImageChannelMask(image,channel);
10069           image=RotationalBlurImage(image,geometry_info.rho,exception);
10070           if (image != (Image *) NULL)
10071             (void) SetImageChannelMask(image,channel_mask);
10072           break;
10073         }
10074         case 83:  /* Thumbnail */
10075         {
10076           if (attribute_flag[0] != 0)
10077             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10078               &geometry,exception);
10079           if (attribute_flag[1] != 0)
10080             geometry.width=argument_list[1].integer_reference;
10081           if (attribute_flag[2] != 0)
10082             geometry.height=argument_list[2].integer_reference;
10083           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10084           break;
10085         }
10086         case 84:  /* Strip */
10087         {
10088           (void) StripImage(image,exception);
10089           break;
10090         }
10091         case 85:  /* Tint */
10092         {
10093           PixelInfo
10094             tint;
10095
10096           GetPixelInfo(image,&tint);
10097           if (attribute_flag[0] != 0)
10098             (void) QueryColorCompliance(argument_list[0].string_reference,
10099               AllCompliance,&tint,exception);
10100           if (attribute_flag[1] == 0)
10101             argument_list[1].string_reference="100";
10102           image=TintImage(image,argument_list[1].string_reference,&tint,
10103             exception);
10104           break;
10105         }
10106         case 86:  /* Channel */
10107         {
10108           if (attribute_flag[0] != 0)
10109             channel=(ChannelType) argument_list[0].integer_reference;
10110           image=SeparateImage(image,channel,exception);
10111           break;
10112         }
10113         case 87:  /* Splice */
10114         {
10115           if (attribute_flag[7] != 0)
10116             image->gravity=(GravityType) argument_list[7].integer_reference;
10117           if (attribute_flag[0] != 0)
10118             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10119               &geometry,exception);
10120           if (attribute_flag[1] != 0)
10121             geometry.width=argument_list[1].integer_reference;
10122           if (attribute_flag[2] != 0)
10123             geometry.height=argument_list[2].integer_reference;
10124           if (attribute_flag[3] != 0)
10125             geometry.x=argument_list[3].integer_reference;
10126           if (attribute_flag[4] != 0)
10127             geometry.y=argument_list[4].integer_reference;
10128           if (attribute_flag[5] != 0)
10129             image->fuzz=StringToDoubleInterval(
10130               argument_list[5].string_reference,(double) QuantumRange+1.0);
10131           if (attribute_flag[6] != 0)
10132             (void) QueryColorCompliance(argument_list[6].string_reference,
10133               AllCompliance,&image->background_color,exception);
10134           image=SpliceImage(image,&geometry,exception);
10135           break;
10136         }
10137         case 88:  /* Posterize */
10138         {
10139           if (attribute_flag[0] == 0)
10140             argument_list[0].integer_reference=3;
10141           if (attribute_flag[1] == 0)
10142             argument_list[1].integer_reference=0;
10143           (void) PosterizeImage(image,argument_list[0].integer_reference,
10144             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10145             NoDitherMethod,exception);
10146           break;
10147         }
10148         case 89:  /* Shadow */
10149         {
10150           if (attribute_flag[0] != 0)
10151             {
10152               flags=ParseGeometry(argument_list[0].string_reference,
10153                 &geometry_info);
10154               if ((flags & SigmaValue) == 0)
10155                 geometry_info.sigma=1.0;
10156               if ((flags & XiValue) == 0)
10157                 geometry_info.xi=4.0;
10158               if ((flags & PsiValue) == 0)
10159                 geometry_info.psi=4.0;
10160             }
10161           if (attribute_flag[1] != 0)
10162             geometry_info.rho=argument_list[1].real_reference;
10163           if (attribute_flag[2] != 0)
10164             geometry_info.sigma=argument_list[2].real_reference;
10165           if (attribute_flag[3] != 0)
10166             geometry_info.xi=argument_list[3].integer_reference;
10167           if (attribute_flag[4] != 0)
10168             geometry_info.psi=argument_list[4].integer_reference;
10169           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10170             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10171             ceil(geometry_info.psi-0.5),exception);
10172           break;
10173         }
10174         case 90:  /* Identify */
10175         {
10176           if (attribute_flag[0] == 0)
10177             argument_list[0].file_reference=(FILE *) NULL;
10178           if (attribute_flag[1] != 0)
10179             (void) SetImageArtifact(image,"identify:features",
10180               argument_list[1].string_reference);
10181           if ((attribute_flag[2] != 0) &&
10182               (argument_list[2].integer_reference != 0))
10183             (void) SetImageArtifact(image,"identify:unique","true");
10184           (void) IdentifyImage(image,argument_list[0].file_reference,
10185             MagickTrue,exception);
10186           break;
10187         }
10188         case 91:  /* SepiaTone */
10189         {
10190           if (attribute_flag[0] == 0)
10191             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10192           image=SepiaToneImage(image,argument_list[0].real_reference,
10193             exception);
10194           break;
10195         }
10196         case 92:  /* SigmoidalContrast */
10197         {
10198           MagickBooleanType
10199             sharpen;
10200
10201           if (attribute_flag[0] != 0)
10202             {
10203               flags=ParseGeometry(argument_list[0].string_reference,
10204                 &geometry_info);
10205               if ((flags & SigmaValue) == 0)
10206                 geometry_info.sigma=QuantumRange/2.0;
10207               if ((flags & PercentValue) != 0)
10208                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10209             }
10210           if (attribute_flag[1] != 0)
10211             geometry_info.rho=argument_list[1].real_reference;
10212           if (attribute_flag[2] != 0)
10213             geometry_info.sigma=argument_list[2].real_reference;
10214           if (attribute_flag[3] != 0)
10215             channel=(ChannelType) argument_list[3].integer_reference;
10216           sharpen=MagickTrue;
10217           if (attribute_flag[4] != 0)
10218             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10219               MagickFalse;
10220           channel_mask=SetImageChannelMask(image,channel);
10221           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10222             geometry_info.sigma,exception);
10223           (void) SetImageChannelMask(image,channel_mask);
10224           break;
10225         }
10226         case 93:  /* Extent */
10227         {
10228           if (attribute_flag[7] != 0)
10229             image->gravity=(GravityType) argument_list[7].integer_reference;
10230           if (attribute_flag[0] != 0)
10231             {
10232               int
10233                 flags;
10234
10235               flags=ParseGravityGeometry(image,
10236                 argument_list[0].string_reference,&geometry,exception);
10237               (void) flags;
10238               if (geometry.width == 0)
10239                 geometry.width=image->columns;
10240               if (geometry.height == 0)
10241                 geometry.height=image->rows;
10242             }
10243           if (attribute_flag[1] != 0)
10244             geometry.width=argument_list[1].integer_reference;
10245           if (attribute_flag[2] != 0)
10246             geometry.height=argument_list[2].integer_reference;
10247           if (attribute_flag[3] != 0)
10248             geometry.x=argument_list[3].integer_reference;
10249           if (attribute_flag[4] != 0)
10250             geometry.y=argument_list[4].integer_reference;
10251           if (attribute_flag[5] != 0)
10252             image->fuzz=StringToDoubleInterval(
10253               argument_list[5].string_reference,(double) QuantumRange+1.0);
10254           if (attribute_flag[6] != 0)
10255             (void) QueryColorCompliance(argument_list[6].string_reference,
10256               AllCompliance,&image->background_color,exception);
10257           image=ExtentImage(image,&geometry,exception);
10258           break;
10259         }
10260         case 94:  /* Vignette */
10261         {
10262           if (attribute_flag[0] != 0)
10263             {
10264               flags=ParseGeometry(argument_list[0].string_reference,
10265                 &geometry_info);
10266               if ((flags & SigmaValue) == 0)
10267                 geometry_info.sigma=1.0;
10268               if ((flags & XiValue) == 0)
10269                 geometry_info.xi=0.1*image->columns;
10270               if ((flags & PsiValue) == 0)
10271                 geometry_info.psi=0.1*image->rows;
10272             }
10273           if (attribute_flag[1] != 0)
10274             geometry_info.rho=argument_list[1].real_reference;
10275           if (attribute_flag[2] != 0)
10276             geometry_info.sigma=argument_list[2].real_reference;
10277           if (attribute_flag[3] != 0)
10278             geometry_info.xi=argument_list[3].integer_reference;
10279           if (attribute_flag[4] != 0)
10280             geometry_info.psi=argument_list[4].integer_reference;
10281           if (attribute_flag[5] != 0)
10282             (void) QueryColorCompliance(argument_list[5].string_reference,
10283               AllCompliance,&image->background_color,exception);
10284           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10285             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10286             ceil(geometry_info.psi-0.5),exception);
10287           break;
10288         }
10289         case 95:  /* ContrastStretch */
10290         {
10291           double
10292             black_point,
10293             white_point;
10294
10295           black_point=0.0;
10296           white_point=(double) image->columns*image->rows;
10297           if (attribute_flag[0] != 0)
10298             {
10299               flags=ParseGeometry(argument_list[0].string_reference,
10300                 &geometry_info);
10301               black_point=geometry_info.rho;
10302               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10303                 black_point;
10304               if ((flags & PercentValue) != 0)
10305                 {
10306                   black_point*=(double) image->columns*image->rows/100.0;
10307                   white_point*=(double) image->columns*image->rows/100.0;
10308                 }
10309               white_point=(double) image->columns*image->rows-
10310                 white_point;
10311             }
10312           if (attribute_flag[1] != 0)
10313             black_point=argument_list[1].real_reference;
10314           if (attribute_flag[2] != 0)
10315             white_point=argument_list[2].real_reference;
10316           if (attribute_flag[4] != 0)
10317             channel=(ChannelType) argument_list[4].integer_reference;
10318           channel_mask=SetImageChannelMask(image,channel);
10319           (void) ContrastStretchImage(image,black_point,white_point,exception);
10320           (void) SetImageChannelMask(image,channel_mask);
10321           break;
10322         }
10323         case 96:  /* Sans0 */
10324         {
10325           break;
10326         }
10327         case 97:  /* Sans1 */
10328         {
10329           break;
10330         }
10331         case 98:  /* AdaptiveSharpen */
10332         {
10333           if (attribute_flag[0] != 0)
10334             {
10335               flags=ParseGeometry(argument_list[0].string_reference,
10336                 &geometry_info);
10337               if ((flags & SigmaValue) == 0)
10338                 geometry_info.sigma=1.0;
10339               if ((flags & XiValue) == 0)
10340                 geometry_info.xi=0.0;
10341             }
10342           if (attribute_flag[1] != 0)
10343             geometry_info.rho=argument_list[1].real_reference;
10344           if (attribute_flag[2] != 0)
10345             geometry_info.sigma=argument_list[2].real_reference;
10346           if (attribute_flag[3] != 0)
10347             geometry_info.xi=argument_list[3].real_reference;
10348           if (attribute_flag[4] != 0)
10349             channel=(ChannelType) argument_list[4].integer_reference;
10350           channel_mask=SetImageChannelMask(image,channel);
10351           image=AdaptiveSharpenImage(image,geometry_info.rho,
10352             geometry_info.sigma,exception);
10353           if (image != (Image *) NULL)
10354             (void) SetImageChannelMask(image,channel_mask);
10355           break;
10356         }
10357         case 99:  /* Transpose */
10358         {
10359           image=TransposeImage(image,exception);
10360           break;
10361         }
10362         case 100:  /* Tranverse */
10363         {
10364           image=TransverseImage(image,exception);
10365           break;
10366         }
10367         case 101:  /* AutoOrient */
10368         {
10369           image=AutoOrientImage(image,image->orientation,exception);
10370           break;
10371         }
10372         case 102:  /* AdaptiveBlur */
10373         {
10374           if (attribute_flag[0] != 0)
10375             {
10376               flags=ParseGeometry(argument_list[0].string_reference,
10377                 &geometry_info);
10378               if ((flags & SigmaValue) == 0)
10379                 geometry_info.sigma=1.0;
10380               if ((flags & XiValue) == 0)
10381                 geometry_info.xi=0.0;
10382             }
10383           if (attribute_flag[1] != 0)
10384             geometry_info.rho=argument_list[1].real_reference;
10385           if (attribute_flag[2] != 0)
10386             geometry_info.sigma=argument_list[2].real_reference;
10387           if (attribute_flag[3] != 0)
10388             channel=(ChannelType) argument_list[3].integer_reference;
10389           channel_mask=SetImageChannelMask(image,channel);
10390           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10391             exception);
10392           if (image != (Image *) NULL)
10393             (void) SetImageChannelMask(image,channel_mask);
10394           break;
10395         }
10396         case 103:  /* Sketch */
10397         {
10398           if (attribute_flag[0] != 0)
10399             {
10400               flags=ParseGeometry(argument_list[0].string_reference,
10401                 &geometry_info);
10402               if ((flags & SigmaValue) == 0)
10403                 geometry_info.sigma=1.0;
10404               if ((flags & XiValue) == 0)
10405                 geometry_info.xi=1.0;
10406             }
10407           if (attribute_flag[1] != 0)
10408             geometry_info.rho=argument_list[1].real_reference;
10409           if (attribute_flag[2] != 0)
10410             geometry_info.sigma=argument_list[2].real_reference;
10411           if (attribute_flag[3] != 0)
10412             geometry_info.xi=argument_list[3].real_reference;
10413           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10414             geometry_info.xi,exception);
10415           break;
10416         }
10417         case 104:  /* UniqueColors */
10418         {
10419           image=UniqueImageColors(image,exception);
10420           break;
10421         }
10422         case 105:  /* AdaptiveResize */
10423         {
10424           if (attribute_flag[0] != 0)
10425             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10426               &geometry,exception);
10427           if (attribute_flag[1] != 0)
10428             geometry.width=argument_list[1].integer_reference;
10429           if (attribute_flag[2] != 0)
10430             geometry.height=argument_list[2].integer_reference;
10431           if (attribute_flag[3] != 0)
10432             image->filter=(FilterType) argument_list[4].integer_reference;
10433           if (attribute_flag[4] != 0)
10434             SetImageArtifact(image,"filter:support",
10435               argument_list[4].string_reference);
10436           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10437             exception);
10438           break;
10439         }
10440         case 106:  /* ClipMask */
10441         {
10442           Image
10443             *mask_image;
10444
10445           if (attribute_flag[0] == 0)
10446             {
10447               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10448                 PackageName);
10449               goto PerlException;
10450             }
10451           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10452             exception);
10453           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10454           mask_image=DestroyImage(mask_image);
10455           break;
10456         }
10457         case 107:  /* LinearStretch */
10458         {
10459            double
10460              black_point,
10461              white_point;
10462
10463            black_point=0.0;
10464            white_point=(double) image->columns*image->rows;
10465            if (attribute_flag[0] != 0)
10466              {
10467                flags=ParseGeometry(argument_list[0].string_reference,
10468                  &geometry_info);
10469                if ((flags & SigmaValue) != 0)
10470                   white_point=geometry_info.sigma;
10471                if ((flags & PercentValue) != 0)
10472                  {
10473                    black_point*=(double) image->columns*image->rows/100.0;
10474                    white_point*=(double) image->columns*image->rows/100.0;
10475                  }
10476                if ((flags & SigmaValue) == 0)
10477                  white_point=(double) image->columns*image->rows-black_point;
10478              }
10479           if (attribute_flag[1] != 0)
10480             black_point=argument_list[1].real_reference;
10481           if (attribute_flag[2] != 0)
10482             white_point=argument_list[2].real_reference;
10483           (void) LinearStretchImage(image,black_point,white_point,exception);
10484           break;
10485         }
10486         case 108:  /* ColorMatrix */
10487         {
10488           AV
10489             *av;
10490
10491           double
10492             *color_matrix;
10493
10494           KernelInfo
10495             *kernel_info;
10496
10497           size_t
10498             order;
10499
10500           if (attribute_flag[0] == 0)
10501             break;
10502           av=(AV *) argument_list[0].array_reference;
10503           order=(size_t) sqrt(av_len(av)+1);
10504           color_matrix=(double *) AcquireQuantumMemory(order,order*
10505             sizeof(*color_matrix));
10506           if (color_matrix == (double *) NULL)
10507             {
10508               ThrowPerlException(exception,ResourceLimitFatalError,
10509                 "MemoryAllocationFailed",PackageName);
10510               goto PerlException;
10511            }
10512           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10513             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10514           for ( ; j < (ssize_t) (order*order); j++)
10515             color_matrix[j]=0.0;
10516           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10517           if (kernel_info == (KernelInfo *) NULL)
10518             break;
10519           kernel_info->width=order;
10520           kernel_info->height=order;
10521           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10522             order*sizeof(*kernel_info->values));
10523           if (kernel_info->values != (MagickRealType *) NULL)
10524             {
10525               for (i=0; i < (ssize_t) (order*order); i++)
10526                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10527               image=ColorMatrixImage(image,kernel_info,exception);
10528             }
10529           kernel_info=DestroyKernelInfo(kernel_info);
10530           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10531           break;
10532         }
10533         case 109:  /* Mask */
10534         {
10535           Image
10536             *mask_image;
10537
10538           if (attribute_flag[0] == 0)
10539             {
10540               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10541                 PackageName);
10542               goto PerlException;
10543             }
10544           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10545             MagickTrue,exception);
10546           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10547           mask_image=DestroyImage(mask_image);
10548           break;
10549         }
10550         case 110:  /* Polaroid */
10551         {
10552           char
10553             *caption;
10554
10555           DrawInfo
10556             *draw_info;
10557
10558           double
10559             angle;
10560
10561           PixelInterpolateMethod
10562             method;
10563
10564           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10565             (DrawInfo *) NULL);
10566           caption=(char *) NULL;
10567           if (attribute_flag[0] != 0)
10568             caption=InterpretImageProperties(info ? info->image_info :
10569               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10570               exception);
10571           angle=0.0;
10572           if (attribute_flag[1] != 0)
10573             angle=argument_list[1].real_reference;
10574           if (attribute_flag[2] != 0)
10575             (void) CloneString(&draw_info->font,
10576               argument_list[2].string_reference);
10577           if (attribute_flag[3] != 0)
10578             (void) QueryColorCompliance(argument_list[3].string_reference,
10579               AllCompliance,&draw_info->stroke,exception);
10580           if (attribute_flag[4] != 0)
10581             (void) QueryColorCompliance(argument_list[4].string_reference,
10582               AllCompliance,&draw_info->fill,exception);
10583           if (attribute_flag[5] != 0)
10584             draw_info->stroke_width=argument_list[5].real_reference;
10585           if (attribute_flag[6] != 0)
10586             draw_info->pointsize=argument_list[6].real_reference;
10587           if (attribute_flag[7] != 0)
10588             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10589           if (attribute_flag[8] != 0)
10590             (void) QueryColorCompliance(argument_list[8].string_reference,
10591               AllCompliance,&image->background_color,exception);
10592           method=UndefinedInterpolatePixel;
10593           if (attribute_flag[9] != 0)
10594             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10595           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10596           draw_info=DestroyDrawInfo(draw_info);
10597           if (caption != (char *) NULL)
10598             caption=DestroyString(caption);
10599           break;
10600         }
10601         case 111:  /* FloodfillPaint */
10602         {
10603           DrawInfo
10604             *draw_info;
10605
10606           MagickBooleanType
10607             invert;
10608
10609           PixelInfo
10610             target;
10611
10612           draw_info=CloneDrawInfo(info ? info->image_info :
10613             (ImageInfo *) NULL,(DrawInfo *) NULL);
10614           if (attribute_flag[0] != 0)
10615             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10616               &geometry,exception);
10617           if (attribute_flag[1] != 0)
10618             geometry.x=argument_list[1].integer_reference;
10619           if (attribute_flag[2] != 0)
10620             geometry.y=argument_list[2].integer_reference;
10621           if (attribute_flag[3] != 0)
10622             (void) QueryColorCompliance(argument_list[3].string_reference,
10623               AllCompliance,&draw_info->fill,exception);
10624           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10625             geometry.x,geometry.y,&target,exception);
10626           if (attribute_flag[4] != 0)
10627             QueryColorCompliance(argument_list[4].string_reference,
10628               AllCompliance,&target,exception);
10629           if (attribute_flag[5] != 0)
10630             image->fuzz=StringToDoubleInterval(
10631               argument_list[5].string_reference,(double) QuantumRange+1.0);
10632           if (attribute_flag[6] != 0)
10633             channel=(ChannelType) argument_list[6].integer_reference;
10634           invert=MagickFalse;
10635           if (attribute_flag[7] != 0)
10636             invert=(MagickBooleanType) argument_list[7].integer_reference;
10637           channel_mask=SetImageChannelMask(image,channel);
10638           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10639             geometry.y,invert,exception);
10640           (void) SetImageChannelMask(image,channel_mask);
10641           draw_info=DestroyDrawInfo(draw_info);
10642           break;
10643         }
10644         case 112:  /* Distort */
10645         {
10646           AV
10647             *av;
10648
10649           double
10650             *coordinates;
10651
10652           DistortMethod
10653             method;
10654
10655           size_t
10656             number_coordinates;
10657
10658           VirtualPixelMethod
10659             virtual_pixel;
10660
10661           if (attribute_flag[0] == 0)
10662             break;
10663           method=UndefinedDistortion;
10664           if (attribute_flag[1] != 0)
10665             method=(DistortMethod) argument_list[1].integer_reference;
10666           av=(AV *) argument_list[0].array_reference;
10667           number_coordinates=(size_t) av_len(av)+1;
10668           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10669             sizeof(*coordinates));
10670           if (coordinates == (double *) NULL)
10671             {
10672               ThrowPerlException(exception,ResourceLimitFatalError,
10673                 "MemoryAllocationFailed",PackageName);
10674               goto PerlException;
10675             }
10676           for (j=0; j < (ssize_t) number_coordinates; j++)
10677             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10678           virtual_pixel=UndefinedVirtualPixelMethod;
10679           if (attribute_flag[2] != 0)
10680             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10681               argument_list[2].integer_reference,exception);
10682           image=DistortImage(image,method,number_coordinates,coordinates,
10683             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10684             exception);
10685           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10686             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10687               exception);
10688           coordinates=(double *) RelinquishMagickMemory(coordinates);
10689           break;
10690         }
10691         case 113:  /* Clut */
10692         {
10693           PixelInterpolateMethod
10694             method;
10695
10696           if (attribute_flag[0] == 0)
10697             {
10698               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10699                 PackageName);
10700               goto PerlException;
10701             }
10702           method=UndefinedInterpolatePixel;
10703           if (attribute_flag[1] != 0)
10704             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10705           if (attribute_flag[2] != 0)
10706             channel=(ChannelType) argument_list[2].integer_reference;
10707           channel_mask=SetImageChannelMask(image,channel);
10708           (void) ClutImage(image,argument_list[0].image_reference,method,
10709             exception);
10710           (void) SetImageChannelMask(image,channel_mask);
10711           break;
10712         }
10713         case 114:  /* LiquidRescale */
10714         {
10715           if (attribute_flag[0] != 0)
10716             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10717               &geometry,exception);
10718           if (attribute_flag[1] != 0)
10719             geometry.width=argument_list[1].integer_reference;
10720           if (attribute_flag[2] != 0)
10721             geometry.height=argument_list[2].integer_reference;
10722           if (attribute_flag[3] == 0)
10723             argument_list[3].real_reference=1.0;
10724           if (attribute_flag[4] == 0)
10725             argument_list[4].real_reference=0.0;
10726           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10727             argument_list[3].real_reference,argument_list[4].real_reference,
10728             exception);
10729           break;
10730         }
10731         case 115:  /* EncipherImage */
10732         {
10733           (void) EncipherImage(image,argument_list[0].string_reference,
10734             exception);
10735           break;
10736         }
10737         case 116:  /* DecipherImage */
10738         {
10739           (void) DecipherImage(image,argument_list[0].string_reference,
10740             exception);
10741           break;
10742         }
10743         case 117:  /* Deskew */
10744         {
10745           geometry_info.rho=QuantumRange/2.0;
10746           if (attribute_flag[0] != 0)
10747             flags=ParseGeometry(argument_list[0].string_reference,
10748               &geometry_info);
10749           if (attribute_flag[1] != 0)
10750             geometry_info.rho=StringToDoubleInterval(
10751               argument_list[1].string_reference,(double) QuantumRange+1.0);
10752           image=DeskewImage(image,geometry_info.rho,exception);
10753           break;
10754         }
10755         case 118:  /* Remap */
10756         {
10757           QuantizeInfo
10758             *quantize_info;
10759
10760           if (attribute_flag[0] == 0)
10761             {
10762               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10763                 PackageName);
10764               goto PerlException;
10765             }
10766           quantize_info=AcquireQuantizeInfo(info->image_info);
10767           if (attribute_flag[1] != 0)
10768             quantize_info->dither_method=(DitherMethod)
10769               argument_list[1].integer_reference;
10770           (void) RemapImages(quantize_info,image,
10771             argument_list[0].image_reference,exception);
10772           quantize_info=DestroyQuantizeInfo(quantize_info);
10773           break;
10774         }
10775         case 119:  /* SparseColor */
10776         {
10777           AV
10778             *av;
10779
10780           double
10781             *coordinates;
10782
10783           SparseColorMethod
10784             method;
10785
10786           size_t
10787             number_coordinates;
10788
10789           VirtualPixelMethod
10790             virtual_pixel;
10791
10792           if (attribute_flag[0] == 0)
10793             break;
10794           method=UndefinedColorInterpolate;
10795           if (attribute_flag[1] != 0)
10796             method=(SparseColorMethod) argument_list[1].integer_reference;
10797           av=(AV *) argument_list[0].array_reference;
10798           number_coordinates=(size_t) av_len(av)+1;
10799           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10800             sizeof(*coordinates));
10801           if (coordinates == (double *) NULL)
10802             {
10803               ThrowPerlException(exception,ResourceLimitFatalError,
10804                 "MemoryAllocationFailed",PackageName);
10805               goto PerlException;
10806             }
10807           for (j=0; j < (ssize_t) number_coordinates; j++)
10808             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10809           virtual_pixel=UndefinedVirtualPixelMethod;
10810           if (attribute_flag[2] != 0)
10811             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10812               argument_list[2].integer_reference,exception);
10813           if (attribute_flag[3] != 0)
10814             channel=(ChannelType) argument_list[3].integer_reference;
10815           channel_mask=SetImageChannelMask(image,channel);
10816           image=SparseColorImage(image,method,number_coordinates,coordinates,
10817             exception);
10818           if (image != (Image *) NULL)
10819             (void) SetImageChannelMask(image,channel_mask);
10820           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10821             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10822               exception);
10823           coordinates=(double *) RelinquishMagickMemory(coordinates);
10824           break;
10825         }
10826         case 120:  /* Function */
10827         {
10828           AV
10829             *av;
10830
10831           double
10832             *parameters;
10833
10834           MagickFunction
10835             function;
10836
10837           size_t
10838             number_parameters;
10839
10840           VirtualPixelMethod
10841             virtual_pixel;
10842
10843           if (attribute_flag[0] == 0)
10844             break;
10845           function=UndefinedFunction;
10846           if (attribute_flag[1] != 0)
10847             function=(MagickFunction) argument_list[1].integer_reference;
10848           av=(AV *) argument_list[0].array_reference;
10849           number_parameters=(size_t) av_len(av)+1;
10850           parameters=(double *) AcquireQuantumMemory(number_parameters,
10851             sizeof(*parameters));
10852           if (parameters == (double *) NULL)
10853             {
10854               ThrowPerlException(exception,ResourceLimitFatalError,
10855                 "MemoryAllocationFailed",PackageName);
10856               goto PerlException;
10857             }
10858           for (j=0; j < (ssize_t) number_parameters; j++)
10859             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10860           virtual_pixel=UndefinedVirtualPixelMethod;
10861           if (attribute_flag[2] != 0)
10862             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10863               argument_list[2].integer_reference,exception);
10864           (void) FunctionImage(image,function,number_parameters,parameters,
10865             exception);
10866           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10867             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10868               exception);
10869           parameters=(double *) RelinquishMagickMemory(parameters);
10870           break;
10871         }
10872         case 121:  /* SelectiveBlur */
10873         {
10874           if (attribute_flag[0] != 0)
10875             {
10876               flags=ParseGeometry(argument_list[0].string_reference,
10877                 &geometry_info);
10878               if ((flags & SigmaValue) == 0)
10879                 geometry_info.sigma=1.0;
10880               if ((flags & PercentValue) != 0)
10881                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10882             }
10883           if (attribute_flag[1] != 0)
10884             geometry_info.rho=argument_list[1].real_reference;
10885           if (attribute_flag[2] != 0)
10886             geometry_info.sigma=argument_list[2].real_reference;
10887           if (attribute_flag[3] != 0)
10888             geometry_info.xi=argument_list[3].integer_reference;;
10889           if (attribute_flag[5] != 0)
10890             channel=(ChannelType) argument_list[5].integer_reference;
10891           channel_mask=SetImageChannelMask(image,channel);
10892           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10893             geometry_info.xi,exception);
10894           if (image != (Image *) NULL)
10895             (void) SetImageChannelMask(image,channel_mask);
10896           break;
10897         }
10898         case 122:  /* HaldClut */
10899         {
10900           if (attribute_flag[0] == 0)
10901             {
10902               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10903                 PackageName);
10904               goto PerlException;
10905             }
10906           if (attribute_flag[1] != 0)
10907             channel=(ChannelType) argument_list[1].integer_reference;
10908           channel_mask=SetImageChannelMask(image,channel);
10909           (void) HaldClutImage(image,argument_list[0].image_reference,
10910             exception);
10911           (void) SetImageChannelMask(image,channel_mask);
10912           break;
10913         }
10914         case 123:  /* BlueShift */
10915         {
10916           if (attribute_flag[0] != 0)
10917             (void) ParseGeometry(argument_list[0].string_reference,
10918               &geometry_info);
10919           image=BlueShiftImage(image,geometry_info.rho,exception);
10920           break;
10921         }
10922         case 124:  /* ForwardFourierTransformImage */
10923         {
10924           image=ForwardFourierTransformImage(image,
10925             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10926             exception);
10927           break;
10928         }
10929         case 125:  /* InverseFourierTransformImage */
10930         {
10931           image=InverseFourierTransformImage(image,image->next,
10932             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10933             exception);
10934           break;
10935         }
10936         case 126:  /* ColorDecisionList */
10937         {
10938           if (attribute_flag[0] == 0)
10939             argument_list[0].string_reference=(char *) NULL;
10940           (void) ColorDecisionListImage(image,
10941             argument_list[0].string_reference,exception);
10942           break;
10943         }
10944         case 127:  /* AutoGamma */
10945         {
10946           if (attribute_flag[0] != 0)
10947             channel=(ChannelType) argument_list[0].integer_reference;
10948           channel_mask=SetImageChannelMask(image,channel);
10949           (void) AutoGammaImage(image,exception);
10950           (void) SetImageChannelMask(image,channel_mask);
10951           break;
10952         }
10953         case 128:  /* AutoLevel */
10954         {
10955           if (attribute_flag[0] != 0)
10956             channel=(ChannelType) argument_list[0].integer_reference;
10957           channel_mask=SetImageChannelMask(image,channel);
10958           (void) AutoLevelImage(image,exception);
10959           (void) SetImageChannelMask(image,channel_mask);
10960           break;
10961         }
10962         case 129:  /* LevelColors */
10963         {
10964           PixelInfo
10965             black_point,
10966             white_point;
10967
10968           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10969             exception);
10970           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10971             exception);
10972           if (attribute_flag[1] != 0)
10973              (void) QueryColorCompliance(
10974                argument_list[1].string_reference,AllCompliance,&black_point,
10975                exception);
10976           if (attribute_flag[2] != 0)
10977              (void) QueryColorCompliance(
10978                argument_list[2].string_reference,AllCompliance,&white_point,
10979                exception);
10980           if (attribute_flag[3] != 0)
10981             channel=(ChannelType) argument_list[3].integer_reference;
10982           channel_mask=SetImageChannelMask(image,channel);
10983           (void) LevelImageColors(image,&black_point,&white_point,
10984             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10985             exception);
10986           (void) SetImageChannelMask(image,channel_mask);
10987           break;
10988         }
10989         case 130:  /* Clamp */
10990         {
10991           if (attribute_flag[0] != 0)
10992             channel=(ChannelType) argument_list[0].integer_reference;
10993           channel_mask=SetImageChannelMask(image,channel);
10994           (void) ClampImage(image,exception);
10995           (void) SetImageChannelMask(image,channel_mask);
10996           break;
10997         }
10998         case 131:  /* BrightnessContrast */
10999         {
11000           double
11001             brightness,
11002             contrast;
11003
11004           brightness=0.0;
11005           contrast=0.0;
11006           if (attribute_flag[0] != 0)
11007             {
11008               flags=ParseGeometry(argument_list[0].string_reference,
11009                 &geometry_info);
11010               brightness=geometry_info.rho;
11011               if ((flags & SigmaValue) == 0)
11012                 contrast=geometry_info.sigma;
11013             }
11014           if (attribute_flag[1] != 0)
11015             brightness=argument_list[1].real_reference;
11016           if (attribute_flag[2] != 0)
11017             contrast=argument_list[2].real_reference;
11018           if (attribute_flag[4] != 0)
11019             channel=(ChannelType) argument_list[4].integer_reference;
11020           channel_mask=SetImageChannelMask(image,channel);
11021           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11022           (void) SetImageChannelMask(image,channel_mask);
11023           break;
11024         }
11025         case 132:  /* Morphology */
11026         {
11027           KernelInfo
11028             *kernel;
11029
11030           MorphologyMethod
11031             method;
11032
11033           ssize_t
11034             iterations;
11035
11036           if (attribute_flag[0] == 0)
11037             break;
11038           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11039           if (kernel == (KernelInfo *) NULL)
11040             break;
11041           if (attribute_flag[1] != 0)
11042             channel=(ChannelType) argument_list[1].integer_reference;
11043           method=UndefinedMorphology;
11044           if (attribute_flag[2] != 0)
11045             method=argument_list[2].integer_reference;
11046           iterations=1;
11047           if (attribute_flag[3] != 0)
11048             iterations=argument_list[3].integer_reference;
11049           channel_mask=SetImageChannelMask(image,channel);
11050           image=MorphologyImage(image,method,iterations,kernel,exception);
11051           if (image != (Image *) NULL)
11052             (void) SetImageChannelMask(image,channel_mask);
11053           kernel=DestroyKernelInfo(kernel);
11054           break;
11055         }
11056         case 133:  /* Mode */
11057         {
11058           if (attribute_flag[0] != 0)
11059             {
11060               flags=ParseGeometry(argument_list[0].string_reference,
11061                 &geometry_info);
11062               if ((flags & SigmaValue) == 0)
11063                 geometry_info.sigma=1.0;
11064             }
11065           if (attribute_flag[1] != 0)
11066             geometry_info.rho=argument_list[1].real_reference;
11067           if (attribute_flag[2] != 0)
11068             geometry_info.sigma=argument_list[2].real_reference;
11069           if (attribute_flag[3] != 0)
11070             channel=(ChannelType) argument_list[3].integer_reference;
11071           channel_mask=SetImageChannelMask(image,channel);
11072           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11073             (size_t) geometry_info.sigma,exception);
11074           if (image != (Image *) NULL)
11075             (void) SetImageChannelMask(image,channel_mask);
11076           break;
11077         }
11078         case 134:  /* Statistic */
11079         {
11080           StatisticType
11081             statistic;
11082
11083           statistic=UndefinedStatistic;
11084           if (attribute_flag[0] != 0)
11085             {
11086               flags=ParseGeometry(argument_list[0].string_reference,
11087                 &geometry_info);
11088               if ((flags & SigmaValue) == 0)
11089                 geometry_info.sigma=1.0;
11090             }
11091           if (attribute_flag[1] != 0)
11092             geometry_info.rho=argument_list[1].real_reference;
11093           if (attribute_flag[2] != 0)
11094             geometry_info.sigma=argument_list[2].real_reference;
11095           if (attribute_flag[3] != 0)
11096             channel=(ChannelType) argument_list[3].integer_reference;
11097           if (attribute_flag[4] != 0)
11098             statistic=(StatisticType) argument_list[4].integer_reference;
11099           channel_mask=SetImageChannelMask(image,channel);
11100           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11101             (size_t) geometry_info.sigma,exception);
11102           if (image != (Image *) NULL)
11103             (void) SetImageChannelMask(image,channel_mask);
11104           break;
11105         }
11106         case 135:  /* Perceptible */
11107         {
11108           double
11109             epsilon;
11110
11111           epsilon=MagickEpsilon;
11112           if (attribute_flag[0] != 0)
11113             epsilon=argument_list[0].real_reference;
11114           if (attribute_flag[1] != 0)
11115             channel=(ChannelType) argument_list[1].integer_reference;
11116           channel_mask=SetImageChannelMask(image,channel);
11117           (void) PerceptibleImage(image,epsilon,exception);
11118           (void) SetImageChannelMask(image,channel_mask);
11119           break;
11120         }
11121         case 136:  /* Poly */
11122         {
11123           AV
11124             *av;
11125
11126           double
11127             *terms;
11128
11129           size_t
11130             number_terms;
11131
11132           if (attribute_flag[0] == 0)
11133             break;
11134           if (attribute_flag[1] != 0)
11135             channel=(ChannelType) argument_list[1].integer_reference;
11136           av=(AV *) argument_list[0].array_reference;
11137           number_terms=(size_t) av_len(av);
11138           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11139           if (terms == (double *) NULL)
11140             {
11141               ThrowPerlException(exception,ResourceLimitFatalError,
11142                 "MemoryAllocationFailed",PackageName);
11143               goto PerlException;
11144             }
11145           for (j=0; j < av_len(av); j++)
11146             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11147           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11148           terms=(double *) RelinquishMagickMemory(terms);
11149           break;
11150         }
11151         case 137:  /* Grayscale */
11152         {
11153           PixelIntensityMethod
11154             method;
11155
11156           method=UndefinedPixelIntensityMethod;
11157           if (attribute_flag[0] != 0)
11158             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11159           (void) GrayscaleImage(image,method,exception);
11160           break;
11161         }
11162         case 138:  /* Canny */
11163         {
11164           if (attribute_flag[0] != 0)
11165             {
11166               flags=ParseGeometry(argument_list[0].string_reference,
11167                 &geometry_info);
11168               if ((flags & SigmaValue) == 0)
11169                 geometry_info.sigma=1.0;
11170               if ((flags & XiValue) == 0)
11171                 geometry_info.xi=0.10;
11172               if ((flags & PsiValue) == 0)
11173                 geometry_info.psi=0.30;
11174               if ((flags & PercentValue) != 0)
11175                 {
11176                   geometry_info.xi/=100.0;
11177                   geometry_info.psi/=100.0;
11178                 }
11179             }
11180           if (attribute_flag[1] != 0)
11181             geometry_info.rho=argument_list[1].real_reference;
11182           if (attribute_flag[2] != 0)
11183             geometry_info.sigma=argument_list[2].real_reference;
11184           if (attribute_flag[3] != 0)
11185             geometry_info.xi=argument_list[3].real_reference;
11186           if (attribute_flag[4] != 0)
11187             geometry_info.psi=argument_list[4].real_reference;
11188           if (attribute_flag[5] != 0)
11189             channel=(ChannelType) argument_list[5].integer_reference;
11190           channel_mask=SetImageChannelMask(image,channel);
11191           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11192             geometry_info.xi,geometry_info.psi,exception);
11193           if (image != (Image *) NULL)
11194             (void) SetImageChannelMask(image,channel_mask);
11195           break;
11196         }
11197         case 139:  /* HoughLine */
11198         {
11199           if (attribute_flag[0] != 0)
11200             {
11201               flags=ParseGeometry(argument_list[0].string_reference,
11202                 &geometry_info);
11203               if ((flags & SigmaValue) == 0)
11204                 geometry_info.sigma=geometry_info.rho;
11205               if ((flags & XiValue) == 0)
11206                 geometry_info.xi=40;
11207             }
11208           if (attribute_flag[1] != 0)
11209             geometry_info.rho=(double) argument_list[1].integer_reference;
11210           if (attribute_flag[2] != 0)
11211             geometry_info.sigma=(double) argument_list[2].integer_reference;
11212           if (attribute_flag[3] != 0)
11213             geometry_info.xi=(double) argument_list[3].integer_reference;
11214           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11215             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11216           break;
11217         }
11218         case 140:  /* MeanShift */
11219         {
11220           if (attribute_flag[0] != 0)
11221             {
11222               flags=ParseGeometry(argument_list[0].string_reference,
11223                 &geometry_info);
11224               if ((flags & SigmaValue) == 0)
11225                 geometry_info.sigma=geometry_info.rho;
11226               if ((flags & XiValue) == 0)
11227                 geometry_info.xi=0.10*QuantumRange;
11228               if ((flags & PercentValue) != 0)
11229                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11230             }
11231           if (attribute_flag[1] != 0)
11232             geometry_info.rho=(double) argument_list[1].integer_reference;
11233           if (attribute_flag[2] != 0)
11234             geometry_info.sigma=(double) argument_list[2].integer_reference;
11235           if (attribute_flag[3] != 0)
11236             geometry_info.xi=(double) argument_list[3].integer_reference;
11237           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11238             geometry_info.sigma,geometry_info.xi,exception);
11239           break;
11240         }
11241         case 141:  /* Kuwahara */
11242         {
11243           if (attribute_flag[0] != 0)
11244             {
11245               flags=ParseGeometry(argument_list[0].string_reference,
11246                 &geometry_info);
11247               if ((flags & SigmaValue) == 0)
11248                 geometry_info.sigma=geometry_info.rho-0.5;
11249             }
11250           if (attribute_flag[1] != 0)
11251             geometry_info.rho=argument_list[1].real_reference;
11252           if (attribute_flag[2] != 0)
11253             geometry_info.sigma=argument_list[2].real_reference;
11254           if (attribute_flag[3] != 0)
11255             channel=(ChannelType) argument_list[3].integer_reference;
11256           channel_mask=SetImageChannelMask(image,channel);
11257           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11258             exception);
11259           if (image != (Image *) NULL)
11260             (void) SetImageChannelMask(image,channel_mask);
11261           break;
11262         }
11263         case 142:  /* ConnectedComponent */
11264         {
11265           size_t
11266             connectivity;
11267
11268           connectivity=4;
11269           if (attribute_flag[0] != 0)
11270             connectivity=argument_list[0].integer_reference;
11271           image=ConnectedComponentsImage(image,connectivity,
11272             (CCObjectInfo **) NULL,exception);
11273           break;
11274         }
11275         case 143:  /* Copy */
11276         {
11277           Image
11278             *source_image;
11279
11280           OffsetInfo
11281             offset;
11282
11283           RectangleInfo
11284             offset_geometry;
11285
11286           source_image=image;
11287           if (attribute_flag[0] != 0)
11288             source_image=argument_list[0].image_reference;
11289           SetGeometry(source_image,&geometry);
11290           if (attribute_flag[1] != 0)
11291             flags=ParseGravityGeometry(source_image,
11292               argument_list[1].string_reference,&geometry,exception);
11293           if (attribute_flag[2] != 0)
11294             geometry.width=argument_list[2].integer_reference;
11295           if (attribute_flag[3] != 0)
11296             geometry.height=argument_list[3].integer_reference;
11297           if (attribute_flag[4] != 0)
11298             geometry.x=argument_list[4].integer_reference;
11299           if (attribute_flag[5] != 0)
11300             geometry.y=argument_list[5].integer_reference;
11301           if (attribute_flag[6] != 0)
11302             image->gravity=(GravityType) argument_list[6].integer_reference;
11303           SetGeometry(image,&offset_geometry);
11304           if (attribute_flag[7] != 0)
11305             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11306               &offset_geometry,exception);
11307           offset.x=offset_geometry.x;
11308           offset.y=offset_geometry.y;
11309           if (attribute_flag[8] != 0)
11310             offset.x=argument_list[8].integer_reference;
11311           if (attribute_flag[9] != 0)
11312             offset.y=argument_list[9].integer_reference;
11313           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11314             exception);
11315           break;
11316         }
11317         case 144:  /* Color */
11318         {
11319           PixelInfo
11320             color;
11321
11322           (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11323           if (attribute_flag[0] != 0)
11324             (void) QueryColorCompliance(argument_list[0].string_reference,
11325               AllCompliance,&color,exception);
11326           (void) SetImageColor(image,&color,exception);
11327           break;
11328         }
11329         case 145:  /* WaveletDenoise */
11330         {
11331           if (attribute_flag[0] != 0)
11332             {
11333               flags=ParseGeometry(argument_list[0].string_reference,
11334                 &geometry_info);
11335               if ((flags & PercentValue) != 0)
11336                 {
11337                   geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11338                   geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11339                 }
11340               if ((flags & SigmaValue) == 0)
11341                 geometry_info.sigma=0.0;
11342             }
11343           if (attribute_flag[1] != 0)
11344             geometry_info.rho=argument_list[1].real_reference;
11345           if (attribute_flag[2] != 0)
11346             geometry_info.sigma=argument_list[2].real_reference;
11347           if (attribute_flag[3] != 0)
11348             channel=(ChannelType) argument_list[3].integer_reference;
11349           channel_mask=SetImageChannelMask(image,channel);
11350           image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11351             exception);
11352           if (image != (Image *) NULL)
11353             (void) SetImageChannelMask(image,channel_mask);
11354           break;
11355         }
11356       }
11357       if (next != (Image *) NULL)
11358         (void) CatchImageException(next);
11359       if (region_image != (Image *) NULL)
11360         {
11361           /*
11362             Composite region.
11363           */
11364           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11365             region_info.x,region_info.y,exception);
11366           (void) status;
11367           (void) CatchImageException(region_image);
11368           image=DestroyImage(image);
11369           image=region_image;
11370         }
11371       if (image != (Image *) NULL)
11372         {
11373           number_images++;
11374           if (next && (next != image))
11375             {
11376               image->next=next->next;
11377               if (image->next != (Image *) NULL)
11378                 image->next->previous=image;
11379               DeleteImageFromRegistry(*pv,next);
11380             }
11381           sv_setiv(*pv,PTR2IV(image));
11382           next=image;
11383         }
11384       if (*pv)
11385         pv++;
11386     }
11387
11388   PerlException:
11389     if (reference_vector)
11390       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11391     InheritPerlException(exception,perl_exception);
11392     exception=DestroyExceptionInfo(exception);
11393     sv_setiv(perl_exception,(IV) number_images);
11394     SvPOK_on(perl_exception);
11395     ST(0)=sv_2mortal(perl_exception);
11396     XSRETURN(1);
11397   }
11398 \f
11399 #
11400 ###############################################################################
11401 #                                                                             #
11402 #                                                                             #
11403 #                                                                             #
11404 #   M o n t a g e                                                             #
11405 #                                                                             #
11406 #                                                                             #
11407 #                                                                             #
11408 ###############################################################################
11409 #
11410 #
11411 void
11412 Montage(ref,...)
11413   Image::Magick ref=NO_INIT
11414   ALIAS:
11415     MontageImage  = 1
11416     montage       = 2
11417     montageimage  = 3
11418   PPCODE:
11419   {
11420     AV
11421       *av;
11422
11423     char
11424       *attribute;
11425
11426     ExceptionInfo
11427       *exception;
11428
11429     HV
11430       *hv;
11431
11432     Image
11433       *image,
11434       *next;
11435
11436     PixelInfo
11437       transparent_color;
11438
11439     MontageInfo
11440       *montage_info;
11441
11442     register ssize_t
11443       i;
11444
11445     ssize_t
11446       sp;
11447
11448     struct PackageInfo
11449       *info;
11450
11451     SV
11452       *av_reference,
11453       *perl_exception,
11454       *reference,
11455       *rv,
11456       *sv;
11457
11458     PERL_UNUSED_VAR(ref);
11459     PERL_UNUSED_VAR(ix);
11460     exception=AcquireExceptionInfo();
11461     perl_exception=newSVpv("",0);
11462     sv=NULL;
11463     attribute=NULL;
11464     if (sv_isobject(ST(0)) == 0)
11465       {
11466         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11467           PackageName);
11468         goto PerlException;
11469       }
11470     reference=SvRV(ST(0));
11471     hv=SvSTASH(reference);
11472     av=newAV();
11473     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11474     SvREFCNT_dec(av);
11475     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11476     if (image == (Image *) NULL)
11477       {
11478         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11479           PackageName);
11480         goto PerlException;
11481       }
11482     /*
11483       Get options.
11484     */
11485     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11486     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11487     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11488       exception);
11489     for (i=2; i < items; i+=2)
11490     {
11491       attribute=(char *) SvPV(ST(i-1),na);
11492       switch (*attribute)
11493       {
11494         case 'B':
11495         case 'b':
11496         {
11497           if (LocaleCompare(attribute,"background") == 0)
11498             {
11499               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11500                 &montage_info->background_color,exception);
11501               for (next=image; next; next=next->next)
11502                 next->background_color=montage_info->background_color;
11503               break;
11504             }
11505           if (LocaleCompare(attribute,"border") == 0)
11506             {
11507               montage_info->border_width=SvIV(ST(i));
11508               break;
11509             }
11510           if (LocaleCompare(attribute,"bordercolor") == 0)
11511             {
11512               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11513                 &montage_info->border_color,exception);
11514               for (next=image; next; next=next->next)
11515                 next->border_color=montage_info->border_color;
11516               break;
11517             }
11518           if (LocaleCompare(attribute,"borderwidth") == 0)
11519             {
11520               montage_info->border_width=SvIV(ST(i));
11521               break;
11522             }
11523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11524             attribute);
11525           break;
11526         }
11527         case 'C':
11528         case 'c':
11529         {
11530           if (LocaleCompare(attribute,"compose") == 0)
11531             {
11532               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11533                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11534               if (sp < 0)
11535                 {
11536                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11537                     SvPV(ST(i),na));
11538                   break;
11539                 }
11540               for (next=image; next; next=next->next)
11541                 next->compose=(CompositeOperator) sp;
11542               break;
11543             }
11544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11545             attribute);
11546           break;
11547         }
11548         case 'F':
11549         case 'f':
11550         {
11551           if (LocaleCompare(attribute,"fill") == 0)
11552             {
11553               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11554                 &montage_info->fill,exception);
11555               break;
11556             }
11557           if (LocaleCompare(attribute,"font") == 0)
11558             {
11559               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11560               break;
11561             }
11562           if (LocaleCompare(attribute,"frame") == 0)
11563             {
11564               char
11565                 *p;
11566
11567               p=SvPV(ST(i),na);
11568               if (IsGeometry(p) == MagickFalse)
11569                 {
11570                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11571                     p);
11572                   break;
11573                 }
11574               (void) CloneString(&montage_info->frame,p);
11575               if (*p == '\0')
11576                 montage_info->frame=(char *) NULL;
11577               break;
11578             }
11579           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11580             attribute);
11581           break;
11582         }
11583         case 'G':
11584         case 'g':
11585         {
11586           if (LocaleCompare(attribute,"geometry") == 0)
11587             {
11588               char
11589                 *p;
11590
11591               p=SvPV(ST(i),na);
11592               if (IsGeometry(p) == MagickFalse)
11593                 {
11594                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11595                     p);
11596                   break;
11597                 }
11598              (void) CloneString(&montage_info->geometry,p);
11599              if (*p == '\0')
11600                montage_info->geometry=(char *) NULL;
11601              break;
11602            }
11603          if (LocaleCompare(attribute,"gravity") == 0)
11604            {
11605              ssize_t
11606                in;
11607
11608              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11609                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11610              if (in < 0)
11611                {
11612                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11613                    SvPV(ST(i),na));
11614                  return;
11615                }
11616              montage_info->gravity=(GravityType) in;
11617              for (next=image; next; next=next->next)
11618                next->gravity=(GravityType) in;
11619              break;
11620            }
11621           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11622             attribute);
11623           break;
11624         }
11625         case 'L':
11626         case 'l':
11627         {
11628           if (LocaleCompare(attribute,"label") == 0)
11629             {
11630               for (next=image; next; next=next->next)
11631                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11632                   info ? info->image_info : (ImageInfo *) NULL,next,
11633                   SvPV(ST(i),na),exception),exception);
11634               break;
11635             }
11636           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11637             attribute);
11638           break;
11639         }
11640         case 'M':
11641         case 'm':
11642         {
11643           if (LocaleCompare(attribute,"mattecolor") == 0)
11644             {
11645               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11646                 &montage_info->alpha_color,exception);
11647               for (next=image; next; next=next->next)
11648                 next->alpha_color=montage_info->alpha_color;
11649               break;
11650             }
11651           if (LocaleCompare(attribute,"mode") == 0)
11652             {
11653               ssize_t
11654                 in;
11655
11656               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11657                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11658               switch (in)
11659               {
11660                 default:
11661                 {
11662                   ThrowPerlException(exception,OptionError,
11663                     "UnrecognizedModeType",SvPV(ST(i),na));
11664                   break;
11665                 }
11666                 case FrameMode:
11667                 {
11668                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11669                   montage_info->shadow=MagickTrue;
11670                   break;
11671                 }
11672                 case UnframeMode:
11673                 {
11674                   montage_info->frame=(char *) NULL;
11675                   montage_info->shadow=MagickFalse;
11676                   montage_info->border_width=0;
11677                   break;
11678                 }
11679                 case ConcatenateMode:
11680                 {
11681                   montage_info->frame=(char *) NULL;
11682                   montage_info->shadow=MagickFalse;
11683                   (void) CloneString(&montage_info->geometry,"+0+0");
11684                   montage_info->border_width=0;
11685                 }
11686               }
11687               break;
11688             }
11689           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11690             attribute);
11691           break;
11692         }
11693         case 'P':
11694         case 'p':
11695         {
11696           if (LocaleCompare(attribute,"pointsize") == 0)
11697             {
11698               montage_info->pointsize=SvIV(ST(i));
11699               break;
11700             }
11701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11702             attribute);
11703           break;
11704         }
11705         case 'S':
11706         case 's':
11707         {
11708           if (LocaleCompare(attribute,"shadow") == 0)
11709             {
11710               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11711                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11712               if (sp < 0)
11713                 {
11714                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11715                     SvPV(ST(i),na));
11716                   break;
11717                 }
11718              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11719              break;
11720             }
11721           if (LocaleCompare(attribute,"stroke") == 0)
11722             {
11723               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11724                 &montage_info->stroke,exception);
11725               break;
11726             }
11727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11728             attribute);
11729           break;
11730         }
11731         case 'T':
11732         case 't':
11733         {
11734           if (LocaleCompare(attribute,"texture") == 0)
11735             {
11736               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11737               break;
11738             }
11739           if (LocaleCompare(attribute,"tile") == 0)
11740             {
11741               char *p=SvPV(ST(i),na);
11742               if (IsGeometry(p) == MagickFalse)
11743                 {
11744                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11745                     p);
11746                   break;
11747                 }
11748               (void) CloneString(&montage_info->tile,p);
11749               if (*p == '\0')
11750                 montage_info->tile=(char *) NULL;
11751               break;
11752             }
11753           if (LocaleCompare(attribute,"title") == 0)
11754             {
11755               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11756               break;
11757             }
11758           if (LocaleCompare(attribute,"transparent") == 0)
11759             {
11760               PixelInfo
11761                 transparent_color;
11762
11763               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11764                 &transparent_color,exception);
11765               for (next=image; next; next=next->next)
11766                 (void) TransparentPaintImage(next,&transparent_color,
11767                   TransparentAlpha,MagickFalse,exception);
11768               break;
11769             }
11770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11771             attribute);
11772           break;
11773         }
11774         default:
11775         {
11776           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11777             attribute);
11778           break;
11779         }
11780       }
11781     }
11782     image=MontageImageList(info->image_info,montage_info,image,exception);
11783     montage_info=DestroyMontageInfo(montage_info);
11784     if (image == (Image *) NULL)
11785       goto PerlException;
11786     if (transparent_color.alpha != TransparentAlpha)
11787       for (next=image; next; next=next->next)
11788         (void) TransparentPaintImage(next,&transparent_color,
11789           TransparentAlpha,MagickFalse,exception);
11790     for (  ; image; image=image->next)
11791     {
11792       AddImageToRegistry(sv,image);
11793       rv=newRV(sv);
11794       av_push(av,sv_bless(rv,hv));
11795       SvREFCNT_dec(sv);
11796     }
11797     exception=DestroyExceptionInfo(exception);
11798     ST(0)=av_reference;
11799     SvREFCNT_dec(perl_exception);
11800     XSRETURN(1);
11801
11802   PerlException:
11803     InheritPerlException(exception,perl_exception);
11804     exception=DestroyExceptionInfo(exception);
11805     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11806     SvPOK_on(perl_exception);
11807     ST(0)=sv_2mortal(perl_exception);
11808     XSRETURN(1);
11809   }
11810 \f
11811 #
11812 ###############################################################################
11813 #                                                                             #
11814 #                                                                             #
11815 #                                                                             #
11816 #   M o r p h                                                                 #
11817 #                                                                             #
11818 #                                                                             #
11819 #                                                                             #
11820 ###############################################################################
11821 #
11822 #
11823 void
11824 Morph(ref,...)
11825   Image::Magick ref=NO_INIT
11826   ALIAS:
11827     MorphImage  = 1
11828     morph       = 2
11829     morphimage  = 3
11830   PPCODE:
11831   {
11832     AV
11833       *av;
11834
11835     char
11836       *attribute;
11837
11838     ExceptionInfo
11839       *exception;
11840
11841     HV
11842       *hv;
11843
11844     Image
11845       *image;
11846
11847     register ssize_t
11848       i;
11849
11850     ssize_t
11851       number_frames;
11852
11853     struct PackageInfo
11854       *info;
11855
11856     SV
11857       *av_reference,
11858       *perl_exception,
11859       *reference,
11860       *rv,
11861       *sv;
11862
11863     PERL_UNUSED_VAR(ref);
11864     PERL_UNUSED_VAR(ix);
11865     exception=AcquireExceptionInfo();
11866     perl_exception=newSVpv("",0);
11867     sv=NULL;
11868     av=NULL;
11869     attribute=NULL;
11870     if (sv_isobject(ST(0)) == 0)
11871       {
11872         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11873           PackageName);
11874         goto PerlException;
11875       }
11876     reference=SvRV(ST(0));
11877     hv=SvSTASH(reference);
11878     av=newAV();
11879     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11880     SvREFCNT_dec(av);
11881     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11882     if (image == (Image *) NULL)
11883       {
11884         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11885           PackageName);
11886         goto PerlException;
11887       }
11888     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11889     /*
11890       Get attribute.
11891     */
11892     number_frames=30;
11893     for (i=2; i < items; i+=2)
11894     {
11895       attribute=(char *) SvPV(ST(i-1),na);
11896       switch (*attribute)
11897       {
11898         case 'F':
11899         case 'f':
11900         {
11901           if (LocaleCompare(attribute,"frames") == 0)
11902             {
11903               number_frames=SvIV(ST(i));
11904               break;
11905             }
11906           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11907             attribute);
11908           break;
11909         }
11910         default:
11911         {
11912           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11913             attribute);
11914           break;
11915         }
11916       }
11917     }
11918     image=MorphImages(image,number_frames,exception);
11919     if (image == (Image *) NULL)
11920       goto PerlException;
11921     for ( ; image; image=image->next)
11922     {
11923       AddImageToRegistry(sv,image);
11924       rv=newRV(sv);
11925       av_push(av,sv_bless(rv,hv));
11926       SvREFCNT_dec(sv);
11927     }
11928     exception=DestroyExceptionInfo(exception);
11929     ST(0)=av_reference;
11930     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11931     XSRETURN(1);
11932
11933   PerlException:
11934     InheritPerlException(exception,perl_exception);
11935     exception=DestroyExceptionInfo(exception);
11936     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11937     SvPOK_on(perl_exception);
11938     ST(0)=sv_2mortal(perl_exception);
11939     XSRETURN(1);
11940   }
11941 \f
11942 #
11943 ###############################################################################
11944 #                                                                             #
11945 #                                                                             #
11946 #                                                                             #
11947 #   M o s a i c                                                               #
11948 #                                                                             #
11949 #                                                                             #
11950 #                                                                             #
11951 ###############################################################################
11952 #
11953 #
11954 void
11955 Mosaic(ref)
11956   Image::Magick ref=NO_INIT
11957   ALIAS:
11958     MosaicImage   = 1
11959     mosaic        = 2
11960     mosaicimage   = 3
11961   PPCODE:
11962   {
11963     AV
11964       *av;
11965
11966     ExceptionInfo
11967       *exception;
11968
11969     HV
11970       *hv;
11971
11972     Image
11973       *image;
11974
11975     struct PackageInfo
11976       *info;
11977
11978     SV
11979       *perl_exception,
11980       *reference,
11981       *rv,
11982       *sv;
11983
11984     PERL_UNUSED_VAR(ref);
11985     PERL_UNUSED_VAR(ix);
11986     exception=AcquireExceptionInfo();
11987     perl_exception=newSVpv("",0);
11988     sv=NULL;
11989     if (sv_isobject(ST(0)) == 0)
11990       {
11991         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11992           PackageName);
11993         goto PerlException;
11994       }
11995     reference=SvRV(ST(0));
11996     hv=SvSTASH(reference);
11997     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11998     if (image == (Image *) NULL)
11999       {
12000         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12001           PackageName);
12002         goto PerlException;
12003       }
12004     image=MergeImageLayers(image,MosaicLayer,exception);
12005     /*
12006       Create blessed Perl array for the returned image.
12007     */
12008     av=newAV();
12009     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12010     SvREFCNT_dec(av);
12011     AddImageToRegistry(sv,image);
12012     rv=newRV(sv);
12013     av_push(av,sv_bless(rv,hv));
12014     SvREFCNT_dec(sv);
12015     (void) CopyMagickString(info->image_info->filename,image->filename,
12016       MagickPathExtent);
12017     SetImageInfo(info->image_info,0,exception);
12018     exception=DestroyExceptionInfo(exception);
12019     SvREFCNT_dec(perl_exception);
12020     XSRETURN(1);
12021
12022   PerlException:
12023     InheritPerlException(exception,perl_exception);
12024     exception=DestroyExceptionInfo(exception);
12025     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12026     SvPOK_on(perl_exception);  /* return messages in string context */
12027     ST(0)=sv_2mortal(perl_exception);
12028     XSRETURN(1);
12029   }
12030 \f
12031 #
12032 ###############################################################################
12033 #                                                                             #
12034 #                                                                             #
12035 #                                                                             #
12036 #   P i n g                                                                   #
12037 #                                                                             #
12038 #                                                                             #
12039 #                                                                             #
12040 ###############################################################################
12041 #
12042 #
12043 void
12044 Ping(ref,...)
12045   Image::Magick ref=NO_INIT
12046   ALIAS:
12047     PingImage  = 1
12048     ping       = 2
12049     pingimage  = 3
12050   PPCODE:
12051   {
12052     AV
12053       *av;
12054
12055     char
12056       **keep,
12057       **list;
12058
12059     ExceptionInfo
12060       *exception;
12061
12062     Image
12063       *image,
12064       *next;
12065
12066     int
12067       n;
12068
12069     MagickBooleanType
12070       status;
12071
12072     register char
12073       **p;
12074
12075     register ssize_t
12076       i;
12077
12078     ssize_t
12079       ac;
12080
12081     STRLEN
12082       *length;
12083
12084     struct PackageInfo
12085       *info,
12086       *package_info;
12087
12088     SV
12089       *perl_exception,
12090       *reference;
12091
12092     size_t
12093       count;
12094
12095     PERL_UNUSED_VAR(ref);
12096     PERL_UNUSED_VAR(ix);
12097     exception=AcquireExceptionInfo();
12098     perl_exception=newSVpv("",0);
12099     package_info=(struct PackageInfo *) NULL;
12100     ac=(items < 2) ? 1 : items-1;
12101     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12102     keep=list;
12103     length=(STRLEN *) NULL;
12104     if (list == (char **) NULL)
12105       {
12106         ThrowPerlException(exception,ResourceLimitError,
12107           "MemoryAllocationFailed",PackageName);
12108         goto PerlException;
12109       }
12110     keep=list;
12111     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12112     if (length == (STRLEN *) NULL)
12113       {
12114         ThrowPerlException(exception,ResourceLimitError,
12115           "MemoryAllocationFailed",PackageName);
12116         goto PerlException;
12117       }
12118     if (sv_isobject(ST(0)) == 0)
12119       {
12120         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12121           PackageName);
12122         goto PerlException;
12123       }
12124     reference=SvRV(ST(0));
12125     if (SvTYPE(reference) != SVt_PVAV)
12126       {
12127         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12128           PackageName);
12129         goto PerlException;
12130       }
12131     av=(AV *) reference;
12132     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12133       exception);
12134     package_info=ClonePackageInfo(info,exception);
12135     n=1;
12136     if (items <= 1)
12137       *list=(char *) (*package_info->image_info->filename ?
12138         package_info->image_info->filename : "XC:black");
12139     else
12140       for (n=0, i=0; i < ac; i++)
12141       {
12142         list[n]=(char *) SvPV(ST(i+1),length[n]);
12143         if ((items >= 3) && strEQcase(list[n],"blob"))
12144           {
12145             void
12146               *blob;
12147
12148             i++;
12149             blob=(void *) (SvPV(ST(i+1),length[n]));
12150             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12151           }
12152         if ((items >= 3) && strEQcase(list[n],"filename"))
12153           continue;
12154         if ((items >= 3) && strEQcase(list[n],"file"))
12155           {
12156             FILE
12157               *file;
12158
12159             PerlIO
12160               *io_info;
12161
12162             i++;
12163             io_info=IoIFP(sv_2io(ST(i+1)));
12164             if (io_info == (PerlIO *) NULL)
12165               {
12166                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12167                   PackageName);
12168                 continue;
12169               }
12170             file=PerlIO_findFILE(io_info);
12171             if (file == (FILE *) NULL)
12172               {
12173                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12174                   PackageName);
12175                 continue;
12176               }
12177             SetImageInfoFile(package_info->image_info,file);
12178           }
12179         if ((items >= 3) && strEQcase(list[n],"magick"))
12180           continue;
12181         n++;
12182       }
12183     list[n]=(char *) NULL;
12184     keep=list;
12185     status=ExpandFilenames(&n,&list);
12186     if (status == MagickFalse)
12187       {
12188         ThrowPerlException(exception,ResourceLimitError,
12189           "MemoryAllocationFailed",PackageName);
12190         goto PerlException;
12191       }
12192     count=0;
12193     for (i=0; i < n; i++)
12194     {
12195       (void) CopyMagickString(package_info->image_info->filename,list[i],
12196         MagickPathExtent);
12197       image=PingImage(package_info->image_info,exception);
12198       if (image == (Image *) NULL)
12199         break;
12200       if ((package_info->image_info->file != (FILE *) NULL) ||
12201           (package_info->image_info->blob != (void *) NULL))
12202         DisassociateImageStream(image);
12203       count+=GetImageListLength(image);
12204       EXTEND(sp,4*count);
12205       for (next=image; next; next=next->next)
12206       {
12207         PUSHs(sv_2mortal(newSViv(next->columns)));
12208         PUSHs(sv_2mortal(newSViv(next->rows)));
12209         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12210         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12211       }
12212       image=DestroyImageList(image);
12213     }
12214     /*
12215       Free resources.
12216     */
12217     for (i=0; i < n; i++)
12218       if (list[i] != (char *) NULL)
12219         for (p=keep; list[i] != *p++; )
12220           if (*p == NULL)
12221             {
12222               list[i]=(char *) RelinquishMagickMemory(list[i]);
12223               break;
12224             }
12225
12226   PerlException:
12227     if (package_info != (struct PackageInfo *) NULL)
12228       DestroyPackageInfo(package_info);
12229     if (list && (list != keep))
12230       list=(char **) RelinquishMagickMemory(list);
12231     if (keep)
12232       keep=(char **) RelinquishMagickMemory(keep);
12233     if (length)
12234       length=(STRLEN *) RelinquishMagickMemory(length);
12235     InheritPerlException(exception,perl_exception);
12236     exception=DestroyExceptionInfo(exception);
12237     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12238   }
12239 \f
12240 #
12241 ###############################################################################
12242 #                                                                             #
12243 #                                                                             #
12244 #                                                                             #
12245 #   P r e v i e w                                                             #
12246 #                                                                             #
12247 #                                                                             #
12248 #                                                                             #
12249 ###############################################################################
12250 #
12251 #
12252 void
12253 Preview(ref,...)
12254   Image::Magick ref=NO_INIT
12255   ALIAS:
12256     PreviewImage = 1
12257     preview      = 2
12258     previewimage = 3
12259   PPCODE:
12260   {
12261     AV
12262       *av;
12263
12264     ExceptionInfo
12265       *exception;
12266
12267     HV
12268       *hv;
12269
12270     Image
12271       *image,
12272       *preview_image;
12273
12274     PreviewType
12275       preview_type;
12276
12277     struct PackageInfo
12278       *info;
12279
12280     SV
12281       *av_reference,
12282       *perl_exception,
12283       *reference,
12284       *rv,
12285       *sv;
12286
12287     PERL_UNUSED_VAR(ref);
12288     PERL_UNUSED_VAR(ix);
12289     exception=AcquireExceptionInfo();
12290     perl_exception=newSVpv("",0);
12291     sv=NULL;
12292     av=NULL;
12293     if (sv_isobject(ST(0)) == 0)
12294       {
12295         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12296           PackageName);
12297         goto PerlException;
12298       }
12299     reference=SvRV(ST(0));
12300     hv=SvSTASH(reference);
12301     av=newAV();
12302     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12303     SvREFCNT_dec(av);
12304     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12305     if (image == (Image *) NULL)
12306       {
12307         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12308           PackageName);
12309         goto PerlException;
12310       }
12311     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12312     preview_type=GammaPreview;
12313     if (items > 1)
12314       preview_type=(PreviewType)
12315         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12316     for ( ; image; image=image->next)
12317     {
12318       preview_image=PreviewImage(image,preview_type,exception);
12319       if (preview_image == (Image *) NULL)
12320         goto PerlException;
12321       AddImageToRegistry(sv,preview_image);
12322       rv=newRV(sv);
12323       av_push(av,sv_bless(rv,hv));
12324       SvREFCNT_dec(sv);
12325     }
12326     exception=DestroyExceptionInfo(exception);
12327     ST(0)=av_reference;
12328     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12329     XSRETURN(1);
12330
12331   PerlException:
12332     InheritPerlException(exception,perl_exception);
12333     exception=DestroyExceptionInfo(exception);
12334     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12335     SvPOK_on(perl_exception);
12336     ST(0)=sv_2mortal(perl_exception);
12337     XSRETURN(1);
12338   }
12339 \f
12340 #
12341 ###############################################################################
12342 #                                                                             #
12343 #                                                                             #
12344 #                                                                             #
12345 #   Q u e r y C o l o r                                                       #
12346 #                                                                             #
12347 #                                                                             #
12348 #                                                                             #
12349 ###############################################################################
12350 #
12351 #
12352 void
12353 QueryColor(ref,...)
12354   Image::Magick ref=NO_INIT
12355   ALIAS:
12356     querycolor = 1
12357   PPCODE:
12358   {
12359     char
12360       *name;
12361
12362     ExceptionInfo
12363       *exception;
12364
12365     PixelInfo
12366       color;
12367
12368     register ssize_t
12369       i;
12370
12371     SV
12372       *perl_exception;
12373
12374     PERL_UNUSED_VAR(ref);
12375     PERL_UNUSED_VAR(ix);
12376     exception=AcquireExceptionInfo();
12377     perl_exception=newSVpv("",0);
12378     if (items == 1)
12379       {
12380         const ColorInfo
12381           **colorlist;
12382
12383         size_t
12384           colors;
12385
12386         colorlist=GetColorInfoList("*",&colors,exception);
12387         EXTEND(sp,colors);
12388         for (i=0; i < (ssize_t) colors; i++)
12389         {
12390           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12391         }
12392         colorlist=(const ColorInfo **)
12393           RelinquishMagickMemory((ColorInfo **) colorlist);
12394         goto PerlException;
12395       }
12396     EXTEND(sp,5*items);
12397     for (i=1; i < items; i++)
12398     {
12399       name=(char *) SvPV(ST(i),na);
12400       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12401         {
12402           PUSHs(&sv_undef);
12403           continue;
12404         }
12405       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12406       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12407       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12408       if (color.colorspace == CMYKColorspace)
12409         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12410       if (color.alpha_trait != UndefinedPixelTrait)
12411         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12412     }
12413
12414   PerlException:
12415     InheritPerlException(exception,perl_exception);
12416     exception=DestroyExceptionInfo(exception);
12417     SvREFCNT_dec(perl_exception);
12418   }
12419 \f
12420 #
12421 ###############################################################################
12422 #                                                                             #
12423 #                                                                             #
12424 #                                                                             #
12425 #   Q u e r y C o l o r N a m e                                               #
12426 #                                                                             #
12427 #                                                                             #
12428 #                                                                             #
12429 ###############################################################################
12430 #
12431 #
12432 void
12433 QueryColorname(ref,...)
12434   Image::Magick ref=NO_INIT
12435   ALIAS:
12436     querycolorname = 1
12437   PPCODE:
12438   {
12439     AV
12440       *av;
12441
12442     char
12443       message[MagickPathExtent];
12444
12445     ExceptionInfo
12446       *exception;
12447
12448     Image
12449       *image;
12450
12451     PixelInfo
12452       target_color;
12453
12454     register ssize_t
12455       i;
12456
12457     struct PackageInfo
12458       *info;
12459
12460     SV
12461       *perl_exception,
12462       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12463
12464     PERL_UNUSED_VAR(ref);
12465     PERL_UNUSED_VAR(ix);
12466     exception=AcquireExceptionInfo();
12467     perl_exception=newSVpv("",0);
12468     reference=SvRV(ST(0));
12469     av=(AV *) reference;
12470     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12471       exception);
12472     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12473     if (image == (Image *) NULL)
12474       {
12475         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12476           PackageName);
12477         goto PerlException;
12478       }
12479     EXTEND(sp,items);
12480     for (i=1; i < items; i++)
12481     {
12482       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12483         exception);
12484       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12485         exception);
12486       PUSHs(sv_2mortal(newSVpv(message,0)));
12487     }
12488
12489   PerlException:
12490     InheritPerlException(exception,perl_exception);
12491     exception=DestroyExceptionInfo(exception);
12492     SvREFCNT_dec(perl_exception);
12493   }
12494 \f
12495 #
12496 ###############################################################################
12497 #                                                                             #
12498 #                                                                             #
12499 #                                                                             #
12500 #   Q u e r y F o n t                                                         #
12501 #                                                                             #
12502 #                                                                             #
12503 #                                                                             #
12504 ###############################################################################
12505 #
12506 #
12507 void
12508 QueryFont(ref,...)
12509   Image::Magick ref=NO_INIT
12510   ALIAS:
12511     queryfont = 1
12512   PPCODE:
12513   {
12514     char
12515       *name,
12516       message[MagickPathExtent];
12517
12518     ExceptionInfo
12519       *exception;
12520
12521     register ssize_t
12522       i;
12523
12524     SV
12525       *perl_exception;
12526
12527     volatile const TypeInfo
12528       *type_info;
12529
12530     PERL_UNUSED_VAR(ref);
12531     PERL_UNUSED_VAR(ix);
12532     exception=AcquireExceptionInfo();
12533     perl_exception=newSVpv("",0);
12534     if (items == 1)
12535       {
12536         const TypeInfo
12537           **typelist;
12538
12539         size_t
12540           types;
12541
12542         typelist=GetTypeInfoList("*",&types,exception);
12543         EXTEND(sp,types);
12544         for (i=0; i < (ssize_t) types; i++)
12545         {
12546           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12547         }
12548         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12549           typelist);
12550         goto PerlException;
12551       }
12552     EXTEND(sp,10*items);
12553     for (i=1; i < items; i++)
12554     {
12555       name=(char *) SvPV(ST(i),na);
12556       type_info=GetTypeInfo(name,exception);
12557       if (type_info == (TypeInfo *) NULL)
12558         {
12559           PUSHs(&sv_undef);
12560           continue;
12561         }
12562       if (type_info->name == (char *) NULL)
12563         PUSHs(&sv_undef);
12564       else
12565         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12566       if (type_info->description == (char *) NULL)
12567         PUSHs(&sv_undef);
12568       else
12569         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12570       if (type_info->family == (char *) NULL)
12571         PUSHs(&sv_undef);
12572       else
12573         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12574       if (type_info->style == UndefinedStyle)
12575         PUSHs(&sv_undef);
12576       else
12577         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12578           type_info->style),0)));
12579       if (type_info->stretch == UndefinedStretch)
12580         PUSHs(&sv_undef);
12581       else
12582         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12583           type_info->stretch),0)));
12584       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12585         type_info->weight);
12586       PUSHs(sv_2mortal(newSVpv(message,0)));
12587       if (type_info->encoding == (char *) NULL)
12588         PUSHs(&sv_undef);
12589       else
12590         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12591       if (type_info->foundry == (char *) NULL)
12592         PUSHs(&sv_undef);
12593       else
12594         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12595       if (type_info->format == (char *) NULL)
12596         PUSHs(&sv_undef);
12597       else
12598         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12599       if (type_info->metrics == (char *) NULL)
12600         PUSHs(&sv_undef);
12601       else
12602         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12603       if (type_info->glyphs == (char *) NULL)
12604         PUSHs(&sv_undef);
12605       else
12606         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12607     }
12608
12609   PerlException:
12610     InheritPerlException(exception,perl_exception);
12611     exception=DestroyExceptionInfo(exception);
12612     SvREFCNT_dec(perl_exception);
12613   }
12614 \f
12615 #
12616 ###############################################################################
12617 #                                                                             #
12618 #                                                                             #
12619 #                                                                             #
12620 #   Q u e r y F o n t M e t r i c s                                           #
12621 #                                                                             #
12622 #                                                                             #
12623 #                                                                             #
12624 ###############################################################################
12625 #
12626 #
12627 void
12628 QueryFontMetrics(ref,...)
12629   Image::Magick ref=NO_INIT
12630   ALIAS:
12631     queryfontmetrics = 1
12632   PPCODE:
12633   {
12634     AffineMatrix
12635       affine,
12636       current;
12637
12638     AV
12639       *av;
12640
12641     char
12642       *attribute;
12643
12644     double
12645       x,
12646       y;
12647
12648     DrawInfo
12649       *draw_info;
12650
12651     ExceptionInfo
12652       *exception;
12653
12654     GeometryInfo
12655       geometry_info;
12656
12657     Image
12658       *image;
12659
12660     MagickBooleanType
12661       status;
12662
12663     MagickStatusType
12664       flags;
12665
12666     register ssize_t
12667       i;
12668
12669     ssize_t
12670       type;
12671
12672     struct PackageInfo
12673       *info,
12674       *package_info;
12675
12676     SV
12677       *perl_exception,
12678       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12679
12680     TypeMetric
12681       metrics;
12682
12683     PERL_UNUSED_VAR(ref);
12684     PERL_UNUSED_VAR(ix);
12685     exception=AcquireExceptionInfo();
12686     package_info=(struct PackageInfo *) NULL;
12687     perl_exception=newSVpv("",0);
12688     reference=SvRV(ST(0));
12689     av=(AV *) reference;
12690     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12691       exception);
12692     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12693     if (image == (Image *) NULL)
12694       {
12695         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12696           PackageName);
12697         goto PerlException;
12698       }
12699     package_info=ClonePackageInfo(info,exception);
12700     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12701     CloneString(&draw_info->text,"");
12702     current=draw_info->affine;
12703     GetAffineMatrix(&affine);
12704     x=0.0;
12705     y=0.0;
12706     EXTEND(sp,7*items);
12707     for (i=2; i < items; i+=2)
12708     {
12709       attribute=(char *) SvPV(ST(i-1),na);
12710       switch (*attribute)
12711       {
12712         case 'A':
12713         case 'a':
12714         {
12715           if (LocaleCompare(attribute,"antialias") == 0)
12716             {
12717               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12718                 SvPV(ST(i),na));
12719               if (type < 0)
12720                 {
12721                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12722                     SvPV(ST(i),na));
12723                   break;
12724                 }
12725               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12726               break;
12727             }
12728           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12729             attribute);
12730           break;
12731         }
12732         case 'd':
12733         case 'D':
12734         {
12735           if (LocaleCompare(attribute,"density") == 0)
12736             {
12737               CloneString(&draw_info->density,SvPV(ST(i),na));
12738               break;
12739             }
12740           if (LocaleCompare(attribute,"direction") == 0)
12741             {
12742               draw_info->direction=(DirectionType) ParseCommandOption(
12743                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12744               break;
12745             }
12746           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12747             attribute);
12748           break;
12749         }
12750         case 'e':
12751         case 'E':
12752         {
12753           if (LocaleCompare(attribute,"encoding") == 0)
12754             {
12755               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12756               break;
12757             }
12758           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12759             attribute);
12760           break;
12761         }
12762         case 'f':
12763         case 'F':
12764         {
12765           if (LocaleCompare(attribute,"family") == 0)
12766             {
12767               CloneString(&draw_info->family,SvPV(ST(i),na));
12768               break;
12769             }
12770           if (LocaleCompare(attribute,"fill") == 0)
12771             {
12772               if (info)
12773                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12774                   &draw_info->fill,exception);
12775               break;
12776             }
12777           if (LocaleCompare(attribute,"font") == 0)
12778             {
12779               CloneString(&draw_info->font,SvPV(ST(i),na));
12780               break;
12781             }
12782           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12783             attribute);
12784           break;
12785         }
12786         case 'g':
12787         case 'G':
12788         {
12789           if (LocaleCompare(attribute,"geometry") == 0)
12790             {
12791               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12792               break;
12793             }
12794           if (LocaleCompare(attribute,"gravity") == 0)
12795             {
12796               draw_info->gravity=(GravityType) ParseCommandOption(
12797                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12798               break;
12799             }
12800           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12801             attribute);
12802           break;
12803         }
12804         case 'i':
12805         case 'I':
12806         {
12807           if (LocaleCompare(attribute,"interline-spacing") == 0)
12808             {
12809               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12810               draw_info->interline_spacing=geometry_info.rho;
12811               break;
12812             }
12813           if (LocaleCompare(attribute,"interword-spacing") == 0)
12814             {
12815               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12816               draw_info->interword_spacing=geometry_info.rho;
12817               break;
12818             }
12819           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12820             attribute);
12821           break;
12822         }
12823         case 'k':
12824         case 'K':
12825         {
12826           if (LocaleCompare(attribute,"kerning") == 0)
12827             {
12828               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12829               draw_info->kerning=geometry_info.rho;
12830               break;
12831             }
12832           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12833             attribute);
12834           break;
12835         }
12836         case 'p':
12837         case 'P':
12838         {
12839           if (LocaleCompare(attribute,"pointsize") == 0)
12840             {
12841               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12842               draw_info->pointsize=geometry_info.rho;
12843               break;
12844             }
12845           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12846             attribute);
12847           break;
12848         }
12849         case 'r':
12850         case 'R':
12851         {
12852           if (LocaleCompare(attribute,"rotate") == 0)
12853             {
12854               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12855               affine.rx=geometry_info.rho;
12856               affine.ry=geometry_info.sigma;
12857               if ((flags & SigmaValue) == 0)
12858                 affine.ry=affine.rx;
12859               break;
12860             }
12861           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12862             attribute);
12863           break;
12864         }
12865         case 's':
12866         case 'S':
12867         {
12868           if (LocaleCompare(attribute,"scale") == 0)
12869             {
12870               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12871               affine.sx=geometry_info.rho;
12872               affine.sy=geometry_info.sigma;
12873               if ((flags & SigmaValue) == 0)
12874                 affine.sy=affine.sx;
12875               break;
12876             }
12877           if (LocaleCompare(attribute,"skew") == 0)
12878             {
12879               double
12880                 x_angle,
12881                 y_angle;
12882
12883               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12884               x_angle=geometry_info.rho;
12885               y_angle=geometry_info.sigma;
12886               if ((flags & SigmaValue) == 0)
12887                 y_angle=x_angle;
12888               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12889               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12890               break;
12891             }
12892           if (LocaleCompare(attribute,"stroke") == 0)
12893             {
12894               if (info)
12895                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12896                   &draw_info->stroke,exception);
12897               break;
12898             }
12899           if (LocaleCompare(attribute,"style") == 0)
12900             {
12901               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12902                 SvPV(ST(i),na));
12903               if (type < 0)
12904                 {
12905                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12906                     SvPV(ST(i),na));
12907                   break;
12908                 }
12909               draw_info->style=(StyleType) type;
12910               break;
12911             }
12912           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12913             attribute);
12914           break;
12915         }
12916         case 't':
12917         case 'T':
12918         {
12919           if (LocaleCompare(attribute,"text") == 0)
12920             {
12921               CloneString(&draw_info->text,SvPV(ST(i),na));
12922               break;
12923             }
12924           if (LocaleCompare(attribute,"translate") == 0)
12925             {
12926               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12927               affine.tx=geometry_info.rho;
12928               affine.ty=geometry_info.sigma;
12929               if ((flags & SigmaValue) == 0)
12930                 affine.ty=affine.tx;
12931               break;
12932             }
12933           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12934             attribute);
12935           break;
12936         }
12937         case 'w':
12938         case 'W':
12939         {
12940           if (LocaleCompare(attribute,"weight") == 0)
12941             {
12942               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12943               draw_info->weight=(size_t) geometry_info.rho;
12944               break;
12945             }
12946           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12947             attribute);
12948           break;
12949         }
12950         case 'x':
12951         case 'X':
12952         {
12953           if (LocaleCompare(attribute,"x") == 0)
12954             {
12955               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12956               x=geometry_info.rho;
12957               break;
12958             }
12959           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12960             attribute);
12961           break;
12962         }
12963         case 'y':
12964         case 'Y':
12965         {
12966           if (LocaleCompare(attribute,"y") == 0)
12967             {
12968               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12969               y=geometry_info.rho;
12970               break;
12971             }
12972           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12973             attribute);
12974           break;
12975         }
12976         default:
12977         {
12978           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12979             attribute);
12980           break;
12981         }
12982       }
12983     }
12984     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12985     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12986     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12987     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12988     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12989     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12990     if (draw_info->geometry == (char *) NULL)
12991       {
12992         draw_info->geometry=AcquireString((char *) NULL);
12993         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12994           "%.15g,%.15g",x,y);
12995       }
12996     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12997     (void) CatchImageException(image);
12998     if (status == MagickFalse)
12999       PUSHs(&sv_undef);
13000     else
13001       {
13002         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13003         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13004         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13005         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13006         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13007         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13008         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13009         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13010         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13011         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13012         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13013         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13014         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13015       }
13016     draw_info=DestroyDrawInfo(draw_info);
13017
13018   PerlException:
13019     if (package_info != (struct PackageInfo *) NULL)
13020       DestroyPackageInfo(package_info);
13021     InheritPerlException(exception,perl_exception);
13022     exception=DestroyExceptionInfo(exception);
13023     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13024   }
13025 \f
13026 #
13027 ###############################################################################
13028 #                                                                             #
13029 #                                                                             #
13030 #                                                                             #
13031 #   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                         #
13032 #                                                                             #
13033 #                                                                             #
13034 #                                                                             #
13035 ###############################################################################
13036 #
13037 #
13038 void
13039 QueryMultilineFontMetrics(ref,...)
13040   Image::Magick ref=NO_INIT
13041   ALIAS:
13042     querymultilinefontmetrics = 1
13043   PPCODE:
13044   {
13045     AffineMatrix
13046       affine,
13047       current;
13048
13049     AV
13050       *av;
13051
13052     char
13053       *attribute;
13054
13055     double
13056       x,
13057       y;
13058
13059     DrawInfo
13060       *draw_info;
13061
13062     ExceptionInfo
13063       *exception;
13064
13065     GeometryInfo
13066       geometry_info;
13067
13068     Image
13069       *image;
13070
13071     MagickBooleanType
13072       status;
13073
13074     MagickStatusType
13075       flags;
13076
13077     register ssize_t
13078       i;
13079
13080     ssize_t
13081       type;
13082
13083     struct PackageInfo
13084       *info,
13085       *package_info;
13086
13087     SV
13088       *perl_exception,
13089       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13090
13091     TypeMetric
13092       metrics;
13093
13094     PERL_UNUSED_VAR(ref);
13095     PERL_UNUSED_VAR(ix);
13096     exception=AcquireExceptionInfo();
13097     package_info=(struct PackageInfo *) NULL;
13098     perl_exception=newSVpv("",0);
13099     reference=SvRV(ST(0));
13100     av=(AV *) reference;
13101     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13102       exception);
13103     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13104     if (image == (Image *) NULL)
13105       {
13106         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13107           PackageName);
13108         goto PerlException;
13109       }
13110     package_info=ClonePackageInfo(info,exception);
13111     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13112     CloneString(&draw_info->text,"");
13113     current=draw_info->affine;
13114     GetAffineMatrix(&affine);
13115     x=0.0;
13116     y=0.0;
13117     EXTEND(sp,7*items);
13118     for (i=2; i < items; i+=2)
13119     {
13120       attribute=(char *) SvPV(ST(i-1),na);
13121       switch (*attribute)
13122       {
13123         case 'A':
13124         case 'a':
13125         {
13126           if (LocaleCompare(attribute,"antialias") == 0)
13127             {
13128               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13129                 SvPV(ST(i),na));
13130               if (type < 0)
13131                 {
13132                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13133                     SvPV(ST(i),na));
13134                   break;
13135                 }
13136               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13137               break;
13138             }
13139           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13140             attribute);
13141           break;
13142         }
13143         case 'd':
13144         case 'D':
13145         {
13146           if (LocaleCompare(attribute,"density") == 0)
13147             {
13148               CloneString(&draw_info->density,SvPV(ST(i),na));
13149               break;
13150             }
13151           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13152             attribute);
13153           break;
13154         }
13155         case 'e':
13156         case 'E':
13157         {
13158           if (LocaleCompare(attribute,"encoding") == 0)
13159             {
13160               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13161               break;
13162             }
13163           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13164             attribute);
13165           break;
13166         }
13167         case 'f':
13168         case 'F':
13169         {
13170           if (LocaleCompare(attribute,"family") == 0)
13171             {
13172               CloneString(&draw_info->family,SvPV(ST(i),na));
13173               break;
13174             }
13175           if (LocaleCompare(attribute,"fill") == 0)
13176             {
13177               if (info)
13178                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13179                   &draw_info->fill,exception);
13180               break;
13181             }
13182           if (LocaleCompare(attribute,"font") == 0)
13183             {
13184               CloneString(&draw_info->font,SvPV(ST(i),na));
13185               break;
13186             }
13187           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13188             attribute);
13189           break;
13190         }
13191         case 'g':
13192         case 'G':
13193         {
13194           if (LocaleCompare(attribute,"geometry") == 0)
13195             {
13196               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13197               break;
13198             }
13199           if (LocaleCompare(attribute,"gravity") == 0)
13200             {
13201               draw_info->gravity=(GravityType) ParseCommandOption(
13202                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13203               break;
13204             }
13205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13206             attribute);
13207           break;
13208         }
13209         case 'p':
13210         case 'P':
13211         {
13212           if (LocaleCompare(attribute,"pointsize") == 0)
13213             {
13214               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13215               draw_info->pointsize=geometry_info.rho;
13216               break;
13217             }
13218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13219             attribute);
13220           break;
13221         }
13222         case 'r':
13223         case 'R':
13224         {
13225           if (LocaleCompare(attribute,"rotate") == 0)
13226             {
13227               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13228               affine.rx=geometry_info.rho;
13229               affine.ry=geometry_info.sigma;
13230               if ((flags & SigmaValue) == 0)
13231                 affine.ry=affine.rx;
13232               break;
13233             }
13234           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13235             attribute);
13236           break;
13237         }
13238         case 's':
13239         case 'S':
13240         {
13241           if (LocaleCompare(attribute,"scale") == 0)
13242             {
13243               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13244               affine.sx=geometry_info.rho;
13245               affine.sy=geometry_info.sigma;
13246               if ((flags & SigmaValue) == 0)
13247                 affine.sy=affine.sx;
13248               break;
13249             }
13250           if (LocaleCompare(attribute,"skew") == 0)
13251             {
13252               double
13253                 x_angle,
13254                 y_angle;
13255
13256               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13257               x_angle=geometry_info.rho;
13258               y_angle=geometry_info.sigma;
13259               if ((flags & SigmaValue) == 0)
13260                 y_angle=x_angle;
13261               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13262               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13263               break;
13264             }
13265           if (LocaleCompare(attribute,"stroke") == 0)
13266             {
13267               if (info)
13268                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13269                   &draw_info->stroke,exception);
13270               break;
13271             }
13272           if (LocaleCompare(attribute,"style") == 0)
13273             {
13274               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13275                 SvPV(ST(i),na));
13276               if (type < 0)
13277                 {
13278                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13279                     SvPV(ST(i),na));
13280                   break;
13281                 }
13282               draw_info->style=(StyleType) type;
13283               break;
13284             }
13285           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13286             attribute);
13287           break;
13288         }
13289         case 't':
13290         case 'T':
13291         {
13292           if (LocaleCompare(attribute,"text") == 0)
13293             {
13294               CloneString(&draw_info->text,SvPV(ST(i),na));
13295               break;
13296             }
13297           if (LocaleCompare(attribute,"translate") == 0)
13298             {
13299               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13300               affine.tx=geometry_info.rho;
13301               affine.ty=geometry_info.sigma;
13302               if ((flags & SigmaValue) == 0)
13303                 affine.ty=affine.tx;
13304               break;
13305             }
13306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13307             attribute);
13308           break;
13309         }
13310         case 'w':
13311         case 'W':
13312         {
13313           if (LocaleCompare(attribute,"weight") == 0)
13314             {
13315               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13316               draw_info->weight=(size_t) geometry_info.rho;
13317               break;
13318             }
13319           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13320             attribute);
13321           break;
13322         }
13323         case 'x':
13324         case 'X':
13325         {
13326           if (LocaleCompare(attribute,"x") == 0)
13327             {
13328               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13329               x=geometry_info.rho;
13330               break;
13331             }
13332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13333             attribute);
13334           break;
13335         }
13336         case 'y':
13337         case 'Y':
13338         {
13339           if (LocaleCompare(attribute,"y") == 0)
13340             {
13341               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13342               y=geometry_info.rho;
13343               break;
13344             }
13345           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13346             attribute);
13347           break;
13348         }
13349         default:
13350         {
13351           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13352             attribute);
13353           break;
13354         }
13355       }
13356     }
13357     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13358     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13359     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13360     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13361     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13362     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13363     if (draw_info->geometry == (char *) NULL)
13364       {
13365         draw_info->geometry=AcquireString((char *) NULL);
13366         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13367           "%.15g,%.15g",x,y);
13368       }
13369     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13370     (void) CatchException(exception);
13371     if (status == MagickFalse)
13372       PUSHs(&sv_undef);
13373     else
13374       {
13375         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13376         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13377         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13378         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13379         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13380         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13381         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13382         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13383         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13384         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13385         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13386         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13387         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13388       }
13389     draw_info=DestroyDrawInfo(draw_info);
13390
13391   PerlException:
13392     if (package_info != (struct PackageInfo *) NULL)
13393       DestroyPackageInfo(package_info);
13394     InheritPerlException(exception,perl_exception);
13395     exception=DestroyExceptionInfo(exception);
13396     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13397   }
13398 \f
13399 #
13400 ###############################################################################
13401 #                                                                             #
13402 #                                                                             #
13403 #                                                                             #
13404 #   Q u e r y F o r m a t                                                     #
13405 #                                                                             #
13406 #                                                                             #
13407 #                                                                             #
13408 ###############################################################################
13409 #
13410 #
13411 void
13412 QueryFormat(ref,...)
13413   Image::Magick ref=NO_INIT
13414   ALIAS:
13415     queryformat = 1
13416   PPCODE:
13417   {
13418     char
13419       *name;
13420
13421     ExceptionInfo
13422       *exception;
13423
13424     register ssize_t
13425       i;
13426
13427     SV
13428       *perl_exception;
13429
13430     volatile const MagickInfo
13431       *magick_info;
13432
13433     PERL_UNUSED_VAR(ref);
13434     PERL_UNUSED_VAR(ix);
13435     exception=AcquireExceptionInfo();
13436     perl_exception=newSVpv("",0);
13437     if (items == 1)
13438       {
13439         char
13440           format[MagickPathExtent];
13441
13442         const MagickInfo
13443           **format_list;
13444
13445         size_t
13446           types;
13447
13448         format_list=GetMagickInfoList("*",&types,exception);
13449         EXTEND(sp,types);
13450         for (i=0; i < (ssize_t) types; i++)
13451         {
13452           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13453           LocaleLower(format);
13454           PUSHs(sv_2mortal(newSVpv(format,0)));
13455         }
13456         format_list=(const MagickInfo **)
13457           RelinquishMagickMemory((MagickInfo *) format_list);
13458         goto PerlException;
13459       }
13460     EXTEND(sp,8*items);
13461     for (i=1; i < items; i++)
13462     {
13463       name=(char *) SvPV(ST(i),na);
13464       magick_info=GetMagickInfo(name,exception);
13465       if (magick_info == (const MagickInfo *) NULL)
13466         {
13467           PUSHs(&sv_undef);
13468           continue;
13469         }
13470       if (magick_info->description == (char *) NULL)
13471         PUSHs(&sv_undef);
13472       else
13473         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13474       if (magick_info->module == (char *) NULL)
13475         PUSHs(&sv_undef);
13476       else
13477         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13478     }
13479
13480   PerlException:
13481     InheritPerlException(exception,perl_exception);
13482     exception=DestroyExceptionInfo(exception);
13483     SvREFCNT_dec(perl_exception);
13484   }
13485 \f
13486 #
13487 ###############################################################################
13488 #                                                                             #
13489 #                                                                             #
13490 #                                                                             #
13491 #   Q u e r y O p t i o n                                                     #
13492 #                                                                             #
13493 #                                                                             #
13494 #                                                                             #
13495 ###############################################################################
13496 #
13497 #
13498 void
13499 QueryOption(ref,...)
13500   Image::Magick ref=NO_INIT
13501   ALIAS:
13502     queryoption = 1
13503   PPCODE:
13504   {
13505     char
13506       **options;
13507
13508     ExceptionInfo
13509       *exception;
13510
13511     register ssize_t
13512       i;
13513
13514     ssize_t
13515       j,
13516       option;
13517
13518     SV
13519       *perl_exception;
13520
13521     PERL_UNUSED_VAR(ref);
13522     PERL_UNUSED_VAR(ix);
13523     exception=AcquireExceptionInfo();
13524     perl_exception=newSVpv("",0);
13525     EXTEND(sp,8*items);
13526     for (i=1; i < items; i++)
13527     {
13528       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13529         SvPV(ST(i),na));
13530       options=GetCommandOptions((CommandOption) option);
13531       if (options == (char **) NULL)
13532         PUSHs(&sv_undef);
13533       else
13534         {
13535           for (j=0; options[j] != (char *) NULL; j++)
13536             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13537           options=DestroyStringList(options);
13538         }
13539     }
13540
13541     InheritPerlException(exception,perl_exception);
13542     exception=DestroyExceptionInfo(exception);
13543     SvREFCNT_dec(perl_exception);
13544   }
13545 \f
13546 #
13547 ###############################################################################
13548 #                                                                             #
13549 #                                                                             #
13550 #                                                                             #
13551 #   R e a d                                                                   #
13552 #                                                                             #
13553 #                                                                             #
13554 #                                                                             #
13555 ###############################################################################
13556 #
13557 #
13558 void
13559 Read(ref,...)
13560   Image::Magick ref=NO_INIT
13561   ALIAS:
13562     ReadImage  = 1
13563     read       = 2
13564     readimage  = 3
13565   PPCODE:
13566   {
13567     AV
13568       *av;
13569
13570     char
13571       **keep,
13572       **list;
13573
13574     ExceptionInfo
13575       *exception;
13576
13577     HV
13578       *hv;
13579
13580     Image
13581       *image;
13582
13583     int
13584       n;
13585
13586     MagickBooleanType
13587       status;
13588
13589     register char
13590       **p;
13591
13592     register ssize_t
13593       i;
13594
13595     ssize_t
13596       ac,
13597       number_images;
13598
13599     STRLEN
13600       *length;
13601
13602     struct PackageInfo
13603       *info,
13604       *package_info;
13605
13606     SV
13607       *perl_exception,  /* Perl variable for storing messages */
13608       *reference,
13609       *rv,
13610       *sv;
13611
13612     PERL_UNUSED_VAR(ref);
13613     PERL_UNUSED_VAR(ix);
13614     exception=AcquireExceptionInfo();
13615     perl_exception=newSVpv("",0);
13616     sv=NULL;
13617     package_info=(struct PackageInfo *) NULL;
13618     number_images=0;
13619     ac=(items < 2) ? 1 : items-1;
13620     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13621     keep=list;
13622     length=(STRLEN *) NULL;
13623     if (list == (char **) NULL)
13624       {
13625         ThrowPerlException(exception,ResourceLimitError,
13626           "MemoryAllocationFailed",PackageName);
13627         goto PerlException;
13628       }
13629     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13630     if (length == (STRLEN *) NULL)
13631       {
13632         ThrowPerlException(exception,ResourceLimitError,
13633           "MemoryAllocationFailed",PackageName);
13634         goto PerlException;
13635       }
13636     if (sv_isobject(ST(0)) == 0)
13637       {
13638         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13639           PackageName);
13640         goto PerlException;
13641       }
13642     reference=SvRV(ST(0));
13643     hv=SvSTASH(reference);
13644     if (SvTYPE(reference) != SVt_PVAV)
13645       {
13646         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13647           PackageName);
13648         goto PerlException;
13649       }
13650     av=(AV *) reference;
13651     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13652       exception);
13653     package_info=ClonePackageInfo(info,exception);
13654     n=1;
13655     if (items <= 1)
13656       *list=(char *) (*package_info->image_info->filename ?
13657         package_info->image_info->filename : "XC:black");
13658     else
13659       for (n=0, i=0; i < ac; i++)
13660       {
13661         list[n]=(char *) SvPV(ST(i+1),length[n]);
13662         if ((items >= 3) && strEQcase(list[n],"blob"))
13663           {
13664             void
13665               *blob;
13666
13667             i++;
13668             blob=(void *) (SvPV(ST(i+1),length[n]));
13669             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13670           }
13671         if ((items >= 3) && strEQcase(list[n],"filename"))
13672           continue;
13673         if ((items >= 3) && strEQcase(list[n],"file"))
13674           {
13675             FILE
13676               *file;
13677
13678             PerlIO
13679               *io_info;
13680
13681             i++;
13682             io_info=IoIFP(sv_2io(ST(i+1)));
13683             if (io_info == (PerlIO *) NULL)
13684               {
13685                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13686                   PackageName);
13687                 continue;
13688               }
13689             file=PerlIO_findFILE(io_info);
13690             if (file == (FILE *) NULL)
13691               {
13692                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13693                   PackageName);
13694                 continue;
13695               }
13696             SetImageInfoFile(package_info->image_info,file);
13697           }
13698         if ((items >= 3) && strEQcase(list[n],"magick"))
13699           continue;
13700         n++;
13701       }
13702     list[n]=(char *) NULL;
13703     keep=list;
13704     status=ExpandFilenames(&n,&list);
13705     if (status == MagickFalse)
13706       {
13707         ThrowPerlException(exception,ResourceLimitError,
13708           "MemoryAllocationFailed",PackageName);
13709         goto PerlException;
13710       }
13711     number_images=0;
13712     for (i=0; i < n; i++)
13713     {
13714       if ((package_info->image_info->file == (FILE *) NULL) &&
13715           (package_info->image_info->blob == (void *) NULL))
13716         image=ReadImages(package_info->image_info,list[i],exception);
13717       else
13718         {
13719           image=ReadImages(package_info->image_info,
13720             package_info->image_info->filename,exception);
13721           if (image != (Image *) NULL)
13722             DisassociateImageStream(image);
13723         }
13724       if (image == (Image *) NULL)
13725         break;
13726       for ( ; image; image=image->next)
13727       {
13728         AddImageToRegistry(sv,image);
13729         rv=newRV(sv);
13730         av_push(av,sv_bless(rv,hv));
13731         SvREFCNT_dec(sv);
13732         number_images++;
13733       }
13734     }
13735     /*
13736       Free resources.
13737     */
13738     for (i=0; i < n; i++)
13739       if (list[i] != (char *) NULL)
13740         for (p=keep; list[i] != *p++; )
13741           if (*p == (char *) NULL)
13742             {
13743               list[i]=(char *) RelinquishMagickMemory(list[i]);
13744               break;
13745             }
13746
13747   PerlException:
13748     if (package_info != (struct PackageInfo *) NULL)
13749       DestroyPackageInfo(package_info);
13750     if (list && (list != keep))
13751       list=(char **) RelinquishMagickMemory(list);
13752     if (keep)
13753       keep=(char **) RelinquishMagickMemory(keep);
13754     if (length)
13755       length=(STRLEN *) RelinquishMagickMemory(length);
13756     InheritPerlException(exception,perl_exception);
13757     exception=DestroyExceptionInfo(exception);
13758     sv_setiv(perl_exception,(IV) number_images);
13759     SvPOK_on(perl_exception);
13760     ST(0)=sv_2mortal(perl_exception);
13761     XSRETURN(1);
13762   }
13763 \f
13764 #
13765 ###############################################################################
13766 #                                                                             #
13767 #                                                                             #
13768 #                                                                             #
13769 #   R e m o t e                                                               #
13770 #                                                                             #
13771 #                                                                             #
13772 #                                                                             #
13773 ###############################################################################
13774 #
13775 #
13776 void
13777 Remote(ref,...)
13778   Image::Magick ref=NO_INIT
13779   ALIAS:
13780     RemoteCommand  = 1
13781     remote         = 2
13782     remoteCommand  = 3
13783   PPCODE:
13784   {
13785     AV
13786       *av;
13787
13788     ExceptionInfo
13789       *exception;
13790
13791     register ssize_t
13792       i;
13793
13794     SV
13795       *perl_exception,
13796       *reference;
13797
13798     struct PackageInfo
13799       *info;
13800
13801     PERL_UNUSED_VAR(ref);
13802     PERL_UNUSED_VAR(ix);
13803     exception=AcquireExceptionInfo();
13804     perl_exception=newSVpv("",0);
13805     reference=SvRV(ST(0));
13806     av=(AV *) reference;
13807     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13808       exception);
13809     for (i=1; i < items; i++)
13810       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13811         SvPV(ST(i),na),exception);
13812     InheritPerlException(exception,perl_exception);
13813     exception=DestroyExceptionInfo(exception);
13814     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13815   }
13816 \f
13817 #
13818 ###############################################################################
13819 #                                                                             #
13820 #                                                                             #
13821 #                                                                             #
13822 #   S e t                                                                     #
13823 #                                                                             #
13824 #                                                                             #
13825 #                                                                             #
13826 ###############################################################################
13827 #
13828 #
13829 void
13830 Set(ref,...)
13831   Image::Magick ref=NO_INIT
13832   ALIAS:
13833     SetAttributes  = 1
13834     SetAttribute   = 2
13835     set            = 3
13836     setattributes  = 4
13837     setattribute   = 5
13838   PPCODE:
13839   {
13840     ExceptionInfo
13841       *exception;
13842
13843     Image
13844       *image;
13845
13846     register ssize_t
13847       i;
13848
13849     struct PackageInfo
13850       *info;
13851
13852     SV
13853       *perl_exception,
13854       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13855
13856     PERL_UNUSED_VAR(ref);
13857     PERL_UNUSED_VAR(ix);
13858     exception=AcquireExceptionInfo();
13859     perl_exception=newSVpv("",0);
13860     if (sv_isobject(ST(0)) == 0)
13861       {
13862         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13863           PackageName);
13864         goto PerlException;
13865       }
13866     reference=SvRV(ST(0));
13867     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13868     if (items == 2)
13869       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13870     else
13871       for (i=2; i < items; i+=2)
13872         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13873
13874   PerlException:
13875     InheritPerlException(exception,perl_exception);
13876     exception=DestroyExceptionInfo(exception);
13877     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13878     SvPOK_on(perl_exception);
13879     ST(0)=sv_2mortal(perl_exception);
13880     XSRETURN(1);
13881   }
13882 \f
13883 #
13884 ###############################################################################
13885 #                                                                             #
13886 #                                                                             #
13887 #                                                                             #
13888 #   S e t P i x e l                                                           #
13889 #                                                                             #
13890 #                                                                             #
13891 #                                                                             #
13892 ###############################################################################
13893 #
13894 #
13895 void
13896 SetPixel(ref,...)
13897   Image::Magick ref=NO_INIT
13898   ALIAS:
13899     setpixel = 1
13900     setPixel = 2
13901   PPCODE:
13902   {
13903     AV
13904       *av;
13905
13906     char
13907       *attribute;
13908
13909     ChannelType
13910       channel,
13911       channel_mask;
13912
13913     ExceptionInfo
13914       *exception;
13915
13916     Image
13917       *image;
13918
13919     MagickBooleanType
13920       normalize;
13921
13922     RectangleInfo
13923       region;
13924
13925     register ssize_t
13926       i;
13927
13928     register Quantum
13929       *q;
13930
13931     ssize_t
13932       option;
13933
13934     struct PackageInfo
13935       *info;
13936
13937     SV
13938       *perl_exception,
13939       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13940
13941     PERL_UNUSED_VAR(ref);
13942     PERL_UNUSED_VAR(ix);
13943     exception=AcquireExceptionInfo();
13944     perl_exception=newSVpv("",0);
13945     reference=SvRV(ST(0));
13946     av=(AV *) reference;
13947     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13948       exception);
13949     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13950     if (image == (Image *) NULL)
13951       {
13952         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13953           PackageName);
13954         goto PerlException;
13955       }
13956     av=(AV *) NULL;
13957     normalize=MagickTrue;
13958     region.x=0;
13959     region.y=0;
13960     region.width=image->columns;
13961     region.height=1;
13962     if (items == 1)
13963       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13964     channel=DefaultChannels;
13965     for (i=2; i < items; i+=2)
13966     {
13967       attribute=(char *) SvPV(ST(i-1),na);
13968       switch (*attribute)
13969       {
13970         case 'C':
13971         case 'c':
13972         {
13973           if (LocaleCompare(attribute,"channel") == 0)
13974             {
13975               ssize_t
13976                 option;
13977
13978               option=ParseChannelOption(SvPV(ST(i),na));
13979               if (option < 0)
13980                 {
13981                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13982                     SvPV(ST(i),na));
13983                   return;
13984                 }
13985               channel=(ChannelType) option;
13986               break;
13987             }
13988           if (LocaleCompare(attribute,"color") == 0)
13989             {
13990               if (SvTYPE(ST(i)) != SVt_RV)
13991                 {
13992                   char
13993                     message[MagickPathExtent];
13994
13995                   (void) FormatLocaleString(message,MagickPathExtent,
13996                     "invalid %.60s value",attribute);
13997                   ThrowPerlException(exception,OptionError,message,
13998                     SvPV(ST(i),na));
13999                 }
14000               av=(AV *) SvRV(ST(i));
14001               break;
14002             }
14003           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14004             attribute);
14005           break;
14006         }
14007         case 'g':
14008         case 'G':
14009         {
14010           if (LocaleCompare(attribute,"geometry") == 0)
14011             {
14012               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14013               break;
14014             }
14015           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14016             attribute);
14017           break;
14018         }
14019         case 'N':
14020         case 'n':
14021         {
14022           if (LocaleCompare(attribute,"normalize") == 0)
14023             {
14024               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14025                 SvPV(ST(i),na));
14026               if (option < 0)
14027                 {
14028                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14029                     SvPV(ST(i),na));
14030                   break;
14031                 }
14032              normalize=option != 0 ? MagickTrue : MagickFalse;
14033              break;
14034             }
14035           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14036             attribute);
14037           break;
14038         }
14039         case 'x':
14040         case 'X':
14041         {
14042           if (LocaleCompare(attribute,"x") == 0)
14043             {
14044               region.x=SvIV(ST(i));
14045               break;
14046             }
14047           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14048             attribute);
14049           break;
14050         }
14051         case 'y':
14052         case 'Y':
14053         {
14054           if (LocaleCompare(attribute,"y") == 0)
14055             {
14056               region.y=SvIV(ST(i));
14057               break;
14058             }
14059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14060             attribute);
14061           break;
14062         }
14063         default:
14064         {
14065           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14066             attribute);
14067           break;
14068         }
14069       }
14070     }
14071     (void) SetImageStorageClass(image,DirectClass,exception);
14072     channel_mask=SetImageChannelMask(image,channel);
14073     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14074     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14075         (SvTYPE(av) != SVt_PVAV))
14076       PUSHs(&sv_undef);
14077     else
14078       {
14079         double
14080           scale;
14081
14082         register ssize_t
14083           i;
14084
14085         i=0;
14086         scale=1.0;
14087         if (normalize != MagickFalse)
14088           scale=QuantumRange;
14089         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14090             (i <= av_len(av)))
14091           {
14092             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14093               av_fetch(av,i,0)))),q);
14094             i++;
14095           }
14096         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14097             (i <= av_len(av)))
14098           {
14099             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14100               av_fetch(av,i,0)))),q);
14101             i++;
14102           }
14103         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14104             (i <= av_len(av)))
14105           {
14106             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14107               av_fetch(av,i,0)))),q);
14108             i++;
14109           }
14110         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14111             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14112           {
14113             SetPixelBlack(image,ClampToQuantum(scale*
14114               SvNV(*(av_fetch(av,i,0)))),q);
14115             i++;
14116           }
14117         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14118             (i <= av_len(av)))
14119           {
14120             SetPixelAlpha(image,ClampToQuantum(scale*
14121               SvNV(*(av_fetch(av,i,0)))),q);
14122             i++;
14123           }
14124         (void) SyncAuthenticPixels(image,exception);
14125       }
14126     (void) SetImageChannelMask(image,channel_mask);
14127
14128   PerlException:
14129     InheritPerlException(exception,perl_exception);
14130     exception=DestroyExceptionInfo(exception);
14131     SvREFCNT_dec(perl_exception);
14132   }
14133 \f
14134 #
14135 ###############################################################################
14136 #                                                                             #
14137 #                                                                             #
14138 #                                                                             #
14139 #   S m u s h                                                                 #
14140 #                                                                             #
14141 #                                                                             #
14142 #                                                                             #
14143 ###############################################################################
14144 #
14145 #
14146 void
14147 Smush(ref,...)
14148   Image::Magick ref=NO_INIT
14149   ALIAS:
14150     SmushImage  = 1
14151     smush       = 2
14152     smushimage  = 3
14153   PPCODE:
14154   {
14155     AV
14156       *av;
14157
14158     char
14159       *attribute;
14160
14161     ExceptionInfo
14162       *exception;
14163
14164     HV
14165       *hv;
14166
14167     Image
14168       *image;
14169
14170     register ssize_t
14171       i;
14172
14173     ssize_t
14174       offset,
14175       stack;
14176
14177     struct PackageInfo
14178       *info;
14179
14180     SV
14181       *av_reference,
14182       *perl_exception,
14183       *reference,
14184       *rv,
14185       *sv;
14186
14187     PERL_UNUSED_VAR(ref);
14188     PERL_UNUSED_VAR(ix);
14189     exception=AcquireExceptionInfo();
14190     perl_exception=newSVpv("",0);
14191     sv=NULL;
14192     attribute=NULL;
14193     av=NULL;
14194     if (sv_isobject(ST(0)) == 0)
14195       {
14196         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14197           PackageName);
14198         goto PerlException;
14199       }
14200     reference=SvRV(ST(0));
14201     hv=SvSTASH(reference);
14202     av=newAV();
14203     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14204     SvREFCNT_dec(av);
14205     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14206     if (image == (Image *) NULL)
14207       {
14208         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14209           PackageName);
14210         goto PerlException;
14211       }
14212     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14213     /*
14214       Get options.
14215     */
14216     offset=0;
14217     stack=MagickTrue;
14218     for (i=2; i < items; i+=2)
14219     {
14220       attribute=(char *) SvPV(ST(i-1),na);
14221       switch (*attribute)
14222       {
14223         case 'O':
14224         case 'o':
14225         {
14226           if (LocaleCompare(attribute,"offset") == 0)
14227             {
14228               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14229               break;
14230             }
14231           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14232             attribute);
14233           break;
14234         }
14235         case 'S':
14236         case 's':
14237         {
14238           if (LocaleCompare(attribute,"stack") == 0)
14239             {
14240               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14241                 SvPV(ST(i),na));
14242               if (stack < 0)
14243                 {
14244                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14245                     SvPV(ST(i),na));
14246                   return;
14247                 }
14248               break;
14249             }
14250           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14251             attribute);
14252           break;
14253         }
14254         default:
14255         {
14256           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14257             attribute);
14258           break;
14259         }
14260       }
14261     }
14262     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14263       exception);
14264     if (image == (Image *) NULL)
14265       goto PerlException;
14266     for ( ; image; image=image->next)
14267     {
14268       AddImageToRegistry(sv,image);
14269       rv=newRV(sv);
14270       av_push(av,sv_bless(rv,hv));
14271       SvREFCNT_dec(sv);
14272     }
14273     exception=DestroyExceptionInfo(exception);
14274     ST(0)=av_reference;
14275     SvREFCNT_dec(perl_exception);
14276     XSRETURN(1);
14277
14278   PerlException:
14279     InheritPerlException(exception,perl_exception);
14280     exception=DestroyExceptionInfo(exception);
14281     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14282     SvPOK_on(perl_exception);
14283     ST(0)=sv_2mortal(perl_exception);
14284     XSRETURN(1);
14285   }
14286 \f
14287 #
14288 ###############################################################################
14289 #                                                                             #
14290 #                                                                             #
14291 #                                                                             #
14292 #   S t a t i s t i c s                                                       #
14293 #                                                                             #
14294 #                                                                             #
14295 #                                                                             #
14296 ###############################################################################
14297 #
14298 #
14299 void
14300 Statistics(ref,...)
14301   Image::Magick ref=NO_INIT
14302   ALIAS:
14303     StatisticsImage = 1
14304     statistics      = 2
14305     statisticsimage = 3
14306   PPCODE:
14307   {
14308 #define ChannelStatistics(channel) \
14309 { \
14310   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14311     (double) channel_statistics[channel].depth); \
14312   PUSHs(sv_2mortal(newSVpv(message,0))); \
14313   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14314     channel_statistics[channel].minima/scale); \
14315   PUSHs(sv_2mortal(newSVpv(message,0))); \
14316   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14317     channel_statistics[channel].maxima/scale); \
14318   PUSHs(sv_2mortal(newSVpv(message,0))); \
14319   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14320     channel_statistics[channel].mean/scale); \
14321   PUSHs(sv_2mortal(newSVpv(message,0))); \
14322   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14323     channel_statistics[channel].standard_deviation/scale); \
14324   PUSHs(sv_2mortal(newSVpv(message,0))); \
14325   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14326     channel_statistics[channel].kurtosis); \
14327   PUSHs(sv_2mortal(newSVpv(message,0))); \
14328   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14329     channel_statistics[channel].skewness); \
14330   PUSHs(sv_2mortal(newSVpv(message,0))); \
14331   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14332     channel_statistics[channel].entropy); \
14333   PUSHs(sv_2mortal(newSVpv(message,0))); \
14334 }
14335
14336     AV
14337       *av;
14338
14339     char
14340       message[MagickPathExtent];
14341
14342     ChannelStatistics
14343       *channel_statistics;
14344
14345     double
14346       scale;
14347
14348     ExceptionInfo
14349       *exception;
14350
14351     Image
14352       *image;
14353
14354     ssize_t
14355       count;
14356
14357     struct PackageInfo
14358       *info;
14359
14360     SV
14361       *perl_exception,
14362       *reference;
14363
14364     PERL_UNUSED_VAR(ref);
14365     PERL_UNUSED_VAR(ix);
14366     exception=AcquireExceptionInfo();
14367     perl_exception=newSVpv("",0);
14368     av=NULL;
14369     if (sv_isobject(ST(0)) == 0)
14370       {
14371         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14372           PackageName);
14373         goto PerlException;
14374       }
14375     reference=SvRV(ST(0));
14376     av=newAV();
14377     SvREFCNT_dec(av);
14378     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14379     if (image == (Image *) NULL)
14380       {
14381         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14382           PackageName);
14383         goto PerlException;
14384       }
14385     count=0;
14386     for ( ; image; image=image->next)
14387     {
14388       channel_statistics=GetImageStatistics(image,exception);
14389       if (channel_statistics == (ChannelStatistics *) NULL)
14390         continue;
14391       count++;
14392       EXTEND(sp,35*count);
14393       scale=(double) QuantumRange;
14394       ChannelStatistics(RedChannel);
14395       ChannelStatistics(GreenChannel);
14396       ChannelStatistics(BlueChannel);
14397       if (image->colorspace == CMYKColorspace)
14398         ChannelStatistics(BlackChannel);
14399       if (image->alpha_trait != UndefinedPixelTrait)
14400         ChannelStatistics(AlphaChannel);
14401       channel_statistics=(ChannelStatistics *)
14402         RelinquishMagickMemory(channel_statistics);
14403     }
14404
14405   PerlException:
14406     InheritPerlException(exception,perl_exception);
14407     exception=DestroyExceptionInfo(exception);
14408     SvREFCNT_dec(perl_exception);
14409   }
14410 \f
14411 #
14412 ###############################################################################
14413 #                                                                             #
14414 #                                                                             #
14415 #                                                                             #
14416 #   S y n c A u t h e n t i c P i x e l s                                     #
14417 #                                                                             #
14418 #                                                                             #
14419 #                                                                             #
14420 ###############################################################################
14421 #
14422 #
14423 void
14424 SyncAuthenticPixels(ref,...)
14425   Image::Magick ref = NO_INIT
14426   ALIAS:
14427     Syncauthenticpixels = 1
14428     SyncImagePixels = 2
14429     syncimagepixels = 3
14430   CODE:
14431   {
14432     ExceptionInfo
14433       *exception;
14434
14435     Image
14436       *image;
14437
14438     MagickBooleanType
14439       status;
14440
14441     struct PackageInfo
14442       *info;
14443
14444     SV
14445       *perl_exception,
14446       *reference;
14447
14448     PERL_UNUSED_VAR(ref);
14449     PERL_UNUSED_VAR(ix);
14450     exception=AcquireExceptionInfo();
14451     perl_exception=newSVpv("",0);
14452     if (sv_isobject(ST(0)) == 0)
14453       {
14454         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14455           PackageName);
14456         goto PerlException;
14457       }
14458
14459     reference=SvRV(ST(0));
14460     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14461     if (image == (Image *) NULL)
14462       {
14463         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14464           PackageName);
14465         goto PerlException;
14466       }
14467
14468     status=SyncAuthenticPixels(image,exception);
14469     if (status != MagickFalse)
14470       return;
14471
14472   PerlException:
14473     InheritPerlException(exception,perl_exception);
14474     exception=DestroyExceptionInfo(exception);
14475     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14476   }
14477 \f
14478 #
14479 ###############################################################################
14480 #                                                                             #
14481 #                                                                             #
14482 #                                                                             #
14483 #   W r i t e                                                                 #
14484 #                                                                             #
14485 #                                                                             #
14486 #                                                                             #
14487 ###############################################################################
14488 #
14489 #
14490 void
14491 Write(ref,...)
14492   Image::Magick ref=NO_INIT
14493   ALIAS:
14494     WriteImage    = 1
14495     write         = 2
14496     writeimage    = 3
14497   PPCODE:
14498   {
14499     char
14500       filename[MagickPathExtent];
14501
14502     ExceptionInfo
14503       *exception;
14504
14505     Image
14506       *image,
14507       *next;
14508
14509     register ssize_t
14510       i;
14511
14512     ssize_t
14513       number_images,
14514       scene;
14515
14516     struct PackageInfo
14517       *info,
14518       *package_info;
14519
14520     SV
14521       *perl_exception,
14522       *reference;
14523
14524     PERL_UNUSED_VAR(ref);
14525     PERL_UNUSED_VAR(ix);
14526     exception=AcquireExceptionInfo();
14527     perl_exception=newSVpv("",0);
14528     number_images=0;
14529     package_info=(struct PackageInfo *) NULL;
14530     if (sv_isobject(ST(0)) == 0)
14531       {
14532         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14533           PackageName);
14534         goto PerlException;
14535       }
14536     reference=SvRV(ST(0));
14537     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14538     if (image == (Image *) NULL)
14539       {
14540         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14541           PackageName);
14542         goto PerlException;
14543       }
14544     package_info=ClonePackageInfo(info,exception);
14545     if (items == 2)
14546       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14547     else
14548       if (items > 2)
14549         for (i=2; i < items; i+=2)
14550           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14551             exception);
14552     (void) CopyMagickString(filename,package_info->image_info->filename,
14553       MagickPathExtent);
14554     scene=0;
14555     for (next=image; next; next=next->next)
14556     {
14557       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14558       next->scene=scene++;
14559     }
14560     *package_info->image_info->magick='\0';
14561     SetImageInfo(package_info->image_info,(unsigned int)
14562       GetImageListLength(image),exception);
14563     for (next=image; next; next=next->next)
14564     {
14565       (void) WriteImage(package_info->image_info,next,exception);
14566       number_images++;
14567       if (package_info->image_info->adjoin)
14568         break;
14569     }
14570
14571   PerlException:
14572     if (package_info != (struct PackageInfo *) NULL)
14573       DestroyPackageInfo(package_info);
14574     InheritPerlException(exception,perl_exception);
14575     exception=DestroyExceptionInfo(exception);
14576     sv_setiv(perl_exception,(IV) number_images);
14577     SvPOK_on(perl_exception);
14578     ST(0)=sv_2mortal(perl_exception);
14579     XSRETURN(1);
14580   }