]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
3845b9f9c854467b78424f883b666a93b3ca92f4
[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-2014 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define 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[MaxTextExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MaxTextExtent,"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} } },
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     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
424       {"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     { "Sans", { {"matrix", ArrayReference} } },
535     { "Color", { {"color", StringReference} } },
536     { "Mode", { {"geometry", StringReference},
537       {"width", IntegerReference},{"height", IntegerReference},
538       {"channel", MagickChannelOptions} } },
539     { "Statistic", { {"geometry", StringReference},
540       {"width", IntegerReference},{"height", IntegerReference},
541       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
542     { "Perceptible", { {"epsilon", RealReference},
543       {"channel", MagickChannelOptions} } },
544     { "Poly", { {"terms", ArrayReference},
545       {"channel", MagickChannelOptions} } },
546     { "Grayscale", { {"method", MagickNoiseOptions} } },
547   };
548
549 static SplayTreeInfo
550   *magick_registry = (SplayTreeInfo *) NULL;
551 \f
552 /*
553   Forward declarations.
554 */
555 static Image
556   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
557
558 static ssize_t
559   strEQcase(const char *,const char *);
560 \f
561 /*
562 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
563 %                                                                             %
564 %                                                                             %
565 %                                                                             %
566 %   C l o n e P a c k a g e I n f o                                           %
567 %                                                                             %
568 %                                                                             %
569 %                                                                             %
570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
571 %
572 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
573 %  a new one.
574 %
575 %  The format of the ClonePackageInfo routine is:
576 %
577 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
578 %        exception)
579 %
580 %  A description of each parameter follows:
581 %
582 %    o info: a structure of type info.
583 %
584 %    o exception: Return any errors or warnings in this structure.
585 %
586 */
587 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
588   ExceptionInfo *exception)
589 {
590   struct PackageInfo
591     *clone_info;
592
593   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
594   if (clone_info == (struct PackageInfo *) NULL)
595     {
596       ThrowPerlException(exception,ResourceLimitError,
597         "UnableToClonePackageInfo",PackageName);
598       return((struct PackageInfo *) NULL);
599     }
600   if (info == (struct PackageInfo *) NULL)
601     {
602       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
603       return(clone_info);
604     }
605   *clone_info=(*info);
606   clone_info->image_info=CloneImageInfo(info->image_info);
607   return(clone_info);
608 }
609 \f
610 /*
611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
612 %                                                                             %
613 %                                                                             %
614 %                                                                             %
615 %   c o n s t a n t                                                           %
616 %                                                                             %
617 %                                                                             %
618 %                                                                             %
619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
620 %
621 %  constant() returns a double value for the specified name.
622 %
623 %  The format of the constant routine is:
624 %
625 %      double constant(char *name,ssize_t sans)
626 %
627 %  A description of each parameter follows:
628 %
629 %    o value: Method constant returns a double value for the specified name.
630 %
631 %    o name: The name of the constant.
632 %
633 %    o sans: This integer value is not used.
634 %
635 */
636 static double constant(char *name,ssize_t sans)
637 {
638   (void) sans;
639   errno=0;
640   switch (*name)
641   {
642     case 'B':
643     {
644       if (strEQ(name,"BlobError"))
645         return(BlobError);
646       if (strEQ(name,"BlobWarning"))
647         return(BlobWarning);
648       break;
649     }
650     case 'C':
651     {
652       if (strEQ(name,"CacheError"))
653         return(CacheError);
654       if (strEQ(name,"CacheWarning"))
655         return(CacheWarning);
656       if (strEQ(name,"CoderError"))
657         return(CoderError);
658       if (strEQ(name,"CoderWarning"))
659         return(CoderWarning);
660       if (strEQ(name,"ConfigureError"))
661         return(ConfigureError);
662       if (strEQ(name,"ConfigureWarning"))
663         return(ConfigureWarning);
664       if (strEQ(name,"CorruptImageError"))
665         return(CorruptImageError);
666       if (strEQ(name,"CorruptImageWarning"))
667         return(CorruptImageWarning);
668       break;
669     }
670     case 'D':
671     {
672       if (strEQ(name,"DelegateError"))
673         return(DelegateError);
674       if (strEQ(name,"DelegateWarning"))
675         return(DelegateWarning);
676       if (strEQ(name,"DrawError"))
677         return(DrawError);
678       if (strEQ(name,"DrawWarning"))
679         return(DrawWarning);
680       break;
681     }
682     case 'E':
683     {
684       if (strEQ(name,"ErrorException"))
685         return(ErrorException);
686       if (strEQ(name,"ExceptionError"))
687         return(CoderError);
688       if (strEQ(name,"ExceptionWarning"))
689         return(CoderWarning);
690       break;
691     }
692     case 'F':
693     {
694       if (strEQ(name,"FatalErrorException"))
695         return(FatalErrorException);
696       if (strEQ(name,"FileOpenError"))
697         return(FileOpenError);
698       if (strEQ(name,"FileOpenWarning"))
699         return(FileOpenWarning);
700       break;
701     }
702     case 'I':
703     {
704       if (strEQ(name,"ImageError"))
705         return(ImageError);
706       if (strEQ(name,"ImageWarning"))
707         return(ImageWarning);
708       break;
709     }
710     case 'M':
711     {
712       if (strEQ(name,"MaxRGB"))
713         return(QuantumRange);
714       if (strEQ(name,"MissingDelegateError"))
715         return(MissingDelegateError);
716       if (strEQ(name,"MissingDelegateWarning"))
717         return(MissingDelegateWarning);
718       if (strEQ(name,"ModuleError"))
719         return(ModuleError);
720       if (strEQ(name,"ModuleWarning"))
721         return(ModuleWarning);
722       break;
723     }
724     case 'O':
725     {
726       if (strEQ(name,"Opaque"))
727         return(OpaqueAlpha);
728       if (strEQ(name,"OptionError"))
729         return(OptionError);
730       if (strEQ(name,"OptionWarning"))
731         return(OptionWarning);
732       break;
733     }
734     case 'Q':
735     {
736       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
737         return(MAGICKCORE_QUANTUM_DEPTH);
738       if (strEQ(name,"QuantumDepth"))
739         return(MAGICKCORE_QUANTUM_DEPTH);
740       if (strEQ(name,"QuantumRange"))
741         return(QuantumRange);
742       break;
743     }
744     case 'R':
745     {
746       if (strEQ(name,"ResourceLimitError"))
747         return(ResourceLimitError);
748       if (strEQ(name,"ResourceLimitWarning"))
749         return(ResourceLimitWarning);
750       if (strEQ(name,"RegistryError"))
751         return(RegistryError);
752       if (strEQ(name,"RegistryWarning"))
753         return(RegistryWarning);
754       break;
755     }
756     case 'S':
757     {
758       if (strEQ(name,"StreamError"))
759         return(StreamError);
760       if (strEQ(name,"StreamWarning"))
761         return(StreamWarning);
762       if (strEQ(name,"Success"))
763         return(0);
764       break;
765     }
766     case 'T':
767     {
768       if (strEQ(name,"Transparent"))
769         return(TransparentAlpha);
770       if (strEQ(name,"TypeError"))
771         return(TypeError);
772       if (strEQ(name,"TypeWarning"))
773         return(TypeWarning);
774       break;
775     }
776     case 'W':
777     {
778       if (strEQ(name,"WarningException"))
779         return(WarningException);
780       break;
781     }
782     case 'X':
783     {
784       if (strEQ(name,"XServerError"))
785         return(XServerError);
786       if (strEQ(name,"XServerWarning"))
787         return(XServerWarning);
788       break;
789     }
790   }
791   errno=EINVAL;
792   return(0);
793 }
794 \f
795 /*
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
797 %                                                                             %
798 %                                                                             %
799 %                                                                             %
800 %   D e s t r o y P a c k a g e I n f o                                       %
801 %                                                                             %
802 %                                                                             %
803 %                                                                             %
804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
805 %
806 %  Method DestroyPackageInfo frees a previously created info structure.
807 %
808 %  The format of the DestroyPackageInfo routine is:
809 %
810 %      DestroyPackageInfo(struct PackageInfo *info)
811 %
812 %  A description of each parameter follows:
813 %
814 %    o info: a structure of type info.
815 %
816 */
817 static void DestroyPackageInfo(struct PackageInfo *info)
818 {
819   info->image_info=DestroyImageInfo(info->image_info);
820   info=(struct PackageInfo *) RelinquishMagickMemory(info);
821 }
822 \f
823 /*
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %                                                                             %
826 %                                                                             %
827 %                                                                             %
828 %   G e t L i s t                                                             %
829 %                                                                             %
830 %                                                                             %
831 %                                                                             %
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %
834 %  Method GetList is recursively called by SetupList to traverse the
835 %  Image__Magick reference.  If building an reference_vector (see SetupList),
836 %  *current is the current position in *reference_vector and *last is the final
837 %  entry in *reference_vector.
838 %
839 %  The format of the GetList routine is:
840 %
841 %      GetList(info)
842 %
843 %  A description of each parameter follows:
844 %
845 %    o info: a structure of type info.
846 %
847 */
848 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
849   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
850 {
851   Image
852     *image;
853
854   if (reference == (SV *) NULL)
855     return(NULL);
856   switch (SvTYPE(reference))
857   {
858     case SVt_PVAV:
859     {
860       AV
861         *av;
862
863       Image
864         *head,
865         *previous;
866
867       register ssize_t
868         i;
869
870       ssize_t
871         n;
872
873       /*
874         Array of images.
875       */
876       previous=(Image *) NULL;
877       head=(Image *) NULL;
878       av=(AV *) reference;
879       n=av_len(av);
880       for (i=0; i <= n; i++)
881       {
882         SV
883           **rv;
884
885         rv=av_fetch(av,i,0);
886         if (rv && *rv && sv_isobject(*rv))
887           {
888             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
889               exception);
890             if (image == (Image *) NULL)
891               continue;
892             if (image == previous)
893               {
894                 image=CloneImage(image,0,0,MagickTrue,exception);
895                 if (image == (Image *) NULL)
896                   return(NULL);
897               }
898             image->previous=previous;
899             *(previous ? &previous->next : &head)=image;
900             for (previous=image; previous->next; previous=previous->next) ;
901           }
902       }
903       return(head);
904     }
905     case SVt_PVMG:
906     {
907       /*
908         Blessed scalar, one image.
909       */
910       image=INT2PTR(Image *,SvIV(reference));
911       if (image == (Image *) NULL)
912         return(NULL);
913       image->previous=(Image *) NULL;
914       image->next=(Image *) NULL;
915       if (reference_vector)
916         {
917           if (*current == *last)
918             {
919               *last+=256;
920               if (*reference_vector == (SV **) NULL)
921                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
922                   sizeof(*reference_vector));
923               else
924                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
925                   *last,sizeof(*reference_vector));
926             }
927           if (*reference_vector == (SV **) NULL)
928             {
929               ThrowPerlException(exception,ResourceLimitError,
930                 "MemoryAllocationFailed",PackageName);
931               return((Image *) NULL);
932             }
933           (*reference_vector)[*current]=reference;
934           (*reference_vector)[++(*current)]=NULL;
935         }
936       return(image);
937     }
938     default:
939       break;
940   }
941   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
942     (double) SvTYPE(reference));
943   return((Image *) NULL);
944 }
945 \f
946 /*
947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
948 %                                                                             %
949 %                                                                             %
950 %                                                                             %
951 %   G e t P a c k a g e I n f o                                               %
952 %                                                                             %
953 %                                                                             %
954 %                                                                             %
955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
956 %
957 %  Method GetPackageInfo looks up or creates an info structure for the given
958 %  Image__Magick reference.  If it does create a new one, the information in
959 %  package_info is used to initialize it.
960 %
961 %  The format of the GetPackageInfo routine is:
962 %
963 %      struct PackageInfo *GetPackageInfo(void *reference,
964 %        struct PackageInfo *package_info,ExceptionInfo *exception)
965 %
966 %  A description of each parameter follows:
967 %
968 %    o info: a structure of type info.
969 %
970 %    o exception: Return any errors or warnings in this structure.
971 %
972 */
973 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
974   struct PackageInfo *package_info,ExceptionInfo *exception)
975 {
976   char
977     message[MaxTextExtent];
978
979   struct PackageInfo
980     *clone_info;
981
982   SV
983     *sv;
984
985   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
986     PackageName,XS_VERSION,reference);
987   sv=perl_get_sv(message,(TRUE | 0x02));
988   if (sv == (SV *) NULL)
989     {
990       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
991         message);
992       return(package_info);
993     }
994   if (SvREFCNT(sv) == 0)
995     (void) SvREFCNT_inc(sv);
996   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
997     return(clone_info);
998   clone_info=ClonePackageInfo(package_info,exception);
999   sv_setiv(sv,PTR2IV(clone_info));
1000   return(clone_info);
1001 }
1002 \f
1003 /*
1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1005 %                                                                             %
1006 %                                                                             %
1007 %                                                                             %
1008 %   S e t A t t r i b u t e                                                   %
1009 %                                                                             %
1010 %                                                                             %
1011 %                                                                             %
1012 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1013 %
1014 %  SetAttribute() sets the attribute to the value in sval.  This can change
1015 %  either or both of image or info.
1016 %
1017 %  The format of the SetAttribute routine is:
1018 %
1019 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1020 %        SV *sval,ExceptionInfo *exception)
1021 %
1022 %  A description of each parameter follows:
1023 %
1024 %    o list: a list of strings.
1025 %
1026 %    o string: a character string.
1027 %
1028 */
1029
1030 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1031 {
1032   char
1033     *q;
1034
1035   double
1036     value;
1037
1038   value=InterpretSiPrefixValue(string,&q);
1039   if (*q == '%')
1040     value*=interval/100.0;
1041   return(value);
1042 }
1043
1044 static inline double StringToDouble(const char *string,char **sentinal)
1045 {
1046   return(InterpretLocaleValue(string,sentinal));
1047 }
1048
1049 static double StringToDoubleInterval(const char *string,const double interval)
1050 {
1051   char
1052     *q;
1053
1054   double
1055     value;
1056
1057   value=InterpretLocaleValue(string,&q);
1058   if (*q == '%')
1059     value*=interval/100.0;
1060   return(value);
1061 }
1062
1063 static inline ssize_t StringToLong(const char *value)
1064 {
1065   return(strtol(value,(char **) NULL,10));
1066 }
1067
1068 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1069   const char *attribute,SV *sval,ExceptionInfo *exception)
1070 {
1071   GeometryInfo
1072     geometry_info;
1073
1074   long
1075     x,
1076     y;
1077
1078   PixelInfo
1079     pixel;
1080
1081   MagickStatusType
1082     flags;
1083
1084   PixelInfo
1085     *color,
1086     target_color;
1087
1088   ssize_t
1089     sp;
1090
1091   switch (*attribute)
1092   {
1093     case 'A':
1094     case 'a':
1095     {
1096       if (LocaleCompare(attribute,"adjoin") == 0)
1097         {
1098           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1099             SvPV(sval,na)) : SvIV(sval);
1100           if (sp < 0)
1101             {
1102               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1103                 SvPV(sval,na));
1104               break;
1105             }
1106           if (info)
1107             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1108           break;
1109         }
1110       if (LocaleCompare(attribute,"alpha") == 0)
1111         {
1112           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1113             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1114           if (sp < 0)
1115             {
1116               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1117                 SvPV(sval,na));
1118               break;
1119             }
1120           for ( ; image; image=image->next)
1121             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1122               exception);
1123           break;
1124         }
1125       if (LocaleCompare(attribute,"antialias") == 0)
1126         {
1127           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1128             SvPV(sval,na)) : SvIV(sval);
1129           if (sp < 0)
1130             {
1131               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1132                 SvPV(sval,na));
1133               break;
1134             }
1135           if (info)
1136             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1137           break;
1138         }
1139       if (LocaleCompare(attribute,"area-limit") == 0)
1140         {
1141           MagickSizeType
1142             limit;
1143
1144           limit=MagickResourceInfinity;
1145           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1146             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1147               100.0);
1148           (void) SetMagickResourceLimit(AreaResource,limit);
1149           break;
1150         }
1151       if (LocaleCompare(attribute,"attenuate") == 0)
1152         {
1153           if (info)
1154             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1155           break;
1156         }
1157       if (LocaleCompare(attribute,"authenticate") == 0)
1158         {
1159           if (info)
1160             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1161           break;
1162         }
1163       if (info)
1164         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1165       for ( ; image; image=image->next)
1166         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1167       break;
1168     }
1169     case 'B':
1170     case 'b':
1171     {
1172       if (LocaleCompare(attribute,"background") == 0)
1173         {
1174           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1175             exception);
1176           if (info)
1177             info->image_info->background_color=target_color;
1178           for ( ; image; image=image->next)
1179             image->background_color=target_color;
1180           break;
1181         }
1182       if (LocaleCompare(attribute,"blue-primary") == 0)
1183         {
1184           for ( ; image; image=image->next)
1185           {
1186             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1187             image->chromaticity.blue_primary.x=geometry_info.rho;
1188             image->chromaticity.blue_primary.y=geometry_info.sigma;
1189             if ((flags & SigmaValue) == 0)
1190               image->chromaticity.blue_primary.y=
1191                 image->chromaticity.blue_primary.x;
1192           }
1193           break;
1194         }
1195       if (LocaleCompare(attribute,"bordercolor") == 0)
1196         {
1197           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1198             exception);
1199           if (info)
1200             info->image_info->border_color=target_color;
1201           for ( ; image; image=image->next)
1202             image->border_color=target_color;
1203           break;
1204         }
1205       if (info)
1206         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1207       for ( ; image; image=image->next)
1208         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1209       break;
1210     }
1211     case 'C':
1212     case 'c':
1213     {
1214       if (LocaleCompare(attribute,"cache-threshold") == 0)
1215         {
1216           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1217             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1218           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1219             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1220           break;
1221         }
1222       if (LocaleCompare(attribute,"clip-mask") == 0)
1223         {
1224           Image
1225             *clip_mask;
1226
1227           clip_mask=(Image *) NULL;
1228           if (SvPOK(sval))
1229             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1230           for ( ; image; image=image->next)
1231             SetImageMask(image,clip_mask,exception);
1232           break;
1233         }
1234       if (LocaleNCompare(attribute,"colormap",8) == 0)
1235         {
1236           for ( ; image; image=image->next)
1237           {
1238             int
1239               items;
1240
1241             long
1242               i;
1243
1244             if (image->storage_class == DirectClass)
1245               continue;
1246             i=0;
1247             items=sscanf(attribute,"%*[^[][%ld",&i);
1248             (void) items;
1249             if (i > (ssize_t) image->colors)
1250               i%=image->colors;
1251             if ((strchr(SvPV(sval,na),',') == 0) ||
1252                 (strchr(SvPV(sval,na),')') != 0))
1253               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1254                 image->colormap+i,exception);
1255             else
1256               {
1257                 color=image->colormap+i;
1258                 pixel.red=color->red;
1259                 pixel.green=color->green;
1260                 pixel.blue=color->blue;
1261                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1262                 pixel.red=geometry_info.rho;
1263                 pixel.green=geometry_info.sigma;
1264                 pixel.blue=geometry_info.xi;
1265                 color->red=ClampToQuantum(pixel.red);
1266                 color->green=ClampToQuantum(pixel.green);
1267                 color->blue=ClampToQuantum(pixel.blue);
1268               }
1269           }
1270           break;
1271         }
1272       if (LocaleCompare(attribute,"colorspace") == 0)
1273         {
1274           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1275             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1276           if (sp < 0)
1277             {
1278               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1279                 SvPV(sval,na));
1280               break;
1281             }
1282           for ( ; image; image=image->next)
1283             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1284               exception);
1285           break;
1286         }
1287       if (LocaleCompare(attribute,"comment") == 0)
1288         {
1289           for ( ; image; image=image->next)
1290             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1291               info ? info->image_info : (ImageInfo *) NULL,image,
1292               SvPV(sval,na),exception),exception);
1293           break;
1294         }
1295       if (LocaleCompare(attribute,"compression") == 0)
1296         {
1297           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1298             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1299           if (sp < 0)
1300             {
1301               ThrowPerlException(exception,OptionError,
1302                 "UnrecognizedImageCompression",SvPV(sval,na));
1303               break;
1304             }
1305           if (info)
1306             info->image_info->compression=(CompressionType) sp;
1307           for ( ; image; image=image->next)
1308             image->compression=(CompressionType) sp;
1309           break;
1310         }
1311       if (info)
1312         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1313       for ( ; image; image=image->next)
1314         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1315       break;
1316     }
1317     case 'D':
1318     case 'd':
1319     {
1320       if (LocaleCompare(attribute,"debug") == 0)
1321         {
1322           SetLogEventMask(SvPV(sval,na));
1323           break;
1324         }
1325       if (LocaleCompare(attribute,"delay") == 0)
1326         {
1327           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1328           for ( ; image; image=image->next)
1329           {
1330             image->delay=(size_t) floor(geometry_info.rho+0.5);
1331             if ((flags & SigmaValue) != 0)
1332               image->ticks_per_second=(ssize_t)
1333                 floor(geometry_info.sigma+0.5);
1334           }
1335           break;
1336         }
1337       if (LocaleCompare(attribute,"disk-limit") == 0)
1338         {
1339           MagickSizeType
1340             limit;
1341
1342           limit=MagickResourceInfinity;
1343           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1344             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1345               100.0);
1346           (void) SetMagickResourceLimit(DiskResource,limit);
1347           break;
1348         }
1349       if (LocaleCompare(attribute,"density") == 0)
1350         {
1351           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1352             {
1353               ThrowPerlException(exception,OptionError,"MissingGeometry",
1354                 SvPV(sval,na));
1355               break;
1356             }
1357           if (info)
1358             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1359           for ( ; image; image=image->next)
1360           {
1361             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1362             image->resolution.x=geometry_info.rho;
1363             image->resolution.y=geometry_info.sigma;
1364             if ((flags & SigmaValue) == 0)
1365               image->resolution.y=image->resolution.x;
1366           }
1367           break;
1368         }
1369       if (LocaleCompare(attribute,"depth") == 0)
1370         {
1371           if (info)
1372             info->image_info->depth=SvIV(sval);
1373           for ( ; image; image=image->next)
1374             (void) SetImageDepth(image,SvIV(sval),exception);
1375           break;
1376         }
1377       if (LocaleCompare(attribute,"dispose") == 0)
1378         {
1379           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1380             SvPV(sval,na)) : SvIV(sval);
1381           if (sp < 0)
1382             {
1383               ThrowPerlException(exception,OptionError,
1384                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1385               break;
1386             }
1387           for ( ; image; image=image->next)
1388             image->dispose=(DisposeType) sp;
1389           break;
1390         }
1391       if (LocaleCompare(attribute,"dither") == 0)
1392         {
1393           if (info)
1394             {
1395               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1396                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1397               if (sp < 0)
1398                 {
1399                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1400                     SvPV(sval,na));
1401                   break;
1402                 }
1403               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1404             }
1405           break;
1406         }
1407       if (LocaleCompare(attribute,"display") == 0)
1408         {
1409           display:
1410           if (info)
1411             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1412           break;
1413         }
1414       if (info)
1415         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1416       for ( ; image; image=image->next)
1417         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1418       break;
1419     }
1420     case 'E':
1421     case 'e':
1422     {
1423       if (LocaleCompare(attribute,"endian") == 0)
1424         {
1425           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1426             SvPV(sval,na)) : SvIV(sval);
1427           if (sp < 0)
1428             {
1429               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1430                 SvPV(sval,na));
1431               break;
1432             }
1433           if (info)
1434             info->image_info->endian=(EndianType) sp;
1435           for ( ; image; image=image->next)
1436             image->endian=(EndianType) sp;
1437           break;
1438         }
1439       if (LocaleCompare(attribute,"extract") == 0)
1440         {
1441           /*
1442             Set image extract geometry.
1443           */
1444           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1445           break;
1446         }
1447       if (info)
1448         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1449       for ( ; image; image=image->next)
1450         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1451       break;
1452     }
1453     case 'F':
1454     case 'f':
1455     {
1456       if (LocaleCompare(attribute,"filename") == 0)
1457         {
1458           if (info)
1459             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1460               MaxTextExtent);
1461           for ( ; image; image=image->next)
1462             (void) CopyMagickString(image->filename,SvPV(sval,na),
1463               MaxTextExtent);
1464           break;
1465         }
1466       if (LocaleCompare(attribute,"file") == 0)
1467         {
1468           FILE
1469             *file;
1470
1471           PerlIO
1472             *io_info;
1473
1474           if (info == (struct PackageInfo *) NULL)
1475             break;
1476           io_info=IoIFP(sv_2io(sval));
1477           if (io_info == (PerlIO *) NULL)
1478             {
1479               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1480                 PackageName);
1481               break;
1482             }
1483           file=PerlIO_findFILE(io_info);
1484           if (file == (FILE *) NULL)
1485             {
1486               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1487                 PackageName);
1488               break;
1489             }
1490           SetImageInfoFile(info->image_info,file);
1491           break;
1492         }
1493       if (LocaleCompare(attribute,"fill") == 0)
1494         {
1495           if (info)
1496             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1497           break;
1498         }
1499       if (LocaleCompare(attribute,"font") == 0)
1500         {
1501           if (info)
1502             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1503           break;
1504         }
1505       if (LocaleCompare(attribute,"foreground") == 0)
1506         break;
1507       if (LocaleCompare(attribute,"fuzz") == 0)
1508         {
1509           if (info)
1510             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1511               QuantumRange+1.0);
1512           for ( ; image; image=image->next)
1513             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1514               QuantumRange+1.0);
1515           break;
1516         }
1517       if (info)
1518         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1519       for ( ; image; image=image->next)
1520         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1521       break;
1522     }
1523     case 'G':
1524     case 'g':
1525     {
1526       if (LocaleCompare(attribute,"gamma") == 0)
1527         {
1528           for ( ; image; image=image->next)
1529             image->gamma=SvNV(sval);
1530           break;
1531         }
1532       if (LocaleCompare(attribute,"gravity") == 0)
1533         {
1534           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1535             SvPV(sval,na)) : SvIV(sval);
1536           if (sp < 0)
1537             {
1538               ThrowPerlException(exception,OptionError,
1539                 "UnrecognizedGravityType",SvPV(sval,na));
1540               break;
1541             }
1542           if (info)
1543             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1544           for ( ; image; image=image->next)
1545             image->gravity=(GravityType) sp;
1546           break;
1547         }
1548       if (LocaleCompare(attribute,"green-primary") == 0)
1549         {
1550           for ( ; image; image=image->next)
1551           {
1552             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1553             image->chromaticity.green_primary.x=geometry_info.rho;
1554             image->chromaticity.green_primary.y=geometry_info.sigma;
1555             if ((flags & SigmaValue) == 0)
1556               image->chromaticity.green_primary.y=
1557                 image->chromaticity.green_primary.x;
1558           }
1559           break;
1560         }
1561       if (info)
1562         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1563       for ( ; image; image=image->next)
1564         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1565       break;
1566     }
1567     case 'I':
1568     case 'i':
1569     {
1570       if (LocaleNCompare(attribute,"index",5) == 0)
1571         {
1572           int
1573             items;
1574
1575           long
1576             index;
1577
1578           register Quantum
1579             *q;
1580
1581           CacheView
1582             *image_view;
1583
1584           for ( ; image; image=image->next)
1585           {
1586             if (image->storage_class != PseudoClass)
1587               continue;
1588             x=0;
1589             y=0;
1590             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1591             (void) items;
1592             image_view=AcquireAuthenticCacheView(image,exception);
1593             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1594             if (q != (Quantum *) NULL)
1595               {
1596                 items=sscanf(SvPV(sval,na),"%ld",&index);
1597                 if ((index >= 0) && (index < (ssize_t) image->colors))
1598                   SetPixelIndex(image,index,q);
1599                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1600               }
1601             image_view=DestroyCacheView(image_view);
1602           }
1603           break;
1604         }
1605       if (LocaleCompare(attribute,"iterations") == 0)
1606         {
1607   iterations:
1608           for ( ; image; image=image->next)
1609             image->iterations=SvIV(sval);
1610           break;
1611         }
1612       if (LocaleCompare(attribute,"interlace") == 0)
1613         {
1614           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1615             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1616           if (sp < 0)
1617             {
1618               ThrowPerlException(exception,OptionError,
1619                 "UnrecognizedInterlaceType",SvPV(sval,na));
1620               break;
1621             }
1622           if (info)
1623             info->image_info->interlace=(InterlaceType) sp;
1624           for ( ; image; image=image->next)
1625             image->interlace=(InterlaceType) sp;
1626           break;
1627         }
1628       if (info)
1629         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1630       for ( ; image; image=image->next)
1631         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1632       break;
1633     }
1634     case 'L':
1635     case 'l':
1636     {
1637       if (LocaleCompare(attribute,"label") == 0)
1638         {
1639           for ( ; image; image=image->next)
1640             (void) SetImageProperty(image,"label",InterpretImageProperties(
1641               info ? info->image_info : (ImageInfo *) NULL,image,
1642               SvPV(sval,na),exception),exception);
1643           break;
1644         }
1645       if (LocaleCompare(attribute,"loop") == 0)
1646         goto iterations;
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 'M':
1654     case 'm':
1655     {
1656       if (LocaleCompare(attribute,"magick") == 0)
1657         {
1658           if (info)
1659             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1660               "%s:",SvPV(sval,na));
1661           for ( ; image; image=image->next)
1662             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1663           break;
1664         }
1665       if (LocaleCompare(attribute,"map-limit") == 0)
1666         {
1667           MagickSizeType
1668             limit;
1669
1670           limit=MagickResourceInfinity;
1671           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1672             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1673               100.0);
1674           (void) SetMagickResourceLimit(MapResource,limit);
1675           break;
1676         }
1677       if (LocaleCompare(attribute,"mask") == 0)
1678         {
1679           Image
1680             *mask;
1681
1682           mask=(Image *) NULL;
1683           if (SvPOK(sval))
1684             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1685           for ( ; image; image=image->next)
1686             SetImageMask(image,mask,exception);
1687           break;
1688         }
1689       if (LocaleCompare(attribute,"mattecolor") == 0)
1690         {
1691           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1692             exception);
1693           if (info)
1694             info->image_info->matte_color=target_color;
1695           for ( ; image; image=image->next)
1696             image->matte_color=target_color;
1697           break;
1698         }
1699       if (LocaleCompare(attribute,"matte") == 0)
1700         {
1701           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1702             SvPV(sval,na)) : SvIV(sval);
1703           if (sp < 0)
1704             {
1705               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1706                 SvPV(sval,na));
1707               break;
1708             }
1709           for ( ; image; image=image->next)
1710             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1711           break;
1712         }
1713       if (LocaleCompare(attribute,"memory-limit") == 0)
1714         {
1715           MagickSizeType
1716             limit;
1717
1718           limit=MagickResourceInfinity;
1719           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1720             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1721               100.0);
1722           (void) SetMagickResourceLimit(MemoryResource,limit);
1723           break;
1724         }
1725       if (LocaleCompare(attribute,"monochrome") == 0)
1726         {
1727           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1728             SvPV(sval,na)) : SvIV(sval);
1729           if (sp < 0)
1730             {
1731               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1732                 SvPV(sval,na));
1733               break;
1734             }
1735           if (info)
1736             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1737           for ( ; image; image=image->next)
1738             (void) SetImageType(image,BilevelType,exception);
1739           break;
1740         }
1741       if (info)
1742         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1743       for ( ; image; image=image->next)
1744         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1745       break;
1746     }
1747     case 'O':
1748     case 'o':
1749     {
1750       if (LocaleCompare(attribute,"option") == 0)
1751         {
1752           if (info)
1753             DefineImageOption(info->image_info,SvPV(sval,na));
1754           break;
1755         }
1756       if (LocaleCompare(attribute,"orientation") == 0)
1757         {
1758           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1759             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1760           if (sp < 0)
1761             {
1762               ThrowPerlException(exception,OptionError,
1763                 "UnrecognizedOrientationType",SvPV(sval,na));
1764               break;
1765             }
1766           if (info)
1767             info->image_info->orientation=(OrientationType) sp;
1768           for ( ; image; image=image->next)
1769             image->orientation=(OrientationType) sp;
1770           break;
1771         }
1772       if (info)
1773         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1774       for ( ; image; image=image->next)
1775         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1776       break;
1777     }
1778     case 'P':
1779     case 'p':
1780     {
1781       if (LocaleCompare(attribute,"page") == 0)
1782         {
1783           char
1784             *geometry;
1785
1786           geometry=GetPageGeometry(SvPV(sval,na));
1787           if (info)
1788             (void) CloneString(&info->image_info->page,geometry);
1789           for ( ; image; image=image->next)
1790             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1791           geometry=(char *) RelinquishMagickMemory(geometry);
1792           break;
1793         }
1794       if (LocaleNCompare(attribute,"pixel",5) == 0)
1795         {
1796           int
1797             items;
1798
1799           PixelInfo
1800             pixel;
1801
1802           register Quantum
1803             *q;
1804
1805           CacheView
1806             *image_view;
1807
1808           for ( ; image; image=image->next)
1809           {
1810             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1811               break;
1812             x=0;
1813             y=0;
1814             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1815             (void) items;
1816             image_view=AcquireVirtualCacheView(image,exception);
1817             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1818             if (q != (Quantum *) NULL)
1819               {
1820                 if ((strchr(SvPV(sval,na),',') == 0) ||
1821                     (strchr(SvPV(sval,na),')') != 0))
1822                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1823                     &pixel,exception);
1824                 else
1825                   {
1826                     GetPixelInfo(image,&pixel);
1827                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1828                     pixel.red=geometry_info.rho;
1829                     if ((flags & SigmaValue) != 0)
1830                       pixel.green=geometry_info.sigma;
1831                     if ((flags & XiValue) != 0)
1832                       pixel.blue=geometry_info.xi;
1833                     if ((flags & PsiValue) != 0)
1834                       pixel.alpha=geometry_info.psi;
1835                     if ((flags & ChiValue) != 0)
1836                       pixel.black=geometry_info.chi;
1837                   }
1838                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1839                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1840                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1841                 if (image->colorspace == CMYKColorspace)
1842                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1843                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1844                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1845               }
1846             image_view=DestroyCacheView(image_view);
1847           }
1848           break;
1849         }
1850       if (LocaleCompare(attribute,"pointsize") == 0)
1851         {
1852           if (info)
1853             {
1854               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1855               info->image_info->pointsize=geometry_info.rho;
1856             }
1857           break;
1858         }
1859       if (LocaleCompare(attribute,"preview") == 0)
1860         {
1861           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1862             SvPV(sval,na)) : SvIV(sval);
1863           if (sp < 0)
1864             {
1865               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1866                 SvPV(sval,na));
1867               break;
1868             }
1869           if (info)
1870             info->image_info->preview_type=(PreviewType) sp;
1871           break;
1872         }
1873       if (info)
1874         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1875       for ( ; image; image=image->next)
1876         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1877       break;
1878     }
1879     case 'Q':
1880     case 'q':
1881     {
1882       if (LocaleCompare(attribute,"quality") == 0)
1883         {
1884           if (info)
1885             info->image_info->quality=SvIV(sval);
1886           for ( ; image; image=image->next)
1887             image->quality=SvIV(sval);
1888           break;
1889         }
1890       if (info)
1891         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1892       for ( ; image; image=image->next)
1893         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1894       break;
1895     }
1896     case 'R':
1897     case 'r':
1898     {
1899       if (LocaleCompare(attribute,"red-primary") == 0)
1900         {
1901           for ( ; image; image=image->next)
1902           {
1903             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1904             image->chromaticity.red_primary.x=geometry_info.rho;
1905             image->chromaticity.red_primary.y=geometry_info.sigma;
1906             if ((flags & SigmaValue) == 0)
1907               image->chromaticity.red_primary.y=
1908                 image->chromaticity.red_primary.x;
1909           }
1910           break;
1911         }
1912       if (LocaleCompare(attribute,"render") == 0)
1913         {
1914           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1915             SvPV(sval,na)) : SvIV(sval);
1916           if (sp < 0)
1917             {
1918               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1919                 SvPV(sval,na));
1920               break;
1921             }
1922          for ( ; image; image=image->next)
1923            image->rendering_intent=(RenderingIntent) sp;
1924          break;
1925        }
1926       if (LocaleCompare(attribute,"repage") == 0)
1927         {
1928           RectangleInfo
1929             geometry;
1930
1931           for ( ; image; image=image->next)
1932           {
1933             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1934             if ((flags & WidthValue) != 0)
1935               {
1936                 if ((flags & HeightValue) == 0)
1937                   geometry.height=geometry.width;
1938                 image->page.width=geometry.width;
1939                 image->page.height=geometry.height;
1940               }
1941             if ((flags & AspectValue) != 0)
1942               {
1943                 if ((flags & XValue) != 0)
1944                   image->page.x+=geometry.x;
1945                 if ((flags & YValue) != 0)
1946                   image->page.y+=geometry.y;
1947               }
1948             else
1949               {
1950                 if ((flags & XValue) != 0)
1951                   {
1952                     image->page.x=geometry.x;
1953                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1954                       image->page.width=image->columns+geometry.x;
1955                   }
1956                 if ((flags & YValue) != 0)
1957                   {
1958                     image->page.y=geometry.y;
1959                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1960                       image->page.height=image->rows+geometry.y;
1961                   }
1962               }
1963           }
1964           break;
1965         }
1966       if (info)
1967         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1968       for ( ; image; image=image->next)
1969         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1970       break;
1971     }
1972     case 'S':
1973     case 's':
1974     {
1975       if (LocaleCompare(attribute,"sampling-factor") == 0)
1976         {
1977           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1978             {
1979               ThrowPerlException(exception,OptionError,"MissingGeometry",
1980                 SvPV(sval,na));
1981               break;
1982             }
1983           if (info)
1984             (void) CloneString(&info->image_info->sampling_factor,
1985               SvPV(sval,na));
1986           break;
1987         }
1988       if (LocaleCompare(attribute,"scene") == 0)
1989         {
1990           for ( ; image; image=image->next)
1991             image->scene=SvIV(sval);
1992           break;
1993         }
1994       if (LocaleCompare(attribute,"server") == 0)
1995         goto display;
1996       if (LocaleCompare(attribute,"size") == 0)
1997         {
1998           if (info)
1999             {
2000               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2001                 {
2002                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2003                     SvPV(sval,na));
2004                   break;
2005                 }
2006               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2007             }
2008           break;
2009         }
2010       if (LocaleCompare(attribute,"stroke") == 0)
2011         {
2012           if (info)
2013             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2014           break;
2015         }
2016       if (info)
2017         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2018       for ( ; image; image=image->next)
2019         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2020       break;
2021     }
2022     case 'T':
2023     case 't':
2024     {
2025       if (LocaleCompare(attribute,"texture") == 0)
2026         {
2027           if (info)
2028             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2029           break;
2030         }
2031       if (LocaleCompare(attribute,"thread-limit") == 0)
2032         {
2033           MagickSizeType
2034             limit;
2035
2036           limit=MagickResourceInfinity;
2037           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2038             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2039               100.0);
2040           (void) SetMagickResourceLimit(ThreadResource,limit);
2041           break;
2042         }
2043       if (LocaleCompare(attribute,"tile-offset") == 0)
2044         {
2045           char
2046             *geometry;
2047
2048           geometry=GetPageGeometry(SvPV(sval,na));
2049           if (info)
2050             (void) CloneString(&info->image_info->page,geometry);
2051           for ( ; image; image=image->next)
2052             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2053               exception);
2054           geometry=(char *) RelinquishMagickMemory(geometry);
2055           break;
2056         }
2057       if (LocaleCompare(attribute,"time-limit") == 0)
2058         {
2059           MagickSizeType
2060             limit;
2061
2062           limit=MagickResourceInfinity;
2063           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2064             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2065               100.0);
2066           (void) SetMagickResourceLimit(TimeResource,limit);
2067           break;
2068         }
2069       if (LocaleCompare(attribute,"transparent-color") == 0)
2070         {
2071           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2072             exception);
2073           if (info)
2074             info->image_info->transparent_color=target_color;
2075           for ( ; image; image=image->next)
2076             image->transparent_color=target_color;
2077           break;
2078         }
2079       if (LocaleCompare(attribute,"type") == 0)
2080         {
2081           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2082             SvPV(sval,na)) : SvIV(sval);
2083           if (sp < 0)
2084             {
2085               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2086                 SvPV(sval,na));
2087               break;
2088             }
2089           if (info)
2090             info->image_info->type=(ImageType) sp;
2091           for ( ; image; image=image->next)
2092             SetImageType(image,(ImageType) sp,exception);
2093           break;
2094         }
2095       if (info)
2096         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2097       for ( ; image; image=image->next)
2098         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2099       break;
2100     }
2101     case 'U':
2102     case 'u':
2103     {
2104       if (LocaleCompare(attribute,"units") == 0)
2105         {
2106           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2107             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2108           if (sp < 0)
2109             {
2110               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2111                 SvPV(sval,na));
2112               break;
2113             }
2114           if (info)
2115             info->image_info->units=(ResolutionType) sp;
2116           for ( ; image; image=image->next)
2117           {
2118             ResolutionType
2119               units;
2120
2121             units=(ResolutionType) sp;
2122             if (image->units != units)
2123               switch (image->units)
2124               {
2125                 case UndefinedResolution:
2126                 case PixelsPerInchResolution:
2127                 {
2128                   if (units == PixelsPerCentimeterResolution)
2129                     {
2130                       image->resolution.x*=2.54;
2131                       image->resolution.y*=2.54;
2132                     }
2133                   break;
2134                 }
2135                 case PixelsPerCentimeterResolution:
2136                 {
2137                   if (units == PixelsPerInchResolution)
2138                     {
2139                       image->resolution.x/=2.54;
2140                       image->resolution.y/=2.54;
2141                     }
2142                   break;
2143                 }
2144               }
2145             image->units=units;
2146           }
2147           break;
2148         }
2149       if (info)
2150         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2151       for ( ; image; image=image->next)
2152         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2153       break;
2154     }
2155     case 'V':
2156     case 'v':
2157     {
2158       if (LocaleCompare(attribute,"verbose") == 0)
2159         {
2160           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2161             SvPV(sval,na)) : SvIV(sval);
2162           if (sp < 0)
2163             {
2164               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2165                 SvPV(sval,na));
2166               break;
2167             }
2168           if (info)
2169             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2170           break;
2171         }
2172       if (LocaleCompare(attribute,"view") == 0)
2173         {
2174           if (info)
2175             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2176           break;
2177         }
2178       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2179         {
2180           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2181             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2182           if (sp < 0)
2183             {
2184               ThrowPerlException(exception,OptionError,
2185                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2186               break;
2187             }
2188           for ( ; image; image=image->next)
2189             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2190           break;
2191         }
2192       if (info)
2193         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2194       for ( ; image; image=image->next)
2195         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2196       break;
2197     }
2198     case 'W':
2199     case 'w':
2200     {
2201       if (LocaleCompare(attribute,"white-point") == 0)
2202         {
2203           for ( ; image; image=image->next)
2204           {
2205             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2206             image->chromaticity.white_point.x=geometry_info.rho;
2207             image->chromaticity.white_point.y=geometry_info.sigma;
2208             if ((flags & SigmaValue) == 0)
2209               image->chromaticity.white_point.y=
2210                 image->chromaticity.white_point.x;
2211           }
2212           break;
2213         }
2214       if (info)
2215         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2216       for ( ; image; image=image->next)
2217         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2218       break;
2219     }
2220     default:
2221     {
2222       if (info)
2223         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2224       for ( ; image; image=image->next)
2225         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2226       break;
2227     }
2228   }
2229 }
2230 \f
2231 /*
2232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2233 %                                                                             %
2234 %                                                                             %
2235 %                                                                             %
2236 %   S e t u p L i s t                                                         %
2237 %                                                                             %
2238 %                                                                             %
2239 %                                                                             %
2240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2241 %
2242 %  Method SetupList returns the list of all the images linked by their
2243 %  image->next and image->previous link lists for use with ImageMagick.  If
2244 %  info is non-NULL, an info structure is returned in *info.  If
2245 %  reference_vector is non-NULL,an array of SV* are returned in
2246 %  *reference_vector.  Reference_vector is used when the images are going to be
2247 %  replaced with new Image*'s.
2248 %
2249 %  The format of the SetupList routine is:
2250 %
2251 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2252 %        SV ***reference_vector,ExceptionInfo *exception)
2253 %
2254 %  A description of each parameter follows:
2255 %
2256 %    o list: a list of strings.
2257 %
2258 %    o string: a character string.
2259 %
2260 %    o exception: Return any errors or warnings in this structure.
2261 %
2262 */
2263 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2264   SV ***reference_vector,ExceptionInfo *exception)
2265 {
2266   Image
2267     *image;
2268
2269   ssize_t
2270     current,
2271     last;
2272
2273   if (reference_vector)
2274     *reference_vector=NULL;
2275   if (info)
2276     *info=NULL;
2277   current=0;
2278   last=0;
2279   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2280   if (info && (SvTYPE(reference) == SVt_PVAV))
2281     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2282       exception);
2283   return(image);
2284 }
2285 \f
2286 /*
2287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2288 %                                                                             %
2289 %                                                                             %
2290 %                                                                             %
2291 %   s t r E Q c a s e                                                         %
2292 %                                                                             %
2293 %                                                                             %
2294 %                                                                             %
2295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2296 %
2297 %  strEQcase() compares two strings and returns 0 if they are the
2298 %  same or if the second string runs out first.  The comparison is case
2299 %  insensitive.
2300 %
2301 %  The format of the strEQcase routine is:
2302 %
2303 %      ssize_t strEQcase(const char *p,const char *q)
2304 %
2305 %  A description of each parameter follows:
2306 %
2307 %    o p: a character string.
2308 %
2309 %    o q: a character string.
2310 %
2311 %
2312 */
2313 static ssize_t strEQcase(const char *p,const char *q)
2314 {
2315   char
2316     c;
2317
2318   register ssize_t
2319     i;
2320
2321   for (i=0 ; (c=(*q)) != 0; i++)
2322   {
2323     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2324         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2325       return(0);
2326     p++;
2327     q++;
2328   }
2329   return(((*q == 0) && (*p == 0)) ? i : 0);
2330 }
2331 \f
2332 /*
2333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2334 %                                                                             %
2335 %                                                                             %
2336 %                                                                             %
2337 %   I m a g e : : M a g i c k                                                 %
2338 %                                                                             %
2339 %                                                                             %
2340 %                                                                             %
2341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2342 %
2343 %
2344 */
2345 MODULE = Image::Magick PACKAGE = Image::Magick
2346
2347 PROTOTYPES: ENABLE
2348
2349 BOOT:
2350   MagickCoreGenesis("PerlMagick",MagickFalse);
2351   SetWarningHandler(NULL);
2352   SetErrorHandler(NULL);
2353   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2354     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2355
2356 void
2357 UNLOAD()
2358   PPCODE:
2359   {
2360     if (magick_registry != (SplayTreeInfo *) NULL)
2361       magick_registry=DestroySplayTree(magick_registry);
2362     MagickCoreTerminus();
2363   }
2364
2365 double
2366 constant(name,argument)
2367   char *name
2368   ssize_t argument
2369 \f
2370 #
2371 ###############################################################################
2372 #                                                                             #
2373 #                                                                             #
2374 #                                                                             #
2375 #   A n i m a t e                                                             #
2376 #                                                                             #
2377 #                                                                             #
2378 #                                                                             #
2379 ###############################################################################
2380 #
2381 #
2382 void
2383 Animate(ref,...)
2384   Image::Magick ref=NO_INIT
2385   ALIAS:
2386     AnimateImage  = 1
2387     animate       = 2
2388     animateimage  = 3
2389   PPCODE:
2390   {
2391     ExceptionInfo
2392       *exception;
2393
2394     Image
2395       *image;
2396
2397     register ssize_t
2398       i;
2399
2400     struct PackageInfo
2401       *info,
2402       *package_info;
2403
2404     SV
2405       *perl_exception,
2406       *reference;
2407
2408     PERL_UNUSED_VAR(ref);
2409     PERL_UNUSED_VAR(ix);
2410     exception=AcquireExceptionInfo();
2411     perl_exception=newSVpv("",0);
2412     package_info=(struct PackageInfo *) NULL;
2413     if (sv_isobject(ST(0)) == 0)
2414       {
2415         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2416           PackageName);
2417         goto PerlException;
2418       }
2419     reference=SvRV(ST(0));
2420     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2421     if (image == (Image *) NULL)
2422       {
2423         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2424           PackageName);
2425         goto PerlException;
2426       }
2427     package_info=ClonePackageInfo(info,exception);
2428     if (items == 2)
2429       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2430     else
2431       if (items > 2)
2432         for (i=2; i < items; i+=2)
2433           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2434             exception);
2435     (void) AnimateImages(package_info->image_info,image,exception);
2436     (void) CatchImageException(image);
2437
2438   PerlException:
2439     if (package_info != (struct PackageInfo *) NULL)
2440       DestroyPackageInfo(package_info);
2441     InheritPerlException(exception,perl_exception);
2442     exception=DestroyExceptionInfo(exception);
2443     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2444     SvPOK_on(perl_exception);
2445     ST(0)=sv_2mortal(perl_exception);
2446     XSRETURN(1);
2447   }
2448 \f
2449 #
2450 ###############################################################################
2451 #                                                                             #
2452 #                                                                             #
2453 #                                                                             #
2454 #   A p p e n d                                                               #
2455 #                                                                             #
2456 #                                                                             #
2457 #                                                                             #
2458 ###############################################################################
2459 #
2460 #
2461 void
2462 Append(ref,...)
2463   Image::Magick ref=NO_INIT
2464   ALIAS:
2465     AppendImage  = 1
2466     append       = 2
2467     appendimage  = 3
2468   PPCODE:
2469   {
2470     AV
2471       *av;
2472
2473     char
2474       *attribute;
2475
2476     ExceptionInfo
2477       *exception;
2478
2479     HV
2480       *hv;
2481
2482     Image
2483       *image;
2484
2485     register ssize_t
2486       i;
2487
2488     ssize_t
2489       stack;
2490
2491     struct PackageInfo
2492       *info;
2493
2494     SV
2495       *av_reference,
2496       *perl_exception,
2497       *reference,
2498       *rv,
2499       *sv;
2500
2501     PERL_UNUSED_VAR(ref);
2502     PERL_UNUSED_VAR(ix);
2503     exception=AcquireExceptionInfo();
2504     perl_exception=newSVpv("",0);
2505     sv=NULL;
2506     attribute=NULL;
2507     av=NULL;
2508     if (sv_isobject(ST(0)) == 0)
2509       {
2510         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2511           PackageName);
2512         goto PerlException;
2513       }
2514     reference=SvRV(ST(0));
2515     hv=SvSTASH(reference);
2516     av=newAV();
2517     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2518     SvREFCNT_dec(av);
2519     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2520     if (image == (Image *) NULL)
2521       {
2522         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2523           PackageName);
2524         goto PerlException;
2525       }
2526     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2527     /*
2528       Get options.
2529     */
2530     stack=MagickTrue;
2531     for (i=2; i < items; i+=2)
2532     {
2533       attribute=(char *) SvPV(ST(i-1),na);
2534       switch (*attribute)
2535       {
2536         case 'S':
2537         case 's':
2538         {
2539           if (LocaleCompare(attribute,"stack") == 0)
2540             {
2541               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2542                 SvPV(ST(i),na));
2543               if (stack < 0)
2544                 {
2545                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2546                     SvPV(ST(i),na));
2547                   return;
2548                 }
2549               break;
2550             }
2551           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2552             attribute);
2553           break;
2554         }
2555         default:
2556         {
2557           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2558             attribute);
2559           break;
2560         }
2561       }
2562     }
2563     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2564     if (image == (Image *) NULL)
2565       goto PerlException;
2566     for ( ; image; image=image->next)
2567     {
2568       AddImageToRegistry(sv,image);
2569       rv=newRV(sv);
2570       av_push(av,sv_bless(rv,hv));
2571       SvREFCNT_dec(sv);
2572     }
2573     exception=DestroyExceptionInfo(exception);
2574     ST(0)=av_reference;
2575     SvREFCNT_dec(perl_exception);
2576     XSRETURN(1);
2577
2578   PerlException:
2579     InheritPerlException(exception,perl_exception);
2580     exception=DestroyExceptionInfo(exception);
2581     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2582     SvPOK_on(perl_exception);
2583     ST(0)=sv_2mortal(perl_exception);
2584     XSRETURN(1);
2585   }
2586 \f
2587 #
2588 ###############################################################################
2589 #                                                                             #
2590 #                                                                             #
2591 #                                                                             #
2592 #   A v e r a g e                                                             #
2593 #                                                                             #
2594 #                                                                             #
2595 #                                                                             #
2596 ###############################################################################
2597 #
2598 #
2599 void
2600 Average(ref)
2601   Image::Magick ref=NO_INIT
2602   ALIAS:
2603     AverageImage   = 1
2604     average        = 2
2605     averageimage   = 3
2606   PPCODE:
2607   {
2608     AV
2609       *av;
2610
2611     char
2612       *p;
2613
2614     ExceptionInfo
2615       *exception;
2616
2617     HV
2618       *hv;
2619
2620     Image
2621       *image;
2622
2623     struct PackageInfo
2624       *info;
2625
2626     SV
2627       *perl_exception,
2628       *reference,
2629       *rv,
2630       *sv;
2631
2632     PERL_UNUSED_VAR(ref);
2633     PERL_UNUSED_VAR(ix);
2634     exception=AcquireExceptionInfo();
2635     perl_exception=newSVpv("",0);
2636     sv=NULL;
2637     if (sv_isobject(ST(0)) == 0)
2638       {
2639         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2640           PackageName);
2641         goto PerlException;
2642       }
2643     reference=SvRV(ST(0));
2644     hv=SvSTASH(reference);
2645     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2646     if (image == (Image *) NULL)
2647       {
2648         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2649           PackageName);
2650         goto PerlException;
2651       }
2652     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2653     if (image == (Image *) NULL)
2654       goto PerlException;
2655     /*
2656       Create blessed Perl array for the returned image.
2657     */
2658     av=newAV();
2659     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2660     SvREFCNT_dec(av);
2661     AddImageToRegistry(sv,image);
2662     rv=newRV(sv);
2663     av_push(av,sv_bless(rv,hv));
2664     SvREFCNT_dec(sv);
2665     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2666     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2667       "average-%.*s",(int) (MaxTextExtent-9),
2668       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2669     (void) CopyMagickString(image->filename,info->image_info->filename,
2670       MaxTextExtent);
2671     SetImageInfo(info->image_info,0,exception);
2672     exception=DestroyExceptionInfo(exception);
2673     SvREFCNT_dec(perl_exception);
2674     XSRETURN(1);
2675
2676   PerlException:
2677     InheritPerlException(exception,perl_exception);
2678     exception=DestroyExceptionInfo(exception);
2679     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2680     SvPOK_on(perl_exception);
2681     ST(0)=sv_2mortal(perl_exception);
2682     XSRETURN(1);
2683   }
2684 \f
2685 #
2686 ###############################################################################
2687 #                                                                             #
2688 #                                                                             #
2689 #                                                                             #
2690 #   B l o b T o I m a g e                                                     #
2691 #                                                                             #
2692 #                                                                             #
2693 #                                                                             #
2694 ###############################################################################
2695 #
2696 #
2697 void
2698 BlobToImage(ref,...)
2699   Image::Magick ref=NO_INIT
2700   ALIAS:
2701     BlobToImage  = 1
2702     blobtoimage  = 2
2703     blobto       = 3
2704   PPCODE:
2705   {
2706     AV
2707       *av;
2708
2709     char
2710       **keep,
2711       **list;
2712
2713     ExceptionInfo
2714       *exception;
2715
2716     HV
2717       *hv;
2718
2719     Image
2720       *image;
2721
2722     register char
2723       **p;
2724
2725     register ssize_t
2726       i;
2727
2728     ssize_t
2729       ac,
2730       n,
2731       number_images;
2732
2733     STRLEN
2734       *length;
2735
2736     struct PackageInfo
2737       *info;
2738
2739     SV
2740       *perl_exception,
2741       *reference,
2742       *rv,
2743       *sv;
2744
2745     PERL_UNUSED_VAR(ref);
2746     PERL_UNUSED_VAR(ix);
2747     exception=AcquireExceptionInfo();
2748     perl_exception=newSVpv("",0);
2749     sv=NULL;
2750     number_images=0;
2751     ac=(items < 2) ? 1 : items-1;
2752     length=(STRLEN *) NULL;
2753     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2754     if (list == (char **) NULL)
2755       {
2756         ThrowPerlException(exception,ResourceLimitError,
2757           "MemoryAllocationFailed",PackageName);
2758         goto PerlException;
2759       }
2760     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2761     if (length == (STRLEN *) NULL)
2762       {
2763         ThrowPerlException(exception,ResourceLimitError,
2764           "MemoryAllocationFailed",PackageName);
2765         goto PerlException;
2766       }
2767     if (sv_isobject(ST(0)) == 0)
2768       {
2769         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2770           PackageName);
2771         goto PerlException;
2772       }
2773     reference=SvRV(ST(0));
2774     hv=SvSTASH(reference);
2775     if (SvTYPE(reference) != SVt_PVAV)
2776       {
2777         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2778           PackageName);
2779         goto PerlException;
2780       }
2781     av=(AV *) reference;
2782     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2783       exception);
2784     n=1;
2785     if (items <= 1)
2786       {
2787         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2788         goto PerlException;
2789       }
2790     for (n=0, i=0; i < ac; i++)
2791     {
2792       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2793       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2794         {
2795           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2796           continue;
2797         }
2798       n++;
2799     }
2800     list[n]=(char *) NULL;
2801     keep=list;
2802     for (i=number_images=0; i < n; i++)
2803     {
2804       image=BlobToImage(info->image_info,list[i],length[i],exception);
2805       if (image == (Image *) NULL)
2806         break;
2807       for ( ; image; image=image->next)
2808       {
2809         AddImageToRegistry(sv,image);
2810         rv=newRV(sv);
2811         av_push(av,sv_bless(rv,hv));
2812         SvREFCNT_dec(sv);
2813         number_images++;
2814       }
2815     }
2816     /*
2817       Free resources.
2818     */
2819     for (i=0; i < n; i++)
2820       if (list[i] != (char *) NULL)
2821         for (p=keep; list[i] != *p++; )
2822           if (*p == (char *) NULL)
2823             {
2824               list[i]=(char *) RelinquishMagickMemory(list[i]);
2825               break;
2826             }
2827
2828   PerlException:
2829     if (list)
2830       list=(char **) RelinquishMagickMemory(list);
2831     if (length)
2832       length=(STRLEN *) RelinquishMagickMemory(length);
2833     InheritPerlException(exception,perl_exception);
2834     exception=DestroyExceptionInfo(exception);
2835     sv_setiv(perl_exception,(IV) number_images);
2836     SvPOK_on(perl_exception);
2837     ST(0)=sv_2mortal(perl_exception);
2838     XSRETURN(1);
2839   }
2840 \f
2841 #
2842 ###############################################################################
2843 #                                                                             #
2844 #                                                                             #
2845 #                                                                             #
2846 #   C h a n n e l F x                                                         #
2847 #                                                                             #
2848 #                                                                             #
2849 #                                                                             #
2850 ###############################################################################
2851 #
2852 #
2853 void
2854 ChannelFx(ref,...)
2855   Image::Magick ref=NO_INIT
2856   ALIAS:
2857     ChannelFxImage  = 1
2858     channelfx       = 2
2859     channelfximage  = 3
2860   PPCODE:
2861   {
2862     AV
2863       *av;
2864
2865     char
2866       *attribute,
2867       expression[MaxTextExtent];
2868
2869     ChannelType
2870       channel,
2871       channel_mask;
2872
2873     ExceptionInfo
2874       *exception;
2875
2876     HV
2877       *hv;
2878
2879     Image
2880       *image;
2881
2882     register ssize_t
2883       i;
2884
2885     struct PackageInfo
2886       *info;
2887
2888     SV
2889       *av_reference,
2890       *perl_exception,
2891       *reference,
2892       *rv,
2893       *sv;
2894
2895     PERL_UNUSED_VAR(ref);
2896     PERL_UNUSED_VAR(ix);
2897     exception=AcquireExceptionInfo();
2898     perl_exception=newSVpv("",0);
2899     sv=NULL;
2900     attribute=NULL;
2901     av=NULL;
2902     if (sv_isobject(ST(0)) == 0)
2903       {
2904         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2905           PackageName);
2906         goto PerlException;
2907       }
2908     reference=SvRV(ST(0));
2909     hv=SvSTASH(reference);
2910     av=newAV();
2911     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2912     SvREFCNT_dec(av);
2913     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2914     if (image == (Image *) NULL)
2915       {
2916         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2917           PackageName);
2918         goto PerlException;
2919       }
2920     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2921     /*
2922       Get options.
2923     */
2924     channel=DefaultChannels;
2925     (void) CopyMagickString(expression,"u",MaxTextExtent);
2926     if (items == 2)
2927       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
2928     else
2929       for (i=2; i < items; i+=2)
2930       {
2931         attribute=(char *) SvPV(ST(i-1),na);
2932         switch (*attribute)
2933         {
2934           case 'C':
2935           case 'c':
2936           {
2937             if (LocaleCompare(attribute,"channel") == 0)
2938               {
2939                 ssize_t
2940                   option;
2941
2942                 option=ParseChannelOption(SvPV(ST(i),na));
2943                 if (option < 0)
2944                   {
2945                     ThrowPerlException(exception,OptionError,
2946                       "UnrecognizedType",SvPV(ST(i),na));
2947                     return;
2948                   }
2949                 channel=(ChannelType) option;
2950                 break;
2951               }
2952             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2953               attribute);
2954             break;
2955           }
2956           case 'E':
2957           case 'e':
2958           {
2959             if (LocaleCompare(attribute,"expression") == 0)
2960               {
2961                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2962                   MaxTextExtent);
2963                 break;
2964               }
2965             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2966               attribute);
2967             break;
2968           }
2969           default:
2970           {
2971             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2972               attribute);
2973             break;
2974           }
2975         }
2976       }
2977     channel_mask=SetImageChannelMask(image,channel);
2978     image=ChannelFxImage(image,expression,exception);
2979     if (image != (Image *) NULL)
2980       (void) SetImageChannelMask(image,channel_mask);
2981     if (image == (Image *) NULL)
2982       goto PerlException;
2983     for ( ; image; image=image->next)
2984     {
2985       AddImageToRegistry(sv,image);
2986       rv=newRV(sv);
2987       av_push(av,sv_bless(rv,hv));
2988       SvREFCNT_dec(sv);
2989     }
2990     exception=DestroyExceptionInfo(exception);
2991     ST(0)=av_reference;
2992     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
2993     XSRETURN(1);
2994
2995   PerlException:
2996     InheritPerlException(exception,perl_exception);
2997     exception=DestroyExceptionInfo(exception);
2998     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2999     SvPOK_on(perl_exception);
3000     ST(0)=sv_2mortal(perl_exception);
3001     XSRETURN(1);
3002   }
3003 \f
3004 #
3005 ###############################################################################
3006 #                                                                             #
3007 #                                                                             #
3008 #                                                                             #
3009 #   C l o n e                                                                 #
3010 #                                                                             #
3011 #                                                                             #
3012 #                                                                             #
3013 ###############################################################################
3014 #
3015 #
3016 void
3017 Clone(ref)
3018   Image::Magick ref=NO_INIT
3019   ALIAS:
3020     CopyImage   = 1
3021     copy        = 2
3022     copyimage   = 3
3023     CloneImage  = 4
3024     clone       = 5
3025     cloneimage  = 6
3026     Clone       = 7
3027   PPCODE:
3028   {
3029     AV
3030       *av;
3031
3032     ExceptionInfo
3033       *exception;
3034
3035     HV
3036       *hv;
3037
3038     Image
3039       *clone,
3040       *image;
3041
3042     struct PackageInfo
3043       *info;
3044
3045     SV
3046       *perl_exception,
3047       *reference,
3048       *rv,
3049       *sv;
3050
3051     PERL_UNUSED_VAR(ref);
3052     PERL_UNUSED_VAR(ix);
3053     exception=AcquireExceptionInfo();
3054     perl_exception=newSVpv("",0);
3055     sv=NULL;
3056     if (sv_isobject(ST(0)) == 0)
3057       {
3058         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3059           PackageName);
3060         goto PerlException;
3061       }
3062     reference=SvRV(ST(0));
3063     hv=SvSTASH(reference);
3064     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3065     if (image == (Image *) NULL)
3066       {
3067         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3068           PackageName);
3069         goto PerlException;
3070       }
3071     /*
3072       Create blessed Perl array for the returned image.
3073     */
3074     av=newAV();
3075     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3076     SvREFCNT_dec(av);
3077     for ( ; image; image=image->next)
3078     {
3079       clone=CloneImage(image,0,0,MagickTrue,exception);
3080       if (clone == (Image *) NULL)
3081         break;
3082       AddImageToRegistry(sv,clone);
3083       rv=newRV(sv);
3084       av_push(av,sv_bless(rv,hv));
3085       SvREFCNT_dec(sv);
3086     }
3087     exception=DestroyExceptionInfo(exception);
3088     SvREFCNT_dec(perl_exception);
3089     XSRETURN(1);
3090
3091   PerlException:
3092     InheritPerlException(exception,perl_exception);
3093     exception=DestroyExceptionInfo(exception);
3094     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3095     SvPOK_on(perl_exception);
3096     ST(0)=sv_2mortal(perl_exception);
3097     XSRETURN(1);
3098   }
3099 \f
3100 #
3101 ###############################################################################
3102 #                                                                             #
3103 #                                                                             #
3104 #                                                                             #
3105 #   C L O N E                                                                 #
3106 #                                                                             #
3107 #                                                                             #
3108 #                                                                             #
3109 ###############################################################################
3110 #
3111 #
3112 void
3113 CLONE(ref,...)
3114   SV *ref;
3115   CODE:
3116   {
3117     PERL_UNUSED_VAR(ref);
3118     if (magick_registry != (SplayTreeInfo *) NULL)
3119       {
3120         register Image
3121           *p;
3122
3123         ResetSplayTreeIterator(magick_registry);
3124         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3125         while (p != (Image *) NULL)
3126         {
3127           ReferenceImage(p);
3128           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3129         }
3130       }
3131   }
3132 \f
3133 #
3134 ###############################################################################
3135 #                                                                             #
3136 #                                                                             #
3137 #                                                                             #
3138 #   C o a l e s c e                                                           #
3139 #                                                                             #
3140 #                                                                             #
3141 #                                                                             #
3142 ###############################################################################
3143 #
3144 #
3145 void
3146 Coalesce(ref)
3147   Image::Magick ref=NO_INIT
3148   ALIAS:
3149     CoalesceImage   = 1
3150     coalesce        = 2
3151     coalesceimage   = 3
3152   PPCODE:
3153   {
3154     AV
3155       *av;
3156
3157     ExceptionInfo
3158       *exception;
3159
3160     HV
3161       *hv;
3162
3163     Image
3164       *image;
3165
3166     struct PackageInfo
3167       *info;
3168
3169     SV
3170       *av_reference,
3171       *perl_exception,
3172       *reference,
3173       *rv,
3174       *sv;
3175
3176     PERL_UNUSED_VAR(ref);
3177     PERL_UNUSED_VAR(ix);
3178     exception=AcquireExceptionInfo();
3179     perl_exception=newSVpv("",0);
3180     sv=NULL;
3181     if (sv_isobject(ST(0)) == 0)
3182       {
3183         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3184           PackageName);
3185         goto PerlException;
3186       }
3187     reference=SvRV(ST(0));
3188     hv=SvSTASH(reference);
3189     av=newAV();
3190     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3191     SvREFCNT_dec(av);
3192     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3193     if (image == (Image *) NULL)
3194       {
3195         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3196           PackageName);
3197         goto PerlException;
3198       }
3199     image=CoalesceImages(image,exception);
3200     if (image == (Image *) NULL)
3201       goto PerlException;
3202     for ( ; image; image=image->next)
3203     {
3204       AddImageToRegistry(sv,image);
3205       rv=newRV(sv);
3206       av_push(av,sv_bless(rv,hv));
3207       SvREFCNT_dec(sv);
3208     }
3209     exception=DestroyExceptionInfo(exception);
3210     ST(0)=av_reference;
3211     SvREFCNT_dec(perl_exception);
3212     XSRETURN(1);
3213
3214   PerlException:
3215     InheritPerlException(exception,perl_exception);
3216     exception=DestroyExceptionInfo(exception);
3217     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3218     SvPOK_on(perl_exception);
3219     ST(0)=sv_2mortal(perl_exception);
3220     XSRETURN(1);
3221   }
3222 \f
3223 #
3224 ###############################################################################
3225 #                                                                             #
3226 #                                                                             #
3227 #                                                                             #
3228 #   C o m p a r e                                                             #
3229 #                                                                             #
3230 #                                                                             #
3231 #                                                                             #
3232 ###############################################################################
3233 #
3234 #
3235 void
3236 Compare(ref,...)
3237   Image::Magick ref=NO_INIT
3238   ALIAS:
3239     CompareImages = 1
3240     compare      = 2
3241     compareimage = 3
3242   PPCODE:
3243   {
3244     AV
3245       *av;
3246
3247     char
3248       *attribute;
3249
3250     double
3251       distortion;
3252
3253     ExceptionInfo
3254       *exception;
3255
3256     HV
3257       *hv;
3258
3259     Image
3260       *difference_image,
3261       *image,
3262       *reconstruct_image;
3263
3264     MetricType
3265       metric;
3266
3267     register ssize_t
3268       i;
3269
3270     ssize_t
3271       option;
3272
3273     struct PackageInfo
3274       *info;
3275
3276     SV
3277       *av_reference,
3278       *perl_exception,
3279       *reference,
3280       *rv,
3281       *sv;
3282
3283     PERL_UNUSED_VAR(ref);
3284     PERL_UNUSED_VAR(ix);
3285     exception=AcquireExceptionInfo();
3286     perl_exception=newSVpv("",0);
3287     sv=NULL;
3288     av=NULL;
3289     attribute=NULL;
3290     if (sv_isobject(ST(0)) == 0)
3291       {
3292         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3293           PackageName);
3294         goto PerlException;
3295       }
3296     reference=SvRV(ST(0));
3297     hv=SvSTASH(reference);
3298     av=newAV();
3299     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3300     SvREFCNT_dec(av);
3301     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3302     if (image == (Image *) NULL)
3303       {
3304         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3305           PackageName);
3306         goto PerlException;
3307       }
3308     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3309     /*
3310       Get attribute.
3311     */
3312     reconstruct_image=image;
3313     metric=RootMeanSquaredErrorMetric;
3314     for (i=2; i < items; i+=2)
3315     {
3316       attribute=(char *) SvPV(ST(i-1),na);
3317       switch (*attribute)
3318       {
3319         case 'C':
3320         case 'c':
3321         {
3322           if (LocaleCompare(attribute,"channel") == 0)
3323             {
3324               ssize_t
3325                 option;
3326
3327               option=ParseChannelOption(SvPV(ST(i),na));
3328               if (option < 0)
3329                 {
3330                   ThrowPerlException(exception,OptionError,
3331                     "UnrecognizedType",SvPV(ST(i),na));
3332                   return;
3333                 }
3334               SetPixelChannelMask(image,(ChannelType) option);
3335               break;
3336             }
3337           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3338             attribute);
3339           break;
3340         }
3341         case 'F':
3342         case 'f':
3343         {
3344           if (LocaleCompare(attribute,"fuzz") == 0)
3345             {
3346               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3347               break;
3348             }
3349           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3350             attribute);
3351           break;
3352         }
3353         case 'I':
3354         case 'i':
3355         {
3356           if (LocaleCompare(attribute,"image") == 0)
3357             {
3358               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3359                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3360               break;
3361             }
3362           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3363             attribute);
3364           break;
3365         }
3366         case 'M':
3367         case 'm':
3368         {
3369           if (LocaleCompare(attribute,"metric") == 0)
3370             {
3371               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3372                 SvPV(ST(i),na));
3373               if (option < 0)
3374                 {
3375                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3376                     SvPV(ST(i),na));
3377                   break;
3378                 }
3379               metric=(MetricType) option;
3380               break;
3381             }
3382           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3383             attribute);
3384           break;
3385         }
3386         default:
3387         {
3388           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3389             attribute);
3390           break;
3391         }
3392       }
3393     }
3394     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3395       exception);
3396     if (difference_image != (Image *) NULL)
3397       {
3398         difference_image->error.mean_error_per_pixel=distortion;
3399         AddImageToRegistry(sv,difference_image);
3400         rv=newRV(sv);
3401         av_push(av,sv_bless(rv,hv));
3402         SvREFCNT_dec(sv);
3403       }
3404     exception=DestroyExceptionInfo(exception);
3405     ST(0)=av_reference;
3406     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3407     XSRETURN(1);
3408
3409   PerlException:
3410     InheritPerlException(exception,perl_exception);
3411     exception=DestroyExceptionInfo(exception);
3412     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3413     SvPOK_on(perl_exception);
3414     ST(0)=sv_2mortal(perl_exception);
3415     XSRETURN(1);
3416   }
3417 \f
3418 #
3419 ###############################################################################
3420 #                                                                             #
3421 #                                                                             #
3422 #                                                                             #
3423 #   C o m p l e x I m a g e s                                                 #
3424 #                                                                             #
3425 #                                                                             #
3426 #                                                                             #
3427 ###############################################################################
3428 #
3429 #
3430 void
3431 ComplexImages(ref)
3432   Image::Magick ref=NO_INIT
3433   ALIAS:
3434     ComplexImages   = 1
3435     compleximages   = 2
3436   PPCODE:
3437   {
3438     AV
3439       *av;
3440
3441     char
3442       *attribute,
3443       *p;
3444
3445     ComplexOperator
3446       op;
3447
3448     ExceptionInfo
3449       *exception;
3450
3451     HV
3452       *hv;
3453
3454     Image
3455       *image;
3456
3457     register ssize_t
3458       i;
3459
3460     struct PackageInfo
3461       *info;
3462
3463     SV
3464       *perl_exception,
3465       *reference,
3466       *rv,
3467       *sv;
3468
3469     PERL_UNUSED_VAR(ref);
3470     PERL_UNUSED_VAR(ix);
3471     exception=AcquireExceptionInfo();
3472     perl_exception=newSVpv("",0);
3473     sv=NULL;
3474     if (sv_isobject(ST(0)) == 0)
3475       {
3476         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3477           PackageName);
3478         goto PerlException;
3479       }
3480     reference=SvRV(ST(0));
3481     hv=SvSTASH(reference);
3482     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3483     if (image == (Image *) NULL)
3484       {
3485         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3486           PackageName);
3487         goto PerlException;
3488       }
3489     op=UndefinedComplexOperator;
3490     if (items == 2)
3491       {
3492         ssize_t
3493           in;
3494
3495         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3496           SvPV(ST(1),na));
3497         if (in < 0)
3498           {
3499             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3500               SvPV(ST(1),na));
3501             return;
3502           }
3503         op=(ComplexOperator) in;
3504       }
3505     else
3506       for (i=2; i < items; i+=2)
3507       {
3508         attribute=(char *) SvPV(ST(i-1),na);
3509         switch (*attribute)
3510         {
3511           case 'O':
3512           case 'o':
3513           {
3514             if (LocaleCompare(attribute,"operator") == 0)
3515               {
3516                 ssize_t
3517                   in;
3518
3519                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3520                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3521                 if (in < 0)
3522                   {
3523                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3524                       SvPV(ST(i),na));
3525                     return;
3526                   }
3527                 op=(ComplexOperator) in;
3528                 break;
3529               }
3530             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3531               attribute);
3532             break;
3533           }
3534           default:
3535           {
3536             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3537               attribute);
3538             break;
3539           }
3540         }
3541       }
3542     image=ComplexImages(image,op,exception);
3543     if (image == (Image *) NULL)
3544       goto PerlException;
3545     /*
3546       Create blessed Perl array for the returned image.
3547     */
3548     av=newAV();
3549     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3550     SvREFCNT_dec(av);
3551     AddImageToRegistry(sv,image);
3552     rv=newRV(sv);
3553     av_push(av,sv_bless(rv,hv));
3554     SvREFCNT_dec(sv);
3555     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3556     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3557       "complex-%.*s",(int) (MaxTextExtent-9),
3558       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3559     (void) CopyMagickString(image->filename,info->image_info->filename,
3560       MaxTextExtent);
3561     SetImageInfo(info->image_info,0,exception);
3562     exception=DestroyExceptionInfo(exception);
3563     SvREFCNT_dec(perl_exception);
3564     XSRETURN(1);
3565
3566   PerlException:
3567     InheritPerlException(exception,perl_exception);
3568     exception=DestroyExceptionInfo(exception);
3569     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3570     SvPOK_on(perl_exception);
3571     ST(0)=sv_2mortal(perl_exception);
3572     XSRETURN(1);
3573   }
3574 \f
3575 #
3576 ###############################################################################
3577 #                                                                             #
3578 #                                                                             #
3579 #                                                                             #
3580 #   C o m p a r e L a y e r s                                                 #
3581 #                                                                             #
3582 #                                                                             #
3583 #                                                                             #
3584 ###############################################################################
3585 #
3586 #
3587 void
3588 CompareLayers(ref)
3589   Image::Magick ref=NO_INIT
3590   ALIAS:
3591     CompareImagesLayers   = 1
3592     comparelayers        = 2
3593     compareimagelayers   = 3
3594   PPCODE:
3595   {
3596     AV
3597       *av;
3598
3599     char
3600       *attribute;
3601
3602     ExceptionInfo
3603       *exception;
3604
3605     HV
3606       *hv;
3607
3608     Image
3609       *image;
3610
3611     LayerMethod
3612       method;
3613
3614     register ssize_t
3615       i;
3616
3617     ssize_t
3618       option;
3619
3620     struct PackageInfo
3621       *info;
3622
3623     SV
3624       *av_reference,
3625       *perl_exception,
3626       *reference,
3627       *rv,
3628       *sv;
3629
3630     PERL_UNUSED_VAR(ref);
3631     PERL_UNUSED_VAR(ix);
3632     exception=AcquireExceptionInfo();
3633     perl_exception=newSVpv("",0);
3634     sv=NULL;
3635     if (sv_isobject(ST(0)) == 0)
3636       {
3637         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3638           PackageName);
3639         goto PerlException;
3640       }
3641     reference=SvRV(ST(0));
3642     hv=SvSTASH(reference);
3643     av=newAV();
3644     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3645     SvREFCNT_dec(av);
3646     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3647     if (image == (Image *) NULL)
3648       {
3649         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3650           PackageName);
3651         goto PerlException;
3652       }
3653     method=CompareAnyLayer;
3654     for (i=2; i < items; i+=2)
3655     {
3656       attribute=(char *) SvPV(ST(i-1),na);
3657       switch (*attribute)
3658       {
3659         case 'M':
3660         case 'm':
3661         {
3662           if (LocaleCompare(attribute,"method") == 0)
3663             {
3664               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3665                 SvPV(ST(i),na));
3666               if (option < 0)
3667                 {
3668                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3669                     SvPV(ST(i),na));
3670                   break;
3671                 }
3672                method=(LayerMethod) option;
3673               break;
3674             }
3675           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3676             attribute);
3677           break;
3678         }
3679         default:
3680         {
3681           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3682             attribute);
3683           break;
3684         }
3685       }
3686     }
3687     image=CompareImagesLayers(image,method,exception);
3688     if (image == (Image *) NULL)
3689       goto PerlException;
3690     for ( ; image; image=image->next)
3691     {
3692       AddImageToRegistry(sv,image);
3693       rv=newRV(sv);
3694       av_push(av,sv_bless(rv,hv));
3695       SvREFCNT_dec(sv);
3696     }
3697     exception=DestroyExceptionInfo(exception);
3698     ST(0)=av_reference;
3699     SvREFCNT_dec(perl_exception);
3700     XSRETURN(1);
3701
3702   PerlException:
3703     InheritPerlException(exception,perl_exception);
3704     exception=DestroyExceptionInfo(exception);
3705     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3706     SvPOK_on(perl_exception);
3707     ST(0)=sv_2mortal(perl_exception);
3708     XSRETURN(1);
3709   }
3710 \f
3711 #
3712 ###############################################################################
3713 #                                                                             #
3714 #                                                                             #
3715 #                                                                             #
3716 #   D e s t r o y                                                             #
3717 #                                                                             #
3718 #                                                                             #
3719 #                                                                             #
3720 ###############################################################################
3721 #
3722 #
3723 void
3724 DESTROY(ref)
3725   Image::Magick ref=NO_INIT
3726   PPCODE:
3727   {
3728     SV
3729       *reference;
3730
3731     PERL_UNUSED_VAR(ref);
3732     if (sv_isobject(ST(0)) == 0)
3733       croak("ReferenceIsNotMyType");
3734     reference=SvRV(ST(0));
3735     switch (SvTYPE(reference))
3736     {
3737       case SVt_PVAV:
3738       {
3739         char
3740           message[MaxTextExtent];
3741
3742         const SV
3743           *key;
3744
3745         HV
3746           *hv;
3747
3748         GV
3749           **gvp;
3750
3751         struct PackageInfo
3752           *info;
3753
3754         SV
3755           *sv;
3756
3757         /*
3758           Array (AV *) reference
3759         */
3760         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3761           XS_VERSION,reference);
3762         hv=gv_stashpv(PackageName, FALSE);
3763         if (!hv)
3764           break;
3765         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3766         if (!gvp)
3767           break;
3768         sv=GvSV(*gvp);
3769         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3770           {
3771             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3772             DestroyPackageInfo(info);
3773           }
3774         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3775         (void) key;
3776         break;
3777       }
3778       case SVt_PVMG:
3779       {
3780         Image
3781           *image;
3782
3783         /*
3784           Blessed scalar = (Image *) SvIV(reference)
3785         */
3786         image=INT2PTR(Image *,SvIV(reference));
3787         if (image != (Image *) NULL)
3788           DeleteImageFromRegistry(reference,image);
3789         break;
3790       }
3791       default:
3792         break;
3793     }
3794   }
3795 \f
3796 #
3797 ###############################################################################
3798 #                                                                             #
3799 #                                                                             #
3800 #                                                                             #
3801 #   D i s p l a y                                                             #
3802 #                                                                             #
3803 #                                                                             #
3804 #                                                                             #
3805 ###############################################################################
3806 #
3807 #
3808 void
3809 Display(ref,...)
3810   Image::Magick ref=NO_INIT
3811   ALIAS:
3812     DisplayImage  = 1
3813     display       = 2
3814     displayimage  = 3
3815   PPCODE:
3816   {
3817     ExceptionInfo
3818       *exception;
3819
3820     Image
3821       *image;
3822
3823     register ssize_t
3824       i;
3825
3826     struct PackageInfo
3827       *info,
3828       *package_info;
3829
3830     SV
3831       *perl_exception,
3832       *reference;
3833
3834     PERL_UNUSED_VAR(ref);
3835     PERL_UNUSED_VAR(ix);
3836     exception=AcquireExceptionInfo();
3837     perl_exception=newSVpv("",0);
3838     package_info=(struct PackageInfo *) NULL;
3839     if (sv_isobject(ST(0)) == 0)
3840       {
3841         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3842           PackageName);
3843         goto PerlException;
3844       }
3845     reference=SvRV(ST(0));
3846     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3847     if (image == (Image *) NULL)
3848       {
3849         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3850           PackageName);
3851         goto PerlException;
3852       }
3853     package_info=ClonePackageInfo(info,exception);
3854     if (items == 2)
3855       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3856     else
3857       if (items > 2)
3858         for (i=2; i < items; i+=2)
3859           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3860             exception);
3861     (void) DisplayImages(package_info->image_info,image,exception);
3862     (void) CatchImageException(image);
3863
3864   PerlException:
3865     if (package_info != (struct PackageInfo *) NULL)
3866       DestroyPackageInfo(package_info);
3867     InheritPerlException(exception,perl_exception);
3868     exception=DestroyExceptionInfo(exception);
3869     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3870     SvPOK_on(perl_exception);
3871     ST(0)=sv_2mortal(perl_exception);
3872     XSRETURN(1);
3873   }
3874 \f
3875 #
3876 ###############################################################################
3877 #                                                                             #
3878 #                                                                             #
3879 #                                                                             #
3880 #   E v a l u a t e I m a g e s                                               #
3881 #                                                                             #
3882 #                                                                             #
3883 #                                                                             #
3884 ###############################################################################
3885 #
3886 #
3887 void
3888 EvaluateImages(ref)
3889   Image::Magick ref=NO_INIT
3890   ALIAS:
3891     EvaluateImages   = 1
3892     evaluateimages   = 2
3893   PPCODE:
3894   {
3895     AV
3896       *av;
3897
3898     char
3899       *attribute,
3900       *p;
3901
3902     ExceptionInfo
3903       *exception;
3904
3905     HV
3906       *hv;
3907
3908     Image
3909       *image;
3910
3911     MagickEvaluateOperator
3912       op;
3913
3914     register ssize_t
3915       i;
3916
3917     struct PackageInfo
3918       *info;
3919
3920     SV
3921       *perl_exception,
3922       *reference,
3923       *rv,
3924       *sv;
3925
3926     PERL_UNUSED_VAR(ref);
3927     PERL_UNUSED_VAR(ix);
3928     exception=AcquireExceptionInfo();
3929     perl_exception=newSVpv("",0);
3930     sv=NULL;
3931     if (sv_isobject(ST(0)) == 0)
3932       {
3933         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3934           PackageName);
3935         goto PerlException;
3936       }
3937     reference=SvRV(ST(0));
3938     hv=SvSTASH(reference);
3939     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3940     if (image == (Image *) NULL)
3941       {
3942         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3943           PackageName);
3944         goto PerlException;
3945       }
3946     op=MeanEvaluateOperator;
3947     if (items == 2)
3948       {
3949         ssize_t
3950           in;
3951
3952         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3953           SvPV(ST(1),na));
3954         if (in < 0)
3955           {
3956             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3957               SvPV(ST(1),na));
3958             return;
3959           }
3960         op=(MagickEvaluateOperator) in;
3961       }
3962     else
3963       for (i=2; i < items; i+=2)
3964       {
3965         attribute=(char *) SvPV(ST(i-1),na);
3966         switch (*attribute)
3967         {
3968           case 'O':
3969           case 'o':
3970           {
3971             if (LocaleCompare(attribute,"operator") == 0)
3972               {
3973                 ssize_t
3974                   in;
3975
3976                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3977                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3978                 if (in < 0)
3979                   {
3980                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3981                       SvPV(ST(i),na));
3982                     return;
3983                   }
3984                 op=(MagickEvaluateOperator) in;
3985                 break;
3986               }
3987             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3988               attribute);
3989             break;
3990           }
3991           default:
3992           {
3993             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3994               attribute);
3995             break;
3996           }
3997         }
3998       }
3999     image=EvaluateImages(image,op,exception);
4000     if (image == (Image *) NULL)
4001       goto PerlException;
4002     /*
4003       Create blessed Perl array for the returned image.
4004     */
4005     av=newAV();
4006     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4007     SvREFCNT_dec(av);
4008     AddImageToRegistry(sv,image);
4009     rv=newRV(sv);
4010     av_push(av,sv_bless(rv,hv));
4011     SvREFCNT_dec(sv);
4012     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4013     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4014       "evaluate-%.*s",(int) (MaxTextExtent-9),
4015       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4016     (void) CopyMagickString(image->filename,info->image_info->filename,
4017       MaxTextExtent);
4018     SetImageInfo(info->image_info,0,exception);
4019     exception=DestroyExceptionInfo(exception);
4020     SvREFCNT_dec(perl_exception);
4021     XSRETURN(1);
4022
4023   PerlException:
4024     InheritPerlException(exception,perl_exception);
4025     exception=DestroyExceptionInfo(exception);
4026     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4027     SvPOK_on(perl_exception);
4028     ST(0)=sv_2mortal(perl_exception);
4029     XSRETURN(1);
4030   }
4031 \f
4032 #
4033 ###############################################################################
4034 #                                                                             #
4035 #                                                                             #
4036 #                                                                             #
4037 #   F e a t u r e s                                                           #
4038 #                                                                             #
4039 #                                                                             #
4040 #                                                                             #
4041 ###############################################################################
4042 #
4043 #
4044 void
4045 Features(ref,...)
4046   Image::Magick ref=NO_INIT
4047   ALIAS:
4048     FeaturesImage = 1
4049     features      = 2
4050     featuresimage = 3
4051   PPCODE:
4052   {
4053 #define ChannelFeatures(channel,direction) \
4054 { \
4055   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4056     channel_features[channel].angular_second_moment[direction]); \
4057   PUSHs(sv_2mortal(newSVpv(message,0))); \
4058   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4059     channel_features[channel].contrast[direction]); \
4060   PUSHs(sv_2mortal(newSVpv(message,0))); \
4061   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4062     channel_features[channel].contrast[direction]); \
4063   PUSHs(sv_2mortal(newSVpv(message,0))); \
4064   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4065     channel_features[channel].variance_sum_of_squares[direction]); \
4066   PUSHs(sv_2mortal(newSVpv(message,0))); \
4067   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4068     channel_features[channel].inverse_difference_moment[direction]); \
4069   PUSHs(sv_2mortal(newSVpv(message,0))); \
4070   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4071     channel_features[channel].sum_average[direction]); \
4072   PUSHs(sv_2mortal(newSVpv(message,0))); \
4073   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4074     channel_features[channel].sum_variance[direction]); \
4075   PUSHs(sv_2mortal(newSVpv(message,0))); \
4076   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4077     channel_features[channel].sum_entropy[direction]); \
4078   PUSHs(sv_2mortal(newSVpv(message,0))); \
4079   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4080     channel_features[channel].entropy[direction]); \
4081   PUSHs(sv_2mortal(newSVpv(message,0))); \
4082   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4083     channel_features[channel].difference_variance[direction]); \
4084   PUSHs(sv_2mortal(newSVpv(message,0))); \
4085   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4086     channel_features[channel].difference_entropy[direction]); \
4087   PUSHs(sv_2mortal(newSVpv(message,0))); \
4088   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4089     channel_features[channel].measure_of_correlation_1[direction]); \
4090   PUSHs(sv_2mortal(newSVpv(message,0))); \
4091   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4092     channel_features[channel].measure_of_correlation_2[direction]); \
4093   PUSHs(sv_2mortal(newSVpv(message,0))); \
4094   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
4095     channel_features[channel].maximum_correlation_coefficient[direction]); \
4096   PUSHs(sv_2mortal(newSVpv(message,0))); \
4097 }
4098
4099     AV
4100       *av;
4101
4102     char
4103       *attribute,
4104       message[MaxTextExtent];
4105
4106     ChannelFeatures
4107       *channel_features;
4108
4109     double
4110       distance;
4111
4112     ExceptionInfo
4113       *exception;
4114
4115     Image
4116       *image;
4117
4118     register ssize_t
4119       i;
4120
4121     ssize_t
4122       count;
4123
4124     struct PackageInfo
4125       *info;
4126
4127     SV
4128       *perl_exception,
4129       *reference;
4130
4131     PERL_UNUSED_VAR(ref);
4132     PERL_UNUSED_VAR(ix);
4133     exception=AcquireExceptionInfo();
4134     perl_exception=newSVpv("",0);
4135     av=NULL;
4136     if (sv_isobject(ST(0)) == 0)
4137       {
4138         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4139           PackageName);
4140         goto PerlException;
4141       }
4142     reference=SvRV(ST(0));
4143     av=newAV();
4144     SvREFCNT_dec(av);
4145     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4146     if (image == (Image *) NULL)
4147       {
4148         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4149           PackageName);
4150         goto PerlException;
4151       }
4152     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4153     distance=1;
4154     for (i=2; i < items; i+=2)
4155     {
4156       attribute=(char *) SvPV(ST(i-1),na);
4157       switch (*attribute)
4158       {
4159         case 'D':
4160         case 'd':
4161         {
4162           if (LocaleCompare(attribute,"distance") == 0)
4163             {
4164               distance=StringToLong((char *) SvPV(ST(1),na));
4165               break;
4166             }
4167           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4168             attribute);
4169           break;
4170         }
4171         default:
4172         {
4173           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4174             attribute);
4175           break;
4176         }
4177       }
4178     }
4179     count=0;
4180     for ( ; image; image=image->next)
4181     {
4182       channel_features=GetImageFeatures(image,distance,exception);
4183       if (channel_features == (ChannelFeatures *) NULL)
4184         continue;
4185       count++;
4186       EXTEND(sp,75*count);
4187       for (i=0; i < 4; i++)
4188       {
4189         ChannelFeatures(RedChannel,i);
4190         ChannelFeatures(GreenChannel,i);
4191         ChannelFeatures(BlueChannel,i);
4192         if (image->colorspace == CMYKColorspace)
4193           ChannelFeatures(BlackChannel,i);
4194         if (image->alpha_trait == BlendPixelTrait)
4195           ChannelFeatures(AlphaChannel,i);
4196       }
4197       channel_features=(ChannelFeatures *)
4198         RelinquishMagickMemory(channel_features);
4199     }
4200
4201   PerlException:
4202     InheritPerlException(exception,perl_exception);
4203     exception=DestroyExceptionInfo(exception);
4204     SvREFCNT_dec(perl_exception);
4205   }
4206 \f
4207 #
4208 ###############################################################################
4209 #                                                                             #
4210 #                                                                             #
4211 #                                                                             #
4212 #   F l a t t e n                                                             #
4213 #                                                                             #
4214 #                                                                             #
4215 #                                                                             #
4216 ###############################################################################
4217 #
4218 #
4219 void
4220 Flatten(ref)
4221   Image::Magick ref=NO_INIT
4222   ALIAS:
4223     FlattenImage   = 1
4224     flatten        = 2
4225     flattenimage   = 3
4226   PPCODE:
4227   {
4228     AV
4229       *av;
4230
4231     char
4232       *attribute,
4233       *p;
4234
4235     ExceptionInfo
4236       *exception;
4237
4238     HV
4239       *hv;
4240
4241     Image
4242       *image;
4243
4244     PixelInfo
4245       background_color;
4246
4247     register ssize_t
4248       i;
4249
4250     struct PackageInfo
4251       *info;
4252
4253     SV
4254       *perl_exception,
4255       *reference,
4256       *rv,
4257       *sv;
4258
4259     PERL_UNUSED_VAR(ref);
4260     PERL_UNUSED_VAR(ix);
4261     exception=AcquireExceptionInfo();
4262     perl_exception=newSVpv("",0);
4263     sv=NULL;
4264     if (sv_isobject(ST(0)) == 0)
4265       {
4266         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4267           PackageName);
4268         goto PerlException;
4269       }
4270     reference=SvRV(ST(0));
4271     hv=SvSTASH(reference);
4272     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4273     if (image == (Image *) NULL)
4274       {
4275         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4276           PackageName);
4277         goto PerlException;
4278       }
4279     background_color=image->background_color;
4280     if (items == 2)
4281       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4282         &background_color,exception);
4283     else
4284       for (i=2; i < items; i+=2)
4285       {
4286         attribute=(char *) SvPV(ST(i-1),na);
4287         switch (*attribute)
4288         {
4289           case 'B':
4290           case 'b':
4291           {
4292             if (LocaleCompare(attribute,"background") == 0)
4293               {
4294                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4295                   AllCompliance,&background_color,exception);
4296                 break;
4297               }
4298             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4299               attribute);
4300             break;
4301           }
4302           default:
4303           {
4304             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4305               attribute);
4306             break;
4307           }
4308         }
4309       }
4310     image->background_color=background_color;
4311     image=MergeImageLayers(image,FlattenLayer,exception);
4312     if (image == (Image *) NULL)
4313       goto PerlException;
4314     /*
4315       Create blessed Perl array for the returned image.
4316     */
4317     av=newAV();
4318     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4319     SvREFCNT_dec(av);
4320     AddImageToRegistry(sv,image);
4321     rv=newRV(sv);
4322     av_push(av,sv_bless(rv,hv));
4323     SvREFCNT_dec(sv);
4324     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4325     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4326       "flatten-%.*s",(int) (MaxTextExtent-9),
4327       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4328     (void) CopyMagickString(image->filename,info->image_info->filename,
4329       MaxTextExtent);
4330     SetImageInfo(info->image_info,0,exception);
4331     exception=DestroyExceptionInfo(exception);
4332     SvREFCNT_dec(perl_exception);
4333     XSRETURN(1);
4334
4335   PerlException:
4336     InheritPerlException(exception,perl_exception);
4337     exception=DestroyExceptionInfo(exception);
4338     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4339     SvPOK_on(perl_exception);  /* return messages in string context */
4340     ST(0)=sv_2mortal(perl_exception);
4341     XSRETURN(1);
4342   }
4343 \f
4344 #
4345 ###############################################################################
4346 #                                                                             #
4347 #                                                                             #
4348 #                                                                             #
4349 #   F x                                                                       #
4350 #                                                                             #
4351 #                                                                             #
4352 #                                                                             #
4353 ###############################################################################
4354 #
4355 #
4356 void
4357 Fx(ref,...)
4358   Image::Magick ref=NO_INIT
4359   ALIAS:
4360     FxImage  = 1
4361     fx       = 2
4362     fximage  = 3
4363   PPCODE:
4364   {
4365     AV
4366       *av;
4367
4368     char
4369       *attribute,
4370       expression[MaxTextExtent];
4371
4372     ChannelType
4373       channel,
4374       channel_mask;
4375
4376     ExceptionInfo
4377       *exception;
4378
4379     HV
4380       *hv;
4381
4382     Image
4383       *image;
4384
4385     register ssize_t
4386       i;
4387
4388     struct PackageInfo
4389       *info;
4390
4391     SV
4392       *av_reference,
4393       *perl_exception,
4394       *reference,
4395       *rv,
4396       *sv;
4397
4398     PERL_UNUSED_VAR(ref);
4399     PERL_UNUSED_VAR(ix);
4400     exception=AcquireExceptionInfo();
4401     perl_exception=newSVpv("",0);
4402     sv=NULL;
4403     attribute=NULL;
4404     av=NULL;
4405     if (sv_isobject(ST(0)) == 0)
4406       {
4407         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4408           PackageName);
4409         goto PerlException;
4410       }
4411     reference=SvRV(ST(0));
4412     hv=SvSTASH(reference);
4413     av=newAV();
4414     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4415     SvREFCNT_dec(av);
4416     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4417     if (image == (Image *) NULL)
4418       {
4419         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4420           PackageName);
4421         goto PerlException;
4422       }
4423     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4424     /*
4425       Get options.
4426     */
4427     channel=DefaultChannels;
4428     (void) CopyMagickString(expression,"u",MaxTextExtent);
4429     if (items == 2)
4430       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4431     else
4432       for (i=2; i < items; i+=2)
4433       {
4434         attribute=(char *) SvPV(ST(i-1),na);
4435         switch (*attribute)
4436         {
4437           case 'C':
4438           case 'c':
4439           {
4440             if (LocaleCompare(attribute,"channel") == 0)
4441               {
4442                 ssize_t
4443                   option;
4444
4445                 option=ParseChannelOption(SvPV(ST(i),na));
4446                 if (option < 0)
4447                   {
4448                     ThrowPerlException(exception,OptionError,
4449                       "UnrecognizedType",SvPV(ST(i),na));
4450                     return;
4451                   }
4452                 channel=(ChannelType) option;
4453                 break;
4454               }
4455             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4456               attribute);
4457             break;
4458           }
4459           case 'E':
4460           case 'e':
4461           {
4462             if (LocaleCompare(attribute,"expression") == 0)
4463               {
4464                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4465                   MaxTextExtent);
4466                 break;
4467               }
4468             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4469               attribute);
4470             break;
4471           }
4472           default:
4473           {
4474             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4475               attribute);
4476             break;
4477           }
4478         }
4479       }
4480     channel_mask=SetImageChannelMask(image,channel);
4481     image=FxImage(image,expression,exception);
4482     if (image != (Image *) NULL)
4483       (void) SetImageChannelMask(image,channel_mask);
4484     if (image == (Image *) NULL)
4485       goto PerlException;
4486     for ( ; image; image=image->next)
4487     {
4488       AddImageToRegistry(sv,image);
4489       rv=newRV(sv);
4490       av_push(av,sv_bless(rv,hv));
4491       SvREFCNT_dec(sv);
4492     }
4493     exception=DestroyExceptionInfo(exception);
4494     ST(0)=av_reference;
4495     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4496     XSRETURN(1);
4497
4498   PerlException:
4499     InheritPerlException(exception,perl_exception);
4500     exception=DestroyExceptionInfo(exception);
4501     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4502     SvPOK_on(perl_exception);
4503     ST(0)=sv_2mortal(perl_exception);
4504     XSRETURN(1);
4505   }
4506 \f
4507 #
4508 ###############################################################################
4509 #                                                                             #
4510 #                                                                             #
4511 #                                                                             #
4512 #   G e t                                                                     #
4513 #                                                                             #
4514 #                                                                             #
4515 #                                                                             #
4516 ###############################################################################
4517 #
4518 #
4519 void
4520 Get(ref,...)
4521   Image::Magick ref=NO_INIT
4522   ALIAS:
4523     GetAttributes = 1
4524     GetAttribute  = 2
4525     get           = 3
4526     getattributes = 4
4527     getattribute  = 5
4528   PPCODE:
4529   {
4530     char
4531       *attribute,
4532       color[MaxTextExtent];
4533
4534     const char
4535       *value;
4536
4537     ExceptionInfo
4538       *exception;
4539
4540     Image
4541       *image;
4542
4543     long
4544       j;
4545
4546     register ssize_t
4547       i;
4548
4549     struct PackageInfo
4550       *info;
4551
4552     SV
4553       *perl_exception,
4554       *reference,
4555       *s;
4556
4557     PERL_UNUSED_VAR(ref);
4558     PERL_UNUSED_VAR(ix);
4559     exception=AcquireExceptionInfo();
4560     perl_exception=newSVpv("",0);
4561     if (sv_isobject(ST(0)) == 0)
4562       {
4563         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4564           PackageName);
4565         XSRETURN_EMPTY;
4566       }
4567     reference=SvRV(ST(0));
4568     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4569     if (image == (Image *) NULL && !info)
4570       XSRETURN_EMPTY;
4571     EXTEND(sp,items);
4572     for (i=1; i < items; i++)
4573     {
4574       attribute=(char *) SvPV(ST(i),na);
4575       s=NULL;
4576       switch (*attribute)
4577       {
4578         case 'A':
4579         case 'a':
4580         {
4581           if (LocaleCompare(attribute,"adjoin") == 0)
4582             {
4583               if (info)
4584                 s=newSViv((ssize_t) info->image_info->adjoin);
4585               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4586               continue;
4587             }
4588           if (LocaleCompare(attribute,"antialias") == 0)
4589             {
4590               if (info)
4591                 s=newSViv((ssize_t) info->image_info->antialias);
4592               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4593               continue;
4594             }
4595           if (LocaleCompare(attribute,"area") == 0)
4596             {
4597               s=newSViv(GetMagickResource(AreaResource));
4598               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4599               continue;
4600             }
4601           if (LocaleCompare(attribute,"attenuate") == 0)
4602             {
4603               const char
4604                 *value;
4605
4606               value=GetImageProperty(image,attribute,exception);
4607               if (value != (const char *) NULL)
4608                 s=newSVpv(value,0);
4609               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4610               continue;
4611             }
4612           if (LocaleCompare(attribute,"authenticate") == 0)
4613             {
4614               if (info)
4615                 {
4616                   const char
4617                     *option;
4618
4619                   option=GetImageOption(info->image_info,attribute);
4620                   if (option != (const char *) NULL)
4621                     s=newSVpv(option,0);
4622                 }
4623               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4624               continue;
4625             }
4626           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4627             attribute);
4628           break;
4629         }
4630         case 'B':
4631         case 'b':
4632         {
4633           if (LocaleCompare(attribute,"background") == 0)
4634             {
4635               if (image == (Image *) NULL)
4636                 break;
4637               (void) FormatLocaleString(color,MaxTextExtent,
4638                 "%.20g,%.20g,%.20g,%.20g",image->background_color.red,
4639                 image->background_color.green,image->background_color.blue,
4640                 image->background_color.alpha);
4641               s=newSVpv(color,0);
4642               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4643               continue;
4644             }
4645           if (LocaleCompare(attribute,"base-columns") == 0)
4646             {
4647               if (image != (Image *) NULL)
4648                 s=newSViv((ssize_t) image->magick_columns);
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           if (LocaleCompare(attribute,"base-filename") == 0)
4653             {
4654               if (image != (Image *) NULL)
4655                 s=newSVpv(image->magick_filename,0);
4656               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4657               continue;
4658             }
4659           if (LocaleCompare(attribute,"base-height") == 0)
4660             {
4661               if (image != (Image *) NULL)
4662                 s=newSViv((ssize_t) image->magick_rows);
4663               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4664               continue;
4665             }
4666           if (LocaleCompare(attribute,"base-rows") == 0)
4667             {
4668               if (image != (Image *) NULL)
4669                 s=newSViv((ssize_t) image->magick_rows);
4670               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4671               continue;
4672             }
4673           if (LocaleCompare(attribute,"base-width") == 0)
4674             {
4675               if (image != (Image *) NULL)
4676                 s=newSViv((ssize_t) image->magick_columns);
4677               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4678               continue;
4679             }
4680           if (LocaleCompare(attribute,"blue-primary") == 0)
4681             {
4682               if (image == (Image *) NULL)
4683                 break;
4684               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4685                 image->chromaticity.blue_primary.x,
4686                 image->chromaticity.blue_primary.y);
4687               s=newSVpv(color,0);
4688               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4689               continue;
4690             }
4691           if (LocaleCompare(attribute,"bordercolor") == 0)
4692             {
4693               if (image == (Image *) NULL)
4694                 break;
4695               (void) FormatLocaleString(color,MaxTextExtent,
4696                 "%.20g,%.20g,%.20g,%.20g",image->border_color.red,
4697                 image->border_color.green,image->border_color.blue,
4698                 image->border_color.alpha);
4699               s=newSVpv(color,0);
4700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701               continue;
4702             }
4703           if (LocaleCompare(attribute,"bounding-box") == 0)
4704             {
4705               char
4706                 geometry[MaxTextExtent];
4707
4708               RectangleInfo
4709                 page;
4710
4711               if (image == (Image *) NULL)
4712                 break;
4713               page=GetImageBoundingBox(image,exception);
4714               (void) FormatLocaleString(geometry,MaxTextExtent,
4715                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4716                 page.height,(double) page.x,(double) page.y);
4717               s=newSVpv(geometry,0);
4718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4719               continue;
4720             }
4721           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4722             attribute);
4723           break;
4724         }
4725         case 'C':
4726         case 'c':
4727         {
4728           if (LocaleCompare(attribute,"class") == 0)
4729             {
4730               if (image == (Image *) NULL)
4731                 break;
4732               s=newSViv(image->storage_class);
4733               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4734                 image->storage_class));
4735               SvIOK_on(s);
4736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737               continue;
4738             }
4739           if (LocaleCompare(attribute,"clip-mask") == 0)
4740             {
4741               if (image != (Image *) NULL)
4742                 {
4743                   Image
4744                     *mask_image;
4745
4746                   SV
4747                     *sv;
4748
4749                   sv=NULL;
4750                   if (image->read_mask == MagickFalse)
4751                     ClipImage(image,exception);
4752                   mask_image=GetImageMask(image,exception);
4753                   if (mask_image != (Image *) NULL)
4754                     {
4755                       AddImageToRegistry(sv,mask_image);
4756                       s=sv_bless(newRV(sv),SvSTASH(reference));
4757                     }
4758                 }
4759               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4760               continue;
4761             }
4762           if (LocaleCompare(attribute,"clip-path") == 0)
4763             {
4764               if (image != (Image *) NULL)
4765                 {
4766                   Image
4767                     *mask_image;
4768
4769                   SV
4770                     *sv;
4771
4772                   sv=NULL;
4773                   if (image->read_mask != MagickFalse)
4774                     ClipImage(image,exception);
4775                   mask_image=GetImageMask(image,exception);
4776                   if (mask_image != (Image *) NULL)
4777                     {
4778                       AddImageToRegistry(sv,mask_image);
4779                       s=sv_bless(newRV(sv),SvSTASH(reference));
4780                     }
4781                 }
4782               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4783               continue;
4784             }
4785           if (LocaleCompare(attribute,"compression") == 0)
4786             {
4787               j=info ? info->image_info->compression : image ?
4788                 image->compression : UndefinedCompression;
4789               if (info)
4790                 if (info->image_info->compression == UndefinedCompression)
4791                   j=image->compression;
4792               s=newSViv(j);
4793               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4794                 j));
4795               SvIOK_on(s);
4796               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4797               continue;
4798             }
4799           if (LocaleCompare(attribute,"colorspace") == 0)
4800             {
4801               j=image ? image->colorspace : RGBColorspace;
4802               s=newSViv(j);
4803               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4804                 j));
4805               SvIOK_on(s);
4806               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4807               continue;
4808             }
4809           if (LocaleCompare(attribute,"colors") == 0)
4810             {
4811               if (image != (Image *) NULL)
4812                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4813                   exception));
4814               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4815               continue;
4816             }
4817           if (LocaleNCompare(attribute,"colormap",8) == 0)
4818             {
4819               int
4820                 items;
4821
4822               if (image == (Image *) NULL || !image->colormap)
4823                 break;
4824               j=0;
4825               items=sscanf(attribute,"%*[^[][%ld",&j);
4826               (void) items;
4827               if (j > (ssize_t) image->colors)
4828                 j%=image->colors;
4829               (void) FormatLocaleString(color,MaxTextExtent,
4830                 "%.20g,%.20g,%.20g,%.20g",image->colormap[j].red,
4831                 image->colormap[j].green,image->colormap[j].blue,
4832                 image->colormap[j].alpha);
4833               s=newSVpv(color,0);
4834               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4835               continue;
4836             }
4837           if (LocaleCompare(attribute,"columns") == 0)
4838             {
4839               if (image != (Image *) NULL)
4840                 s=newSViv((ssize_t) image->columns);
4841               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4842               continue;
4843             }
4844           if (LocaleCompare(attribute,"comment") == 0)
4845             {
4846               const char
4847                 *value;
4848
4849               value=GetImageProperty(image,attribute,exception);
4850               if (value != (const char *) NULL)
4851                 s=newSVpv(value,0);
4852               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4853               continue;
4854             }
4855           if (LocaleCompare(attribute,"copyright") == 0)
4856             {
4857               s=newSVpv(GetMagickCopyright(),0);
4858               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4859               continue;
4860             }
4861           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4862             attribute);
4863           break;
4864         }
4865         case 'D':
4866         case 'd':
4867         {
4868           if (LocaleCompare(attribute,"density") == 0)
4869             {
4870               char
4871                 geometry[MaxTextExtent];
4872
4873               if (image == (Image *) NULL)
4874                 break;
4875               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4876                 image->resolution.x,image->resolution.y);
4877               s=newSVpv(geometry,0);
4878               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4879               continue;
4880             }
4881           if (LocaleCompare(attribute,"delay") == 0)
4882             {
4883               if (image != (Image *) NULL)
4884                 s=newSViv((ssize_t) image->delay);
4885               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4886               continue;
4887             }
4888           if (LocaleCompare(attribute,"depth") == 0)
4889             {
4890               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4891               if (image != (Image *) NULL)
4892                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4893               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4894               continue;
4895             }
4896           if (LocaleCompare(attribute,"directory") == 0)
4897             {
4898               if (image && image->directory)
4899                 s=newSVpv(image->directory,0);
4900               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4901               continue;
4902             }
4903           if (LocaleCompare(attribute,"dispose") == 0)
4904             {
4905               if (image == (Image *) NULL)
4906                 break;
4907
4908               s=newSViv(image->dispose);
4909               (void) sv_setpv(s,
4910                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4911               SvIOK_on(s);
4912               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4913               continue;
4914             }
4915           if (LocaleCompare(attribute,"disk") == 0)
4916             {
4917               s=newSViv(GetMagickResource(DiskResource));
4918               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4919               continue;
4920             }
4921           if (LocaleCompare(attribute,"dither") == 0)
4922             {
4923               if (info)
4924                 s=newSViv((ssize_t) info->image_info->dither);
4925               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926               continue;
4927             }
4928           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4929             {
4930               if (info && info->image_info->server_name)
4931                 s=newSVpv(info->image_info->server_name,0);
4932               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4933               continue;
4934             }
4935           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4936             attribute);
4937           break;
4938         }
4939         case 'E':
4940         case 'e':
4941         {
4942           if (LocaleCompare(attribute,"elapsed-time") == 0)
4943             {
4944               if (image != (Image *) NULL)
4945                 s=newSVnv(GetElapsedTime(&image->timer));
4946               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4947               continue;
4948             }
4949           if (LocaleCompare(attribute,"endian") == 0)
4950             {
4951               j=info ? info->image_info->endian : image ? image->endian :
4952                 UndefinedEndian;
4953               s=newSViv(j);
4954               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4955               SvIOK_on(s);
4956               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4957               continue;
4958             }
4959           if (LocaleCompare(attribute,"error") == 0)
4960             {
4961               if (image != (Image *) NULL)
4962                 s=newSVnv(image->error.mean_error_per_pixel);
4963               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4964               continue;
4965             }
4966           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4967             attribute);
4968           break;
4969         }
4970         case 'F':
4971         case 'f':
4972         {
4973           if (LocaleCompare(attribute,"filesize") == 0)
4974             {
4975               if (image != (Image *) NULL)
4976                 s=newSViv((ssize_t) GetBlobSize(image));
4977               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4978               continue;
4979             }
4980           if (LocaleCompare(attribute,"filename") == 0)
4981             {
4982               if (info && info->image_info->filename &&
4983                   *info->image_info->filename)
4984                 s=newSVpv(info->image_info->filename,0);
4985               if (image != (Image *) NULL)
4986                 s=newSVpv(image->filename,0);
4987               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4988               continue;
4989             }
4990           if (LocaleCompare(attribute,"filter") == 0)
4991             {
4992               s=image ? newSViv(image->filter) : newSViv(0);
4993               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4994                 image->filter));
4995               SvIOK_on(s);
4996               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4997               continue;
4998             }
4999           if (LocaleCompare(attribute,"font") == 0)
5000             {
5001               if (info && info->image_info->font)
5002                 s=newSVpv(info->image_info->font,0);
5003               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5004               continue;
5005             }
5006           if (LocaleCompare(attribute,"foreground") == 0)
5007             continue;
5008           if (LocaleCompare(attribute,"format") == 0)
5009             {
5010               const MagickInfo
5011                 *magick_info;
5012
5013               magick_info=(const MagickInfo *) NULL;
5014               if (info && (*info->image_info->magick != '\0'))
5015                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5016               if (image != (Image *) NULL)
5017                 magick_info=GetMagickInfo(image->magick,exception);
5018               if ((magick_info != (const MagickInfo *) NULL) &&
5019                   (*magick_info->description != '\0'))
5020                 s=newSVpv((char *) magick_info->description,0);
5021               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5022               continue;
5023             }
5024           if (LocaleCompare(attribute,"fuzz") == 0)
5025             {
5026               if (info)
5027                 s=newSVnv(info->image_info->fuzz);
5028               if (image != (Image *) NULL)
5029                 s=newSVnv(image->fuzz);
5030               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5031               continue;
5032             }
5033           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5034             attribute);
5035           break;
5036         }
5037         case 'G':
5038         case 'g':
5039         {
5040           if (LocaleCompare(attribute,"gamma") == 0)
5041             {
5042               if (image != (Image *) NULL)
5043                 s=newSVnv(image->gamma);
5044               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5045               continue;
5046             }
5047           if (LocaleCompare(attribute,"geometry") == 0)
5048             {
5049               if (image && image->geometry)
5050                 s=newSVpv(image->geometry,0);
5051               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5052               continue;
5053             }
5054           if (LocaleCompare(attribute,"gravity") == 0)
5055             {
5056               s=image ? newSViv(image->gravity) : newSViv(0);
5057               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5058                 image->gravity));
5059               SvIOK_on(s);
5060               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5061               continue;
5062             }
5063           if (LocaleCompare(attribute,"green-primary") == 0)
5064             {
5065               if (image == (Image *) NULL)
5066                 break;
5067               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5068                 image->chromaticity.green_primary.x,
5069                 image->chromaticity.green_primary.y);
5070               s=newSVpv(color,0);
5071               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5072               continue;
5073             }
5074           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5075             attribute);
5076           break;
5077         }
5078         case 'H':
5079         case 'h':
5080         {
5081           if (LocaleCompare(attribute,"height") == 0)
5082             {
5083               if (image != (Image *) NULL)
5084                 s=newSViv((ssize_t) image->rows);
5085               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5086               continue;
5087             }
5088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5089             attribute);
5090           break;
5091         }
5092         case 'I':
5093         case 'i':
5094         {
5095           if (LocaleCompare(attribute,"icc") == 0)
5096             {
5097               if (image != (Image *) NULL)
5098                 {
5099                   const StringInfo
5100                     *profile;
5101
5102                   profile=GetImageProfile(image,"icc");
5103                   if (profile != (StringInfo *) NULL)
5104                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5105                       GetStringInfoLength(profile));
5106                 }
5107               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5108               continue;
5109             }
5110           if (LocaleCompare(attribute,"icm") == 0)
5111             {
5112               if (image != (Image *) NULL)
5113                 {
5114                   const StringInfo
5115                     *profile;
5116
5117                   profile=GetImageProfile(image,"icm");
5118                   if (profile != (const StringInfo *) NULL)
5119                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5120                       GetStringInfoLength(profile));
5121                 }
5122               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5123               continue;
5124             }
5125           if (LocaleCompare(attribute,"id") == 0)
5126             {
5127               if (image != (Image *) NULL)
5128                 {
5129                   char
5130                     key[MaxTextExtent];
5131
5132                   MagickBooleanType
5133                     status;
5134
5135                   static ssize_t
5136                     id = 0;
5137
5138                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
5139                     id);
5140                   status=SetImageRegistry(ImageRegistryType,key,image,
5141                     exception);
5142                   (void) status;
5143                   s=newSViv(id++);
5144                 }
5145               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5146               continue;
5147             }
5148           if (LocaleNCompare(attribute,"index",5) == 0)
5149             {
5150               char
5151                 name[MaxTextExtent];
5152
5153               int
5154                 items;
5155
5156               long
5157                 x,
5158                 y;
5159
5160               register const Quantum
5161                 *p;
5162
5163               CacheView
5164                 *image_view;
5165
5166               if (image == (Image *) NULL)
5167                 break;
5168               if (image->storage_class != PseudoClass)
5169                 break;
5170               x=0;
5171               y=0;
5172               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5173               (void) items;
5174               image_view=AcquireVirtualCacheView(image,exception);
5175               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5176               if (p != (const Quantum *) NULL)
5177                 {
5178                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
5179                     GetPixelIndex(image,p));
5180                   s=newSVpv(name,0);
5181                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5182                 }
5183               image_view=DestroyCacheView(image_view);
5184               continue;
5185             }
5186           if (LocaleCompare(attribute,"iptc") == 0)
5187             {
5188               if (image != (Image *) NULL)
5189                 {
5190                   const StringInfo
5191                     *profile;
5192
5193                   profile=GetImageProfile(image,"iptc");
5194                   if (profile != (const StringInfo *) NULL)
5195                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5196                       GetStringInfoLength(profile));
5197                 }
5198               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5199               continue;
5200             }
5201           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5202             {
5203               if (image != (Image *) NULL)
5204                 s=newSViv((ssize_t) image->iterations);
5205               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5206               continue;
5207             }
5208           if (LocaleCompare(attribute,"interlace") == 0)
5209             {
5210               j=info ? info->image_info->interlace : image ? image->interlace :
5211                 UndefinedInterlace;
5212               s=newSViv(j);
5213               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5214                 j));
5215               SvIOK_on(s);
5216               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5217               continue;
5218             }
5219           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5220             attribute);
5221           break;
5222         }
5223         case 'L':
5224         case 'l':
5225         {
5226           if (LocaleCompare(attribute,"label") == 0)
5227             {
5228               const char
5229                 *value;
5230
5231               if (image == (Image *) NULL)
5232                 break;
5233               value=GetImageProperty(image,"Label",exception);
5234               if (value != (const char *) NULL)
5235                 s=newSVpv(value,0);
5236               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5237               continue;
5238             }
5239           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5240             {
5241               if (image != (Image *) NULL)
5242                 s=newSViv((ssize_t) image->iterations);
5243               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5244               continue;
5245             }
5246           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5247             attribute);
5248           break;
5249         }
5250         case 'M':
5251         case 'm':
5252         {
5253           if (LocaleCompare(attribute,"magick") == 0)
5254             {
5255               if (info && *info->image_info->magick)
5256                 s=newSVpv(info->image_info->magick,0);
5257               if (image != (Image *) NULL)
5258                 s=newSVpv(image->magick,0);
5259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5260               continue;
5261             }
5262           if (LocaleCompare(attribute,"map") == 0)
5263             {
5264               s=newSViv(GetMagickResource(MapResource));
5265               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5266               continue;
5267             }
5268           if (LocaleCompare(attribute,"maximum-error") == 0)
5269             {
5270               if (image != (Image *) NULL)
5271                 s=newSVnv(image->error.normalized_maximum_error);
5272               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5273               continue;
5274             }
5275           if (LocaleCompare(attribute,"memory") == 0)
5276             {
5277               s=newSViv(GetMagickResource(MemoryResource));
5278               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5279               continue;
5280             }
5281           if (LocaleCompare(attribute,"mean-error") == 0)
5282             {
5283               if (image != (Image *) NULL)
5284                 s=newSVnv(image->error.normalized_mean_error);
5285               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5286               continue;
5287             }
5288           if (LocaleCompare(attribute,"mime") == 0)
5289             {
5290               if (info && *info->image_info->magick)
5291                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5292               if (image != (Image *) NULL)
5293                 s=newSVpv(MagickToMime(image->magick),0);
5294               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5295               continue;
5296             }
5297           if (LocaleCompare(attribute,"mattecolor") == 0)
5298             {
5299               if (image == (Image *) NULL)
5300                 break;
5301               (void) FormatLocaleString(color,MaxTextExtent,
5302                 "%.20g,%.20g,%.20g,%.20g",image->matte_color.red,
5303                 image->matte_color.green,image->matte_color.blue,
5304                 image->matte_color.alpha);
5305               s=newSVpv(color,0);
5306               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5307               continue;
5308             }
5309           if (LocaleCompare(attribute,"matte") == 0)
5310             {
5311               if (image != (Image *) NULL)
5312                 s=newSViv((ssize_t) image->alpha_trait == BlendPixelTrait ?
5313                   1 : 0);
5314               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5315               continue;
5316             }
5317           if (LocaleCompare(attribute,"mime") == 0)
5318             {
5319               const char
5320                 *magick;
5321
5322               magick=NULL;
5323               if (info && *info->image_info->magick)
5324                 magick=info->image_info->magick;
5325               if (image != (Image *) NULL)
5326                 magick=image->magick;
5327               if (magick)
5328                 {
5329                   char
5330                     *mime;
5331
5332                   mime=MagickToMime(magick);
5333                   s=newSVpv(mime,0);
5334                   mime=(char *) RelinquishMagickMemory(mime);
5335                 }
5336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5337               continue;
5338             }
5339           if (LocaleCompare(attribute,"monochrome") == 0)
5340             {
5341               if (image == (Image *) NULL)
5342                 continue;
5343               j=info ? info->image_info->monochrome :
5344                 IsImageMonochrome(image,exception);
5345               s=newSViv(j);
5346               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5347               continue;
5348             }
5349           if (LocaleCompare(attribute,"montage") == 0)
5350             {
5351               if (image && image->montage)
5352                 s=newSVpv(image->montage,0);
5353               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5354               continue;
5355             }
5356           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5357             attribute);
5358           break;
5359         }
5360         case 'O':
5361         case 'o':
5362         {
5363           if (LocaleCompare(attribute,"orientation") == 0)
5364             {
5365               j=info ? info->image_info->orientation : image ?
5366                 image->orientation : UndefinedOrientation;
5367               s=newSViv(j);
5368               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5369                 j));
5370               SvIOK_on(s);
5371               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5372               continue;
5373             }
5374           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5375             attribute);
5376           break;
5377         }
5378         case 'P':
5379         case 'p':
5380         {
5381           if (LocaleCompare(attribute,"page") == 0)
5382             {
5383               if (info && info->image_info->page)
5384                 s=newSVpv(info->image_info->page,0);
5385               if (image != (Image *) NULL)
5386                 {
5387                   char
5388                     geometry[MaxTextExtent];
5389
5390                   (void) FormatLocaleString(geometry,MaxTextExtent,
5391                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5392                     (double) image->page.height,(double) image->page.x,(double)
5393                     image->page.y);
5394                   s=newSVpv(geometry,0);
5395                 }
5396               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5397               continue;
5398             }
5399           if (LocaleCompare(attribute,"page.x") == 0)
5400             {
5401               if (image != (Image *) NULL)
5402                 s=newSViv((ssize_t) image->page.x);
5403               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5404               continue;
5405             }
5406           if (LocaleCompare(attribute,"page.y") == 0)
5407             {
5408               if (image != (Image *) NULL)
5409                 s=newSViv((ssize_t) image->page.y);
5410               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5411               continue;
5412             }
5413           if (LocaleNCompare(attribute,"pixel",5) == 0)
5414             {
5415               char
5416                 tuple[MaxTextExtent];
5417
5418               int
5419                 items;
5420
5421               long
5422                 x,
5423                 y;
5424
5425               register const Quantum
5426                 *p;
5427
5428               if (image == (Image *) NULL)
5429                 break;
5430               x=0;
5431               y=0;
5432               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5433               (void) items;
5434               p=GetVirtualPixels(image,x,y,1,1,exception);
5435               if (image->colorspace != CMYKColorspace)
5436                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5437                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5438                   GetPixelRed(image,p),GetPixelGreen(image,p),
5439                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5440               else
5441                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5442                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5443                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5444                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5445                   GetPixelAlpha(image,p));
5446               s=newSVpv(tuple,0);
5447               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5448               continue;
5449             }
5450           if (LocaleCompare(attribute,"pointsize") == 0)
5451             {
5452               if (info)
5453                 s=newSViv((ssize_t) info->image_info->pointsize);
5454               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5455               continue;
5456             }
5457           if (LocaleCompare(attribute,"preview") == 0)
5458             {
5459               s=newSViv(info->image_info->preview_type);
5460               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5461                 info->image_info->preview_type));
5462               SvIOK_on(s);
5463               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5464               continue;
5465             }
5466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5467             attribute);
5468           break;
5469         }
5470         case 'Q':
5471         case 'q':
5472         {
5473           if (LocaleCompare(attribute,"quality") == 0)
5474             {
5475               if (info)
5476                 s=newSViv((ssize_t) info->image_info->quality);
5477               if (image != (Image *) NULL)
5478                 s=newSViv((ssize_t) image->quality);
5479               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5480               continue;
5481             }
5482           if (LocaleCompare(attribute,"quantum") == 0)
5483             {
5484               if (info)
5485                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5486               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5487               continue;
5488             }
5489           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5490             attribute);
5491           break;
5492         }
5493         case 'R':
5494         case 'r':
5495         {
5496           if (LocaleCompare(attribute,"rendering-intent") == 0)
5497             {
5498               s=newSViv(image->rendering_intent);
5499               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5500                 image->rendering_intent));
5501               SvIOK_on(s);
5502               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5503               continue;
5504             }
5505           if (LocaleCompare(attribute,"red-primary") == 0)
5506             {
5507               if (image == (Image *) NULL)
5508                 break;
5509               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5510                 image->chromaticity.red_primary.x,
5511                 image->chromaticity.red_primary.y);
5512               s=newSVpv(color,0);
5513               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5514               continue;
5515             }
5516           if (LocaleCompare(attribute,"rows") == 0)
5517             {
5518               if (image != (Image *) NULL)
5519                 s=newSViv((ssize_t) image->rows);
5520               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5521               continue;
5522             }
5523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5524             attribute);
5525           break;
5526         }
5527         case 'S':
5528         case 's':
5529         {
5530           if (LocaleCompare(attribute,"sampling-factor") == 0)
5531             {
5532               if (info && info->image_info->sampling_factor)
5533                 s=newSVpv(info->image_info->sampling_factor,0);
5534               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5535               continue;
5536             }
5537           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5538             {
5539               if (info && info->image_info->server_name)
5540                 s=newSVpv(info->image_info->server_name,0);
5541               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5542               continue;
5543             }
5544           if (LocaleCompare(attribute,"size") == 0)
5545             {
5546               if (info && info->image_info->size)
5547                 s=newSVpv(info->image_info->size,0);
5548               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5549               continue;
5550             }
5551           if (LocaleCompare(attribute,"scene") == 0)
5552             {
5553               if (image != (Image *) NULL)
5554                 s=newSViv((ssize_t) image->scene);
5555               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5556               continue;
5557             }
5558           if (LocaleCompare(attribute,"scenes") == 0)
5559             {
5560               if (image != (Image *) NULL)
5561                 s=newSViv((ssize_t) info->image_info->number_scenes);
5562               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5563               continue;
5564             }
5565           if (LocaleCompare(attribute,"signature") == 0)
5566             {
5567               const char
5568                 *value;
5569
5570               if (image == (Image *) NULL)
5571                 break;
5572               (void) SignatureImage(image,exception);
5573               value=GetImageProperty(image,"Signature",exception);
5574               if (value != (const char *) NULL)
5575                 s=newSVpv(value,0);
5576               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5577               continue;
5578             }
5579           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5580             attribute);
5581           break;
5582         }
5583         case 'T':
5584         case 't':
5585         {
5586           if (LocaleCompare(attribute,"taint") == 0)
5587             {
5588               if (image != (Image *) NULL)
5589                 s=newSViv((ssize_t) IsTaintImage(image));
5590               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5591               continue;
5592             }
5593           if (LocaleCompare(attribute,"texture") == 0)
5594             {
5595               if (info && info->image_info->texture)
5596                 s=newSVpv(info->image_info->texture,0);
5597               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5598               continue;
5599             }
5600           if (LocaleCompare(attribute,"total-ink-density") == 0)
5601             {
5602               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5603               if (image != (Image *) NULL)
5604                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5605               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5606               continue;
5607             }
5608           if (LocaleCompare(attribute,"transparent-color") == 0)
5609             {
5610               if (image == (Image *) NULL)
5611                 break;
5612               (void) FormatLocaleString(color,MaxTextExtent,
5613                 "%.20g,%.20g,%.20g,%.20g",image->transparent_color.red,
5614                 image->transparent_color.green,image->transparent_color.blue,
5615                 image->transparent_color.alpha);
5616               s=newSVpv(color,0);
5617               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5618               continue;
5619             }
5620           if (LocaleCompare(attribute,"type") == 0)
5621             {
5622               if (image == (Image *) NULL)
5623                 break;
5624               j=(ssize_t) GetImageType(image,exception);
5625               s=newSViv(j);
5626               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5627               SvIOK_on(s);
5628               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5629               continue;
5630             }
5631           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5632             attribute);
5633           break;
5634         }
5635         case 'U':
5636         case 'u':
5637         {
5638           if (LocaleCompare(attribute,"units") == 0)
5639             {
5640               j=info ? info->image_info->units : image ? image->units :
5641                 UndefinedResolution;
5642               if (info && (info->image_info->units == UndefinedResolution))
5643                 if (image)
5644                   j=image->units;
5645               if (j == UndefinedResolution)
5646                 s=newSVpv("undefined units",0);
5647               else
5648                 if (j == PixelsPerInchResolution)
5649                   s=newSVpv("pixels / inch",0);
5650                 else
5651                   s=newSVpv("pixels / centimeter",0);
5652               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5653               continue;
5654             }
5655           if (LocaleCompare(attribute,"user-time") == 0)
5656             {
5657               if (image != (Image *) NULL)
5658                 s=newSVnv(GetUserTime(&image->timer));
5659               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5660               continue;
5661             }
5662           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5663             attribute);
5664           break;
5665         }
5666         case 'V':
5667         case 'v':
5668         {
5669           if (LocaleCompare(attribute,"verbose") == 0)
5670             {
5671               if (info)
5672                 s=newSViv((ssize_t) info->image_info->verbose);
5673               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5674               continue;
5675             }
5676           if (LocaleCompare(attribute,"version") == 0)
5677             {
5678               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5679               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5680               continue;
5681             }
5682           if (LocaleCompare(attribute,"view") == 0)
5683             {
5684               if (info && info->image_info->view)
5685                 s=newSVpv(info->image_info->view,0);
5686               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5687               continue;
5688             }
5689           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5690             {
5691               if (image == (Image *) NULL)
5692                 break;
5693               j=(ssize_t) GetImageVirtualPixelMethod(image);
5694               s=newSViv(j);
5695               (void) sv_setpv(s,CommandOptionToMnemonic(
5696                 MagickVirtualPixelOptions,j));
5697               SvIOK_on(s);
5698               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5699               continue;
5700             }
5701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5702             attribute);
5703           break;
5704         }
5705         case 'W':
5706         case 'w':
5707         {
5708           if (LocaleCompare(attribute,"white-point") == 0)
5709             {
5710               if (image == (Image *) NULL)
5711                 break;
5712               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5713                 image->chromaticity.white_point.x,
5714                 image->chromaticity.white_point.y);
5715               s=newSVpv(color,0);
5716               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5717               continue;
5718             }
5719           if (LocaleCompare(attribute,"width") == 0)
5720             {
5721               if (image != (Image *) NULL)
5722                 s=newSViv((ssize_t) image->columns);
5723               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5724               continue;
5725             }
5726           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5727              attribute);
5728           break;
5729         }
5730         case 'X':
5731         case 'x':
5732         {
5733           if (LocaleCompare(attribute,"x-resolution") == 0)
5734             {
5735               if (image != (Image *) NULL)
5736                 s=newSVnv(image->resolution.x);
5737               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5738               continue;
5739             }
5740           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5741             attribute);
5742           break;
5743         }
5744         case 'Y':
5745         case 'y':
5746         {
5747           if (LocaleCompare(attribute,"y-resolution") == 0)
5748             {
5749               if (image != (Image *) NULL)
5750                 s=newSVnv(image->resolution.y);
5751               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5752               continue;
5753             }
5754           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5755             attribute);
5756           break;
5757         }
5758         default:
5759           break;
5760       }
5761       if (image == (Image *) NULL)
5762         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5763           attribute)
5764       else
5765         {
5766           value=GetImageProperty(image,attribute,exception);
5767           if (value != (const char *) NULL)
5768             {
5769               s=newSVpv(value,0);
5770               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5771             }
5772           else
5773             if (*attribute != '%')
5774               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5775                 attribute)
5776             else
5777               {
5778                  char
5779                    *meta;
5780
5781                  meta=InterpretImageProperties(info ? info->image_info :
5782                    (ImageInfo *) NULL,image,attribute,exception);
5783                  s=newSVpv(meta,0);
5784                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5785                  meta=(char *) RelinquishMagickMemory(meta);
5786               }
5787         }
5788     }
5789     exception=DestroyExceptionInfo(exception);
5790     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5791   }
5792 \f
5793 #
5794 ###############################################################################
5795 #                                                                             #
5796 #                                                                             #
5797 #                                                                             #
5798 #   G e t A u t h e n t i c P i x e l s                                       #
5799 #                                                                             #
5800 #                                                                             #
5801 #                                                                             #
5802 ###############################################################################
5803 #
5804 #
5805 void *
5806 GetAuthenticPixels(ref,...)
5807   Image::Magick ref = NO_INIT
5808   ALIAS:
5809     getauthenticpixels = 1
5810     GetImagePixels = 2
5811     getimagepixels = 3
5812   CODE:
5813   {
5814     char
5815       *attribute;
5816
5817     ExceptionInfo
5818       *exception;
5819
5820     Image
5821       *image;
5822
5823     RectangleInfo
5824       region;
5825
5826     ssize_t
5827       i;
5828
5829     struct PackageInfo
5830       *info;
5831
5832     SV
5833       *perl_exception,
5834       *reference;
5835
5836     void
5837       *blob = NULL;
5838
5839     PERL_UNUSED_VAR(ref);
5840     PERL_UNUSED_VAR(ix);
5841     exception=AcquireExceptionInfo();
5842     perl_exception=newSVpv("",0);
5843     if (sv_isobject(ST(0)) == 0)
5844       {
5845         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5846           PackageName);
5847         goto PerlException;
5848       }
5849     reference=SvRV(ST(0));
5850
5851     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5852     if (image == (Image *) NULL)
5853       {
5854         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5855           PackageName);
5856         goto PerlException;
5857       }
5858
5859     region.x=0;
5860     region.y=0;
5861     region.width=image->columns;
5862     region.height=1;
5863     if (items == 1)
5864       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5865     for (i=2; i < items; i+=2)
5866     {
5867       attribute=(char *) SvPV(ST(i-1),na);
5868       switch (*attribute)
5869       {
5870         case 'g':
5871         case 'G':
5872         {
5873           if (LocaleCompare(attribute,"geometry") == 0)
5874             {
5875               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5876               break;
5877             }
5878           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5879             attribute);
5880           break;
5881         }
5882         case 'H':
5883         case 'h':
5884         {
5885           if (LocaleCompare(attribute,"height") == 0)
5886             {
5887               region.height=SvIV(ST(i));
5888               continue;
5889             }
5890           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5891             attribute);
5892           break;
5893         }
5894         case 'X':
5895         case 'x':
5896         {
5897           if (LocaleCompare(attribute,"x") == 0)
5898             {
5899               region.x=SvIV(ST(i));
5900               continue;
5901             }
5902           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5903             attribute);
5904           break;
5905         }
5906         case 'Y':
5907         case 'y':
5908         {
5909           if (LocaleCompare(attribute,"y") == 0)
5910             {
5911               region.y=SvIV(ST(i));
5912               continue;
5913             }
5914           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5915             attribute);
5916           break;
5917         }
5918         case 'W':
5919         case 'w':
5920         {
5921           if (LocaleCompare(attribute,"width") == 0)
5922             {
5923               region.width=SvIV(ST(i));
5924               continue;
5925             }
5926           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5927             attribute);
5928           break;
5929         }
5930       }
5931     }
5932     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5933       region.height,exception);
5934     if (blob != (void *) NULL)
5935       goto PerlEnd;
5936
5937   PerlException:
5938     InheritPerlException(exception,perl_exception);
5939     exception=DestroyExceptionInfo(exception);
5940     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5941
5942   PerlEnd:
5943     RETVAL = blob;
5944   }
5945   OUTPUT:
5946     RETVAL
5947 \f
5948 #
5949 ###############################################################################
5950 #                                                                             #
5951 #                                                                             #
5952 #                                                                             #
5953 #   G e t V i r t u a l P i x e l s                                           #
5954 #                                                                             #
5955 #                                                                             #
5956 #                                                                             #
5957 ###############################################################################
5958 #
5959 #
5960 void *
5961 GetVirtualPixels(ref,...)
5962   Image::Magick ref = NO_INIT
5963   ALIAS:
5964     getvirtualpixels = 1
5965     AcquireImagePixels = 2
5966     acquireimagepixels = 3
5967   CODE:
5968   {
5969     char
5970       *attribute;
5971
5972     const void
5973       *blob = NULL;
5974
5975     ExceptionInfo
5976       *exception;
5977
5978     Image
5979       *image;
5980
5981     RectangleInfo
5982       region;
5983
5984     ssize_t
5985       i;
5986
5987     struct PackageInfo
5988       *info;
5989
5990     SV
5991       *perl_exception,
5992       *reference;
5993
5994     PERL_UNUSED_VAR(ref);
5995     PERL_UNUSED_VAR(ix);
5996     exception=AcquireExceptionInfo();
5997     perl_exception=newSVpv("",0);
5998     if (sv_isobject(ST(0)) == 0)
5999       {
6000         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6001           PackageName);
6002         goto PerlException;
6003       }
6004     reference=SvRV(ST(0));
6005
6006     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6007     if (image == (Image *) NULL)
6008       {
6009         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6010           PackageName);
6011         goto PerlException;
6012       }
6013
6014     region.x=0;
6015     region.y=0;
6016     region.width=image->columns;
6017     region.height=1;
6018     if (items == 1)
6019       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6020     for (i=2; i < items; i+=2)
6021     {
6022       attribute=(char *) SvPV(ST(i-1),na);
6023       switch (*attribute)
6024       {
6025         case 'g':
6026         case 'G':
6027         {
6028           if (LocaleCompare(attribute,"geometry") == 0)
6029             {
6030               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6031               break;
6032             }
6033           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6034             attribute);
6035           break;
6036         }
6037         case 'H':
6038         case 'h':
6039         {
6040           if (LocaleCompare(attribute,"height") == 0)
6041             {
6042               region.height=SvIV(ST(i));
6043               continue;
6044             }
6045           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6046             attribute);
6047           break;
6048         }
6049         case 'X':
6050         case 'x':
6051         {
6052           if (LocaleCompare(attribute,"x") == 0)
6053             {
6054               region.x=SvIV(ST(i));
6055               continue;
6056             }
6057           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6058             attribute);
6059           break;
6060         }
6061         case 'Y':
6062         case 'y':
6063         {
6064           if (LocaleCompare(attribute,"y") == 0)
6065             {
6066               region.y=SvIV(ST(i));
6067               continue;
6068             }
6069           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6070             attribute);
6071           break;
6072         }
6073         case 'W':
6074         case 'w':
6075         {
6076           if (LocaleCompare(attribute,"width") == 0)
6077             {
6078               region.width=SvIV(ST(i));
6079               continue;
6080             }
6081           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6082             attribute);
6083           break;
6084         }
6085       }
6086     }
6087     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6088       region.height,exception);
6089     if (blob != (void *) NULL)
6090       goto PerlEnd;
6091
6092   PerlException:
6093     InheritPerlException(exception,perl_exception);
6094     exception=DestroyExceptionInfo(exception);
6095     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6096
6097   PerlEnd:
6098     RETVAL = (void *) blob;
6099   }
6100   OUTPUT:
6101     RETVAL
6102 \f
6103 #
6104 ###############################################################################
6105 #                                                                             #
6106 #                                                                             #
6107 #                                                                             #
6108 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6109 #                                                                             #
6110 #                                                                             #
6111 #                                                                             #
6112 ###############################################################################
6113 #
6114 #
6115 void *
6116 GetAuthenticMetacontent(ref,...)
6117   Image::Magick ref = NO_INIT
6118   ALIAS:
6119     getauthenticmetacontent = 1
6120     GetMetacontent = 2
6121     getmetacontent = 3
6122   CODE:
6123   {
6124     ExceptionInfo
6125       *exception;
6126
6127     Image
6128       *image;
6129
6130     struct PackageInfo
6131       *info;
6132
6133     SV
6134       *perl_exception,
6135       *reference;
6136
6137     void
6138       *blob = NULL;
6139
6140     PERL_UNUSED_VAR(ref);
6141     PERL_UNUSED_VAR(ix);
6142     exception=AcquireExceptionInfo();
6143     perl_exception=newSVpv("",0);
6144     if (sv_isobject(ST(0)) == 0)
6145       {
6146         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6147           PackageName);
6148         goto PerlException;
6149       }
6150     reference=SvRV(ST(0));
6151
6152     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6153     if (image == (Image *) NULL)
6154       {
6155         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6156           PackageName);
6157         goto PerlException;
6158       }
6159
6160     blob=(void *) GetAuthenticMetacontent(image);
6161     if (blob != (void *) NULL)
6162       goto PerlEnd;
6163
6164   PerlException:
6165     InheritPerlException(exception,perl_exception);
6166     exception=DestroyExceptionInfo(exception);
6167     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6168
6169   PerlEnd:
6170     RETVAL = blob;
6171   }
6172   OUTPUT:
6173     RETVAL
6174 \f
6175 #
6176 ###############################################################################
6177 #                                                                             #
6178 #                                                                             #
6179 #                                                                             #
6180 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6181 #                                                                             #
6182 #                                                                             #
6183 #                                                                             #
6184 ###############################################################################
6185 #
6186 #
6187 void *
6188 GetVirtualMetacontent(ref,...)
6189   Image::Magick ref = NO_INIT
6190   ALIAS:
6191     getvirtualmetacontent = 1
6192   CODE:
6193   {
6194     ExceptionInfo
6195       *exception;
6196
6197     Image
6198       *image;
6199
6200     struct PackageInfo
6201       *info;
6202
6203     SV
6204       *perl_exception,
6205       *reference;
6206
6207     void
6208       *blob = NULL;
6209
6210     PERL_UNUSED_VAR(ref);
6211     PERL_UNUSED_VAR(ix);
6212     exception=AcquireExceptionInfo();
6213     perl_exception=newSVpv("",0);
6214     if (sv_isobject(ST(0)) == 0)
6215       {
6216         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6217           PackageName);
6218         goto PerlException;
6219       }
6220     reference=SvRV(ST(0));
6221
6222     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6223     if (image == (Image *) NULL)
6224       {
6225         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6226           PackageName);
6227         goto PerlException;
6228       }
6229
6230     blob=(void *) GetVirtualMetacontent(image);
6231     if (blob != (void *) NULL)
6232       goto PerlEnd;
6233
6234   PerlException:
6235     InheritPerlException(exception,perl_exception);
6236     exception=DestroyExceptionInfo(exception);
6237     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6238
6239   PerlEnd:
6240     RETVAL = blob;
6241   }
6242   OUTPUT:
6243     RETVAL
6244 \f
6245 #
6246 ###############################################################################
6247 #                                                                             #
6248 #                                                                             #
6249 #                                                                             #
6250 #   H i s t o g r a m                                                         #
6251 #                                                                             #
6252 #                                                                             #
6253 #                                                                             #
6254 ###############################################################################
6255 #
6256 #
6257 void
6258 Histogram(ref,...)
6259   Image::Magick ref=NO_INIT
6260   ALIAS:
6261     HistogramImage = 1
6262     histogram      = 2
6263     histogramimage = 3
6264   PPCODE:
6265   {
6266     AV
6267       *av;
6268
6269     char
6270       message[MaxTextExtent];
6271
6272     PixelInfo
6273       *histogram;
6274
6275     ExceptionInfo
6276       *exception;
6277
6278     Image
6279       *image;
6280
6281     register ssize_t
6282       i;
6283
6284     ssize_t
6285       count;
6286
6287     struct PackageInfo
6288       *info;
6289
6290     SV
6291       *perl_exception,
6292       *reference;
6293
6294     size_t
6295       number_colors;
6296
6297     PERL_UNUSED_VAR(ref);
6298     PERL_UNUSED_VAR(ix);
6299     exception=AcquireExceptionInfo();
6300     perl_exception=newSVpv("",0);
6301     av=NULL;
6302     if (sv_isobject(ST(0)) == 0)
6303       {
6304         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6305           PackageName);
6306         goto PerlException;
6307       }
6308     reference=SvRV(ST(0));
6309     av=newAV();
6310     SvREFCNT_dec(av);
6311     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6312     if (image == (Image *) NULL)
6313       {
6314         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6315           PackageName);
6316         goto PerlException;
6317       }
6318     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
6319     count=0;
6320     for ( ; image; image=image->next)
6321     {
6322       histogram=GetImageHistogram(image,&number_colors,exception);
6323       if (histogram == (PixelInfo *) NULL)
6324         continue;
6325       count+=(ssize_t) number_colors;
6326       EXTEND(sp,6*count);
6327       for (i=0; i < (ssize_t) number_colors; i++)
6328       {
6329         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6330           histogram[i].red);
6331         PUSHs(sv_2mortal(newSVpv(message,0)));
6332         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6333           histogram[i].green);
6334         PUSHs(sv_2mortal(newSVpv(message,0)));
6335         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6336           histogram[i].blue);
6337         PUSHs(sv_2mortal(newSVpv(message,0)));
6338         if (image->colorspace == CMYKColorspace)
6339           {
6340             (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6341               histogram[i].black);
6342             PUSHs(sv_2mortal(newSVpv(message,0)));
6343           }
6344         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",
6345           histogram[i].alpha);
6346         PUSHs(sv_2mortal(newSVpv(message,0)));
6347         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6348           histogram[i].count);
6349         PUSHs(sv_2mortal(newSVpv(message,0)));
6350       }
6351       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6352     }
6353
6354   PerlException:
6355     InheritPerlException(exception,perl_exception);
6356     exception=DestroyExceptionInfo(exception);
6357     SvREFCNT_dec(perl_exception);
6358   }
6359 \f
6360 #
6361 ###############################################################################
6362 #                                                                             #
6363 #                                                                             #
6364 #                                                                             #
6365 #   G e t P i x e l                                                           #
6366 #                                                                             #
6367 #                                                                             #
6368 #                                                                             #
6369 ###############################################################################
6370 #
6371 #
6372 void
6373 GetPixel(ref,...)
6374   Image::Magick ref=NO_INIT
6375   ALIAS:
6376     getpixel = 1
6377     getPixel = 2
6378   PPCODE:
6379   {
6380     AV
6381       *av;
6382
6383     char
6384       *attribute;
6385
6386     ExceptionInfo
6387       *exception;
6388
6389     Image
6390       *image;
6391
6392     MagickBooleanType
6393       normalize;
6394
6395     RectangleInfo
6396       region;
6397
6398     register const Quantum
6399       *p;
6400
6401     register ssize_t
6402       i;
6403
6404     ssize_t
6405       option;
6406
6407     struct PackageInfo
6408       *info;
6409
6410     SV
6411       *perl_exception,
6412       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6413
6414     PERL_UNUSED_VAR(ref);
6415     PERL_UNUSED_VAR(ix);
6416     exception=AcquireExceptionInfo();
6417     perl_exception=newSVpv("",0);
6418     reference=SvRV(ST(0));
6419     av=(AV *) reference;
6420     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6421       exception);
6422     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6423     if (image == (Image *) NULL)
6424       {
6425         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6426           PackageName);
6427         goto PerlException;
6428       }
6429     normalize=MagickTrue;
6430     region.x=0;
6431     region.y=0;
6432     region.width=image->columns;
6433     region.height=1;
6434     if (items == 1)
6435       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6436     for (i=2; i < items; i+=2)
6437     {
6438       attribute=(char *) SvPV(ST(i-1),na);
6439       switch (*attribute)
6440       {
6441         case 'C':
6442         case 'c':
6443         {
6444           if (LocaleCompare(attribute,"channel") == 0)
6445             {
6446               ssize_t
6447                 option;
6448
6449               option=ParseChannelOption(SvPV(ST(i),na));
6450               if (option < 0)
6451                 {
6452                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6453                     SvPV(ST(i),na));
6454                   return;
6455                 }
6456               SetPixelChannelMask(image,(ChannelType) option);
6457               break;
6458             }
6459           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6460             attribute);
6461           break;
6462         }
6463         case 'g':
6464         case 'G':
6465         {
6466           if (LocaleCompare(attribute,"geometry") == 0)
6467             {
6468               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6469               break;
6470             }
6471           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6472             attribute);
6473           break;
6474         }
6475         case 'N':
6476         case 'n':
6477         {
6478           if (LocaleCompare(attribute,"normalize") == 0)
6479             {
6480               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6481                 SvPV(ST(i),na));
6482               if (option < 0)
6483                 {
6484                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6485                     SvPV(ST(i),na));
6486                   break;
6487                 }
6488              normalize=option != 0 ? MagickTrue : MagickFalse;
6489              break;
6490             }
6491           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6492             attribute);
6493           break;
6494         }
6495         case 'x':
6496         case 'X':
6497         {
6498           if (LocaleCompare(attribute,"x") == 0)
6499             {
6500               region.x=SvIV(ST(i));
6501               break;
6502             }
6503           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6504             attribute);
6505           break;
6506         }
6507         case 'y':
6508         case 'Y':
6509         {
6510           if (LocaleCompare(attribute,"y") == 0)
6511             {
6512               region.y=SvIV(ST(i));
6513               break;
6514             }
6515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6516             attribute);
6517           break;
6518         }
6519         default:
6520         {
6521           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6522             attribute);
6523           break;
6524         }
6525       }
6526     }
6527     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6528     if (p == (const Quantum *) NULL)
6529       PUSHs(&sv_undef);
6530     else
6531       {
6532         double
6533           scale;
6534
6535         scale=1.0;
6536         if (normalize != MagickFalse)
6537           scale=1.0/QuantumRange;
6538         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6539           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6540         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6541           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6542         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6543           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6544         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6545             (image->colorspace == CMYKColorspace))
6546           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6547         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6548           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6549       }
6550
6551   PerlException:
6552     InheritPerlException(exception,perl_exception);
6553     exception=DestroyExceptionInfo(exception);
6554     SvREFCNT_dec(perl_exception);
6555   }
6556 \f
6557 #
6558 ###############################################################################
6559 #                                                                             #
6560 #                                                                             #
6561 #                                                                             #
6562 #   G e t P i x e l s                                                         #
6563 #                                                                             #
6564 #                                                                             #
6565 #                                                                             #
6566 ###############################################################################
6567 #
6568 #
6569 void
6570 GetPixels(ref,...)
6571   Image::Magick ref=NO_INIT
6572   ALIAS:
6573     getpixels = 1
6574     getPixels = 2
6575   PPCODE:
6576   {
6577     AV
6578       *av;
6579
6580     char
6581       *attribute;
6582
6583     const char
6584       *map;
6585
6586     ExceptionInfo
6587       *exception;
6588
6589     Image
6590       *image;
6591
6592     MagickBooleanType
6593       normalize,
6594       status;
6595
6596     RectangleInfo
6597       region;
6598
6599     register ssize_t
6600       i;
6601
6602     ssize_t
6603       option;
6604
6605     struct PackageInfo
6606       *info;
6607
6608     SV
6609       *perl_exception,
6610       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6611
6612     PERL_UNUSED_VAR(ref);
6613     PERL_UNUSED_VAR(ix);
6614     exception=AcquireExceptionInfo();
6615     perl_exception=newSVpv("",0);
6616     reference=SvRV(ST(0));
6617     av=(AV *) reference;
6618     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6619       exception);
6620     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6621     if (image == (Image *) NULL)
6622       {
6623         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6624           PackageName);
6625         goto PerlException;
6626       }
6627     map="RGB";
6628     if (image->alpha_trait == BlendPixelTrait)
6629       map="RGBA";
6630     if (image->colorspace == CMYKColorspace)
6631       {
6632         map="CMYK";
6633         if (image->alpha_trait == BlendPixelTrait)
6634           map="CMYKA";
6635       }
6636     normalize=MagickFalse;
6637     region.x=0;
6638     region.y=0;
6639     region.width=image->columns;
6640     region.height=1;
6641     if (items == 1)
6642       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6643     for (i=2; i < items; i+=2)
6644     {
6645       attribute=(char *) SvPV(ST(i-1),na);
6646       switch (*attribute)
6647       {
6648         case 'g':
6649         case 'G':
6650         {
6651           if (LocaleCompare(attribute,"geometry") == 0)
6652             {
6653               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6654               break;
6655             }
6656           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6657             attribute);
6658           break;
6659         }
6660         case 'H':
6661         case 'h':
6662         {
6663           if (LocaleCompare(attribute,"height") == 0)
6664             {
6665               region.height=SvIV(ST(i));
6666               break;
6667             }
6668           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6669             attribute);
6670           break;
6671         }
6672         case 'M':
6673         case 'm':
6674         {
6675           if (LocaleCompare(attribute,"map") == 0)
6676             {
6677               map=SvPV(ST(i),na);
6678               break;
6679             }
6680           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6681             attribute);
6682           break;
6683         }
6684         case 'N':
6685         case 'n':
6686         {
6687           if (LocaleCompare(attribute,"normalize") == 0)
6688             {
6689               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6690                 SvPV(ST(i),na));
6691               if (option < 0)
6692                 {
6693                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6694                     SvPV(ST(i),na));
6695                   break;
6696                 }
6697              normalize=option != 0 ? MagickTrue : MagickFalse;
6698              break;
6699             }
6700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6701             attribute);
6702           break;
6703         }
6704         case 'W':
6705         case 'w':
6706         {
6707           if (LocaleCompare(attribute,"width") == 0)
6708             {
6709               region.width=SvIV(ST(i));
6710               break;
6711             }
6712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6713             attribute);
6714           break;
6715         }
6716         case 'x':
6717         case 'X':
6718         {
6719           if (LocaleCompare(attribute,"x") == 0)
6720             {
6721               region.x=SvIV(ST(i));
6722               break;
6723             }
6724           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6725             attribute);
6726           break;
6727         }
6728         case 'y':
6729         case 'Y':
6730         {
6731           if (LocaleCompare(attribute,"y") == 0)
6732             {
6733               region.y=SvIV(ST(i));
6734               break;
6735             }
6736           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6737             attribute);
6738           break;
6739         }
6740         default:
6741         {
6742           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6743             attribute);
6744           break;
6745         }
6746       }
6747     }
6748     if (normalize != MagickFalse)
6749       {
6750         float
6751           *pixels;
6752
6753         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6754           region.height*sizeof(*pixels));
6755         if (pixels == (float *) NULL)
6756           {
6757             ThrowPerlException(exception,ResourceLimitError,
6758               "MemoryAllocationFailed",PackageName);
6759             goto PerlException;
6760           }
6761         status=ExportImagePixels(image,region.x,region.y,region.width,
6762           region.height,map,FloatPixel,pixels,exception);
6763         if (status == MagickFalse)
6764           PUSHs(&sv_undef);
6765         else
6766           {
6767             EXTEND(sp,strlen(map)*region.width*region.height);
6768             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6769               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6770           }
6771         pixels=(float *) RelinquishMagickMemory(pixels);
6772       }
6773     else
6774       {
6775         Quantum
6776           *pixels;
6777
6778         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6779           region.height*sizeof(*pixels));
6780         if (pixels == (Quantum *) NULL)
6781           {
6782             ThrowPerlException(exception,ResourceLimitError,
6783               "MemoryAllocationFailed",PackageName);
6784             goto PerlException;
6785           }
6786         status=ExportImagePixels(image,region.x,region.y,region.width,
6787           region.height,map,QuantumPixel,pixels,exception);
6788         if (status == MagickFalse)
6789           PUSHs(&sv_undef);
6790         else
6791           {
6792             EXTEND(sp,strlen(map)*region.width*region.height);
6793             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6794               PUSHs(sv_2mortal(newSViv(pixels[i])));
6795           }
6796         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6797       }
6798
6799   PerlException:
6800     InheritPerlException(exception,perl_exception);
6801     exception=DestroyExceptionInfo(exception);
6802     SvREFCNT_dec(perl_exception);
6803   }
6804 \f
6805 #
6806 ###############################################################################
6807 #                                                                             #
6808 #                                                                             #
6809 #                                                                             #
6810 #   I m a g e T o B l o b                                                     #
6811 #                                                                             #
6812 #                                                                             #
6813 #                                                                             #
6814 ###############################################################################
6815 #
6816 #
6817 void
6818 ImageToBlob(ref,...)
6819   Image::Magick ref=NO_INIT
6820   ALIAS:
6821     ImageToBlob  = 1
6822     imagetoblob  = 2
6823     toblob       = 3
6824     blob         = 4
6825   PPCODE:
6826   {
6827     char
6828       filename[MaxTextExtent];
6829
6830     ExceptionInfo
6831       *exception;
6832
6833     Image
6834       *image,
6835       *next;
6836
6837     register ssize_t
6838       i;
6839
6840     struct PackageInfo
6841       *info,
6842       *package_info;
6843
6844     size_t
6845       length;
6846
6847     ssize_t
6848       scene;
6849
6850     SV
6851       *perl_exception,
6852       *reference;
6853
6854     void
6855       *blob;
6856
6857     PERL_UNUSED_VAR(ref);
6858     PERL_UNUSED_VAR(ix);
6859     exception=AcquireExceptionInfo();
6860     perl_exception=newSVpv("",0);
6861     package_info=(struct PackageInfo *) NULL;
6862     if (sv_isobject(ST(0)) == 0)
6863       {
6864         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6865           PackageName);
6866         goto PerlException;
6867       }
6868     reference=SvRV(ST(0));
6869     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6870     if (image == (Image *) NULL)
6871       {
6872         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6873           PackageName);
6874         goto PerlException;
6875       }
6876     package_info=ClonePackageInfo(info,exception);
6877     for (i=2; i < items; i+=2)
6878       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6879     (void) CopyMagickString(filename,package_info->image_info->filename,
6880       MaxTextExtent);
6881     scene=0;
6882     for (next=image; next; next=next->next)
6883     {
6884       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6885       next->scene=scene++;
6886     }
6887     SetImageInfo(package_info->image_info,(unsigned int)
6888       GetImageListLength(image),exception);
6889     EXTEND(sp,(ssize_t) GetImageListLength(image));
6890     for ( ; image; image=image->next)
6891     {
6892       length=0;
6893       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6894       if (blob != (char *) NULL)
6895         {
6896           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6897           blob=(unsigned char *) RelinquishMagickMemory(blob);
6898         }
6899       if (package_info->image_info->adjoin)
6900         break;
6901     }
6902
6903   PerlException:
6904     if (package_info != (struct PackageInfo *) NULL)
6905       DestroyPackageInfo(package_info);
6906     InheritPerlException(exception,perl_exception);
6907     exception=DestroyExceptionInfo(exception);
6908     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6909   }
6910 \f
6911 #
6912 ###############################################################################
6913 #                                                                             #
6914 #                                                                             #
6915 #                                                                             #
6916 #   L a y e r s                                                               #
6917 #                                                                             #
6918 #                                                                             #
6919 #                                                                             #
6920 ###############################################################################
6921 #
6922 #
6923 void
6924 Layers(ref,...)
6925   Image::Magick ref=NO_INIT
6926   ALIAS:
6927     Layers                = 1
6928     layers           = 2
6929     OptimizeImageLayers   = 3
6930     optimizelayers        = 4
6931     optimizeimagelayers   = 5
6932   PPCODE:
6933   {
6934     AV
6935       *av;
6936
6937     char
6938       *attribute;
6939
6940     CompositeOperator
6941       compose;
6942
6943     ExceptionInfo
6944       *exception;
6945
6946     HV
6947       *hv;
6948
6949     Image
6950       *image,
6951       *layers;
6952
6953     LayerMethod
6954       method;
6955
6956     register ssize_t
6957       i;
6958
6959     ssize_t
6960       option,
6961       sp;
6962
6963     struct PackageInfo
6964       *info;
6965
6966     SV
6967       *av_reference,
6968       *perl_exception,
6969       *reference,
6970       *rv,
6971       *sv;
6972
6973     PERL_UNUSED_VAR(ref);
6974     PERL_UNUSED_VAR(ix);
6975     exception=AcquireExceptionInfo();
6976     perl_exception=newSVpv("",0);
6977     sv=NULL;
6978     if (sv_isobject(ST(0)) == 0)
6979       {
6980         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6981           PackageName);
6982         goto PerlException;
6983       }
6984     reference=SvRV(ST(0));
6985     hv=SvSTASH(reference);
6986     av=newAV();
6987     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6988     SvREFCNT_dec(av);
6989     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6990     if (image == (Image *) NULL)
6991       {
6992         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6993           PackageName);
6994         goto PerlException;
6995       }
6996     compose=image->compose;
6997     method=OptimizeLayer;
6998     for (i=2; i < items; i+=2)
6999     {
7000       attribute=(char *) SvPV(ST(i-1),na);
7001       switch (*attribute)
7002       {
7003         case 'C':
7004         case 'c':
7005         {
7006           if (LocaleCompare(attribute,"compose") == 0)
7007             {
7008               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7009                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7010               if (sp < 0)
7011                 {
7012                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7013                     SvPV(ST(i),na));
7014                   break;
7015                 }
7016               compose=(CompositeOperator) sp;
7017               break;
7018             }
7019           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7020             attribute);
7021           break;
7022         }
7023         case 'M':
7024         case 'm':
7025         {
7026           if (LocaleCompare(attribute,"method") == 0)
7027             {
7028               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7029                 SvPV(ST(i),na));
7030               if (option < 0)
7031                 {
7032                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7033                     SvPV(ST(i),na));
7034                   break;
7035                 }
7036               method=(LayerMethod) option;
7037               break;
7038             }
7039           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7040             attribute);
7041           break;
7042         }
7043         default:
7044         {
7045           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7046             attribute);
7047           break;
7048         }
7049       }
7050     }
7051     layers=(Image *) NULL;
7052     switch (method)
7053     {
7054       case CompareAnyLayer:
7055       case CompareClearLayer:
7056       case CompareOverlayLayer:
7057       default:
7058       {
7059         layers=CompareImagesLayers(image,method,exception);
7060         break;
7061       }
7062       case MergeLayer:
7063       case FlattenLayer:
7064       case MosaicLayer:
7065       {
7066         layers=MergeImageLayers(image,method,exception);
7067         break;
7068       }
7069       case DisposeLayer:
7070       {
7071         layers=DisposeImages(image,exception);
7072         break;
7073       }
7074       case OptimizeImageLayer:
7075       {
7076         layers=OptimizeImageLayers(image,exception);
7077         break;
7078       }
7079       case OptimizePlusLayer:
7080       {
7081         layers=OptimizePlusImageLayers(image,exception);
7082         break;
7083       }
7084       case OptimizeTransLayer:
7085       {
7086         OptimizeImageTransparency(image,exception);
7087         break;
7088       }
7089       case RemoveDupsLayer:
7090       {
7091         RemoveDuplicateLayers(&image,exception);
7092         break;
7093       }
7094       case RemoveZeroLayer:
7095       {
7096         RemoveZeroDelayLayers(&image,exception);
7097         break;
7098       }
7099       case OptimizeLayer:
7100       {
7101         QuantizeInfo
7102           *quantize_info;
7103
7104         /*
7105           General Purpose, GIF Animation Optimizer.
7106         */
7107         layers=CoalesceImages(image,exception);
7108         if (layers == (Image *) NULL)
7109           break;
7110         image=layers;
7111         layers=OptimizeImageLayers(image,exception);
7112         if (layers == (Image *) NULL)
7113           break;
7114         image=DestroyImageList(image);
7115         image=layers;
7116         layers=(Image *) NULL;
7117         OptimizeImageTransparency(image,exception);
7118         quantize_info=AcquireQuantizeInfo(info->image_info);
7119         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7120         quantize_info=DestroyQuantizeInfo(quantize_info);
7121         break;
7122       }
7123       case CompositeLayer:
7124       {
7125         Image
7126           *source;
7127
7128         RectangleInfo
7129           geometry;
7130
7131         /*
7132           Split image sequence at the first 'NULL:' image.
7133         */
7134         source=image;
7135         while (source != (Image *) NULL)
7136         {
7137           source=GetNextImageInList(source);
7138           if ((source != (Image *) NULL) &&
7139               (LocaleCompare(source->magick,"NULL") == 0))
7140             break;
7141         }
7142         if (source != (Image *) NULL)
7143           {
7144             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7145                 (GetNextImageInList(source) == (Image *) NULL))
7146               source=(Image *) NULL;
7147             else
7148               {
7149                 /*
7150                   Separate the two lists, junk the null: image.
7151                 */
7152                 source=SplitImageList(source->previous);
7153                 DeleteImageFromList(&source);
7154               }
7155           }
7156         if (source == (Image *) NULL)
7157           {
7158             (void) ThrowMagickException(exception,GetMagickModule(),
7159               OptionError,"MissingNullSeparator","layers Composite");
7160             break;
7161           }
7162         /*
7163           Adjust offset with gravity and virtual canvas.
7164         */
7165         SetGeometry(image,&geometry);
7166         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7167         geometry.width=source->page.width != 0 ? source->page.width :
7168           source->columns;
7169         geometry.height=source->page.height != 0 ? source->page.height :
7170           source->rows;
7171         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7172           image->columns,image->page.height != 0 ? image->page.height :
7173           image->rows,image->gravity,&geometry);
7174         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7175         source=DestroyImageList(source);
7176         break;
7177       }
7178     }
7179     if (layers != (Image *) NULL)
7180       image=layers;
7181     else
7182       image=CloneImage(image,0,0,MagickTrue,exception);
7183     if (image == (Image *) NULL)
7184       goto PerlException;
7185     for ( ; image; image=image->next)
7186     {
7187       AddImageToRegistry(sv,image);
7188       rv=newRV(sv);
7189       av_push(av,sv_bless(rv,hv));
7190       SvREFCNT_dec(sv);
7191     }
7192     exception=DestroyExceptionInfo(exception);
7193     ST(0)=av_reference;
7194     SvREFCNT_dec(perl_exception);
7195     XSRETURN(1);
7196
7197   PerlException:
7198     InheritPerlException(exception,perl_exception);
7199     exception=DestroyExceptionInfo(exception);
7200     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7201     SvPOK_on(perl_exception);
7202     ST(0)=sv_2mortal(perl_exception);
7203     XSRETURN(1);
7204   }
7205 \f
7206 #
7207 ###############################################################################
7208 #                                                                             #
7209 #                                                                             #
7210 #                                                                             #
7211 #   M a g i c k T o M i m e                                                   #
7212 #                                                                             #
7213 #                                                                             #
7214 #                                                                             #
7215 ###############################################################################
7216 #
7217 #
7218 SV *
7219 MagickToMime(ref,name)
7220   Image::Magick ref=NO_INIT
7221   char *name
7222   ALIAS:
7223     magicktomime = 1
7224   CODE:
7225   {
7226     char
7227       *mime;
7228
7229     PERL_UNUSED_VAR(ref);
7230     PERL_UNUSED_VAR(ix);
7231     mime=MagickToMime(name);
7232     RETVAL=newSVpv(mime,0);
7233     mime=(char *) RelinquishMagickMemory(mime);
7234   }
7235   OUTPUT:
7236     RETVAL
7237 \f
7238 #
7239 ###############################################################################
7240 #                                                                             #
7241 #                                                                             #
7242 #                                                                             #
7243 #   M o g r i f y                                                             #
7244 #                                                                             #
7245 #                                                                             #
7246 #                                                                             #
7247 ###############################################################################
7248 #
7249 #
7250 void
7251 Mogrify(ref,...)
7252   Image::Magick ref=NO_INIT
7253   ALIAS:
7254     Comment            =   1
7255     CommentImage       =   2
7256     Label              =   3
7257     LabelImage         =   4
7258     AddNoise           =   5
7259     AddNoiseImage      =   6
7260     Colorize           =   7
7261     ColorizeImage      =   8
7262     Border             =   9
7263     BorderImage        =  10
7264     Blur               =  11
7265     BlurImage          =  12
7266     Chop               =  13
7267     ChopImage          =  14
7268     Crop               =  15
7269     CropImage          =  16
7270     Despeckle          =  17
7271     DespeckleImage     =  18
7272     Edge               =  19
7273     EdgeImage          =  20
7274     Emboss             =  21
7275     EmbossImage        =  22
7276     Enhance            =  23
7277     EnhanceImage       =  24
7278     Flip               =  25
7279     FlipImage          =  26
7280     Flop               =  27
7281     FlopImage          =  28
7282     Frame              =  29
7283     FrameImage         =  30
7284     Implode            =  31
7285     ImplodeImage       =  32
7286     Magnify            =  33
7287     MagnifyImage       =  34
7288     MedianFilter       =  35
7289     MedianConvolveImage  =  36
7290     Minify             =  37
7291     MinifyImage        =  38
7292     OilPaint           =  39
7293     OilPaintImage      =  40
7294     ReduceNoise        =  41
7295     ReduceNoiseImage   =  42
7296     Roll               =  43
7297     RollImage          =  44
7298     Rotate             =  45
7299     RotateImage        =  46
7300     Sample             =  47
7301     SampleImage        =  48
7302     Scale              =  49
7303     ScaleImage         =  50
7304     Shade              =  51
7305     ShadeImage         =  52
7306     Sharpen            =  53
7307     SharpenImage       =  54
7308     Shear              =  55
7309     ShearImage         =  56
7310     Spread             =  57
7311     SpreadImage        =  58
7312     Swirl              =  59
7313     SwirlImage         =  60
7314     Resize             =  61
7315     ResizeImage        =  62
7316     Zoom               =  63
7317     ZoomImage          =  64
7318     Annotate           =  65
7319     AnnotateImage      =  66
7320     ColorFloodfill     =  67
7321     ColorFloodfillImage=  68
7322     Composite          =  69
7323     CompositeImage     =  70
7324     Contrast           =  71
7325     ContrastImage      =  72
7326     CycleColormap      =  73
7327     CycleColormapImage =  74
7328     Draw               =  75
7329     DrawImage          =  76
7330     Equalize           =  77
7331     EqualizeImage      =  78
7332     Gamma              =  79
7333     GammaImage         =  80
7334     Map                =  81
7335     MapImage           =  82
7336     MatteFloodfill     =  83
7337     MatteFloodfillImage=  84
7338     Modulate           =  85
7339     ModulateImage      =  86
7340     Negate             =  87
7341     NegateImage        =  88
7342     Normalize          =  89
7343     NormalizeImage     =  90
7344     NumberColors       =  91
7345     NumberColorsImage  =  92
7346     Opaque             =  93
7347     OpaqueImage        =  94
7348     Quantize           =  95
7349     QuantizeImage      =  96
7350     Raise              =  97
7351     RaiseImage         =  98
7352     Segment            =  99
7353     SegmentImage       = 100
7354     Signature          = 101
7355     SignatureImage     = 102
7356     Solarize           = 103
7357     SolarizeImage      = 104
7358     Sync               = 105
7359     SyncImage          = 106
7360     Texture            = 107
7361     TextureImage       = 108
7362     Evaluate           = 109
7363     EvaluateImage      = 110
7364     Transparent        = 111
7365     TransparentImage   = 112
7366     Threshold          = 113
7367     ThresholdImage     = 114
7368     Charcoal           = 115
7369     CharcoalImage      = 116
7370     Trim               = 117
7371     TrimImage          = 118
7372     Wave               = 119
7373     WaveImage          = 120
7374     Separate           = 121
7375     SeparateImage      = 122
7376     Stereo             = 125
7377     StereoImage        = 126
7378     Stegano            = 127
7379     SteganoImage       = 128
7380     Deconstruct        = 129
7381     DeconstructImage   = 130
7382     GaussianBlur       = 131
7383     GaussianBlurImage  = 132
7384     Convolve           = 133
7385     ConvolveImage      = 134
7386     Profile            = 135
7387     ProfileImage       = 136
7388     UnsharpMask        = 137
7389     UnsharpMaskImage   = 138
7390     MotionBlur         = 139
7391     MotionBlurImage    = 140
7392     OrderedDither      = 141
7393     OrderedDitherImage = 142
7394     Shave              = 143
7395     ShaveImage         = 144
7396     Level              = 145
7397     LevelImage         = 146
7398     Clip               = 147
7399     ClipImage          = 148
7400     AffineTransform    = 149
7401     AffineTransformImage = 150
7402     Difference         = 151
7403     DifferenceImage    = 152
7404     AdaptiveThreshold  = 153
7405     AdaptiveThresholdImage = 154
7406     Resample           = 155
7407     ResampleImage      = 156
7408     Describe           = 157
7409     DescribeImage      = 158
7410     BlackThreshold     = 159
7411     BlackThresholdImage= 160
7412     WhiteThreshold     = 161
7413     WhiteThresholdImage= 162
7414     RadialBlur         = 163
7415     RadialBlurImage    = 164
7416     Thumbnail          = 165
7417     ThumbnailImage     = 166
7418     Strip              = 167
7419     StripImage         = 168
7420     Tint               = 169
7421     TintImage          = 170
7422     Channel            = 171
7423     ChannelImage       = 172
7424     Splice             = 173
7425     SpliceImage        = 174
7426     Posterize          = 175
7427     PosterizeImage     = 176
7428     Shadow             = 177
7429     ShadowImage        = 178
7430     Identify           = 179
7431     IdentifyImage      = 180
7432     SepiaTone          = 181
7433     SepiaToneImage     = 182
7434     SigmoidalContrast  = 183
7435     SigmoidalContrastImage = 184
7436     Extent             = 185
7437     ExtentImage        = 186
7438     Vignette           = 187
7439     VignetteImage      = 188
7440     ContrastStretch    = 189
7441     ContrastStretchImage = 190
7442     Sans0              = 191
7443     Sans0Image         = 192
7444     Sans1              = 193
7445     Sans1Image         = 194
7446     AdaptiveSharpen    = 195
7447     AdaptiveSharpenImage = 196
7448     Transpose          = 197
7449     TransposeImage     = 198
7450     Transverse         = 199
7451     TransverseImage    = 200
7452     AutoOrient         = 201
7453     AutoOrientImage    = 202
7454     AdaptiveBlur       = 203
7455     AdaptiveBlurImage  = 204
7456     Sketch             = 205
7457     SketchImage        = 206
7458     UniqueColors       = 207
7459     UniqueColorsImage  = 208
7460     AdaptiveResize     = 209
7461     AdaptiveResizeImage= 210
7462     ClipMask           = 211
7463     ClipMaskImage      = 212
7464     LinearStretch      = 213
7465     LinearStretchImage = 214
7466     ColorMatrix        = 215
7467     ColorMatrixImage   = 216
7468     Mask               = 217
7469     MaskImage          = 218
7470     Polaroid           = 219
7471     PolaroidImage      = 220
7472     FloodfillPaint     = 221
7473     FloodfillPaintImage= 222
7474     Distort            = 223
7475     DistortImage       = 224
7476     Clut               = 225
7477     ClutImage          = 226
7478     LiquidRescale      = 227
7479     LiquidRescaleImage = 228
7480     Encipher           = 229
7481     EncipherImage      = 230
7482     Decipher           = 231
7483     DecipherImage      = 232
7484     Deskew             = 233
7485     DeskewImage        = 234
7486     Remap              = 235
7487     RemapImage         = 236
7488     SparseColor        = 237
7489     SparseColorImage   = 238
7490     Function           = 239
7491     FunctionImage      = 240
7492     SelectiveBlur      = 241
7493     SelectiveBlurImage = 242
7494     HaldClut           = 243
7495     HaldClutImage      = 244
7496     BlueShift          = 245
7497     BlueShiftImage     = 246
7498     ForwardFourierTransform  = 247
7499     ForwardFourierTransformImage = 248
7500     InverseFourierTransform = 249
7501     InverseFourierTransformImage = 250
7502     ColorDecisionList  = 251
7503     ColorDecisionListImage = 252
7504     AutoGamma          = 253
7505     AutoGammaImage     = 254
7506     AutoLevel          = 255
7507     AutoLevelImage     = 256
7508     LevelColors        = 257
7509     LevelImageColors   = 258
7510     Clamp              = 259
7511     ClampImage         = 260
7512     BrightnessContrast = 261
7513     BrightnessContrastImage = 262
7514     Morphology         = 263
7515     MorphologyImage    = 264
7516     Color              = 265
7517     ColorImage         = 266
7518     Mode               = 267
7519     ModeImage          = 268
7520     Statistic          = 269
7521     StatisticImage     = 270
7522     Perceptible        = 271
7523     PerceptibleImage   = 272
7524     Poly               = 273
7525     PolyImage          = 274
7526     Grayscale          = 275
7527     GrayscaleImage     = 276
7528     MogrifyRegion      = 666
7529   PPCODE:
7530   {
7531     AffineMatrix
7532       affine,
7533       current;
7534
7535     char
7536       attribute_flag[MaxArguments],
7537       message[MaxTextExtent];
7538
7539     ChannelType
7540       channel,
7541       channel_mask;
7542
7543     CompositeOperator
7544       compose;
7545
7546     const char
7547       *attribute,
7548       *value;
7549
7550     double
7551       angle;
7552
7553     ExceptionInfo
7554       *exception;
7555
7556     GeometryInfo
7557       geometry_info;
7558
7559     Image
7560       *image,
7561       *next,
7562       *region_image;
7563
7564     MagickBooleanType
7565       status;
7566
7567     MagickStatusType
7568       flags;
7569
7570     PixelInfo
7571       fill_color;
7572
7573     RectangleInfo
7574       geometry,
7575       region_info;
7576
7577     register ssize_t
7578       i;
7579
7580     ssize_t
7581       base,
7582       j,
7583       number_images;
7584
7585     struct Methods
7586       *rp;
7587
7588     struct PackageInfo
7589       *info;
7590
7591     SV
7592       *perl_exception,
7593       **pv,
7594       *reference,
7595       **reference_vector;
7596
7597     struct ArgumentList
7598       argument_list[MaxArguments];
7599
7600     PERL_UNUSED_VAR(ref);
7601     PERL_UNUSED_VAR(ix);
7602     exception=AcquireExceptionInfo();
7603     perl_exception=newSVpv("",0);
7604     reference_vector=NULL;
7605     region_image=NULL;
7606     number_images=0;
7607     base=2;
7608     if (sv_isobject(ST(0)) == 0)
7609       {
7610         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7611           PackageName);
7612         goto PerlException;
7613       }
7614     reference=SvRV(ST(0));
7615     region_info.width=0;
7616     region_info.height=0;
7617     region_info.x=0;
7618     region_info.y=0;
7619     region_image=(Image *) NULL;
7620     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7621     if (ix && (ix != 666))
7622       {
7623         /*
7624           Called as Method(...)
7625         */
7626         ix=(ix+1)/2;
7627         rp=(&Methods[ix-1]);
7628         attribute=rp->name;
7629       }
7630     else
7631       {
7632         /*
7633           Called as Mogrify("Method",...)
7634         */
7635         attribute=(char *) SvPV(ST(1),na);
7636         if (ix)
7637           {
7638             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7639             attribute=(char *) SvPV(ST(2),na);
7640             base++;
7641           }
7642         for (rp=Methods; ; rp++)
7643         {
7644           if (rp >= EndOf(Methods))
7645             {
7646               ThrowPerlException(exception,OptionError,
7647                 "UnrecognizedPerlMagickMethod",attribute);
7648               goto PerlException;
7649             }
7650           if (strEQcase(attribute,rp->name))
7651             break;
7652         }
7653         ix=rp-Methods+1;
7654         base++;
7655       }
7656     if (image == (Image *) NULL)
7657       {
7658         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7659         goto PerlException;
7660       }
7661     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7662     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7663     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7664     {
7665       Arguments
7666         *pp,
7667         *qq;
7668
7669       ssize_t
7670         ssize_test;
7671
7672       struct ArgumentList
7673         *al;
7674
7675       SV
7676         *sv;
7677
7678       sv=NULL;
7679       ssize_test=0;
7680       pp=(Arguments *) NULL;
7681       qq=rp->arguments;
7682       if (i == items)
7683         {
7684           pp=rp->arguments,
7685           sv=ST(i-1);
7686         }
7687       else
7688         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7689         {
7690           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7691             break;
7692           if (strEQcase(attribute,qq->method) > ssize_test)
7693             {
7694               pp=qq;
7695               ssize_test=strEQcase(attribute,qq->method);
7696             }
7697         }
7698       if (pp == (Arguments *) NULL)
7699         {
7700           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7701             attribute);
7702           goto continue_outer_loop;
7703         }
7704       al=(&argument_list[pp-rp->arguments]);
7705       switch (pp->type)
7706       {
7707         case ArrayReference:
7708         {
7709           if (SvTYPE(sv) != SVt_RV)
7710             {
7711               (void) FormatLocaleString(message,MaxTextExtent,
7712                 "invalid %.60s value",pp->method);
7713               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7714               goto continue_outer_loop;
7715             }
7716           al->array_reference=SvRV(sv);
7717           break;
7718         }
7719         case RealReference:
7720         {
7721           al->real_reference=SvNV(sv);
7722           break;
7723         }
7724         case FileReference:
7725         {
7726           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7727           break;
7728         }
7729         case ImageReference:
7730         {
7731           if (!sv_isobject(sv) ||
7732               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7733                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7734             {
7735               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7736                 PackageName);
7737               goto PerlException;
7738             }
7739           break;
7740         }
7741         case IntegerReference:
7742         {
7743           al->integer_reference=SvIV(sv);
7744           break;
7745         }
7746         case StringReference:
7747         {
7748           al->string_reference=(char *) SvPV(sv,al->length);
7749           if (sv_isobject(sv))
7750             al->image_reference=SetupList(aTHX_ SvRV(sv),
7751               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7752           break;
7753         }
7754         default:
7755         {
7756           /*
7757             Is a string; look up name.
7758           */
7759           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7760             {
7761               al->string_reference=(char *) SvPV(sv,al->length);
7762               al->integer_reference=(-1);
7763               break;
7764             }
7765           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7766             MagickFalse,SvPV(sv,na));
7767           if (pp->type == MagickChannelOptions)
7768             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7769           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7770             {
7771               (void) FormatLocaleString(message,MaxTextExtent,
7772                 "invalid %.60s value",pp->method);
7773               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7774               goto continue_outer_loop;
7775             }
7776           break;
7777         }
7778       }
7779       attribute_flag[pp-rp->arguments]++;
7780       continue_outer_loop: ;
7781     }
7782     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7783     pv=reference_vector;
7784     SetGeometryInfo(&geometry_info);
7785     channel=DefaultChannels;
7786     for (next=image; next; next=next->next)
7787     {
7788       image=next;
7789       SetGeometry(image,&geometry);
7790       if ((region_info.width*region_info.height) != 0)
7791         {
7792           region_image=image;
7793           image=CropImage(image,&region_info,exception);
7794         }
7795       switch (ix)
7796       {
7797         default:
7798         {
7799           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7800           ThrowPerlException(exception,OptionError,
7801             "UnrecognizedPerlMagickMethod",message);
7802           goto PerlException;
7803         }
7804         case 1:  /* Comment */
7805         {
7806           if (attribute_flag[0] == 0)
7807             argument_list[0].string_reference=(char *) NULL;
7808           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7809             info ? info->image_info : (ImageInfo *) NULL,image,
7810             argument_list[0].string_reference,exception),exception);
7811           break;
7812         }
7813         case 2:  /* Label */
7814         {
7815           if (attribute_flag[0] == 0)
7816             argument_list[0].string_reference=(char *) NULL;
7817           (void) SetImageProperty(image,"label",InterpretImageProperties(
7818             info ? info->image_info : (ImageInfo *) NULL,image,
7819             argument_list[0].string_reference,exception),exception);
7820           break;
7821         }
7822         case 3:  /* AddNoise */
7823         {
7824           double
7825             attenuate;
7826
7827           if (attribute_flag[0] == 0)
7828             argument_list[0].integer_reference=UniformNoise;
7829           attenuate=1.0;
7830           if (attribute_flag[1] != 0)
7831             attenuate=argument_list[1].real_reference;
7832           if (attribute_flag[2] != 0)
7833             channel=(ChannelType) argument_list[2].integer_reference;
7834           channel_mask=SetImageChannelMask(image,channel);
7835           image=AddNoiseImage(image,(NoiseType)
7836             argument_list[0].integer_reference,attenuate,exception);
7837           if (image != (Image *) NULL)
7838             (void) SetImageChannelMask(image,channel_mask);
7839           break;
7840         }
7841         case 4:  /* Colorize */
7842         {
7843           PixelInfo
7844             target;
7845
7846           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7847             0,0,&target,exception);
7848           if (attribute_flag[0] != 0)
7849             (void) QueryColorCompliance(argument_list[0].string_reference,
7850               AllCompliance,&target,exception);
7851           if (attribute_flag[1] == 0)
7852             argument_list[1].string_reference="100%";
7853           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7854             exception);
7855           break;
7856         }
7857         case 5:  /* Border */
7858         {
7859           CompositeOperator
7860             compose;
7861
7862           geometry.width=0;
7863           geometry.height=0;
7864           if (attribute_flag[0] != 0)
7865             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7866               &geometry,exception);
7867           if (attribute_flag[1] != 0)
7868             geometry.width=argument_list[1].integer_reference;
7869           if (attribute_flag[2] != 0)
7870             geometry.height=argument_list[2].integer_reference;
7871           if (attribute_flag[3] != 0)
7872             QueryColorCompliance(argument_list[3].string_reference,
7873               AllCompliance,&image->border_color,exception);
7874           if (attribute_flag[4] != 0)
7875             QueryColorCompliance(argument_list[4].string_reference,
7876               AllCompliance,&image->border_color,exception);
7877           if (attribute_flag[5] != 0)
7878             QueryColorCompliance(argument_list[5].string_reference,
7879               AllCompliance,&image->border_color,exception);
7880           compose=image->compose;
7881           if (attribute_flag[6] != 0)
7882             compose=(CompositeOperator) argument_list[6].integer_reference;
7883           image=BorderImage(image,&geometry,compose,exception);
7884           break;
7885         }
7886         case 6:  /* Blur */
7887         {
7888           if (attribute_flag[0] != 0)
7889             {
7890               flags=ParseGeometry(argument_list[0].string_reference,
7891                 &geometry_info);
7892               if ((flags & SigmaValue) == 0)
7893                 geometry_info.sigma=1.0;
7894             }
7895           if (attribute_flag[1] != 0)
7896             geometry_info.rho=argument_list[1].real_reference;
7897           if (attribute_flag[2] != 0)
7898             geometry_info.sigma=argument_list[2].real_reference;
7899           if (attribute_flag[3] != 0)
7900             channel=(ChannelType) argument_list[3].integer_reference;
7901           channel_mask=SetImageChannelMask(image,channel);
7902           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7903             exception);
7904           if (image != (Image *) NULL)
7905             (void) SetImageChannelMask(image,channel_mask);
7906           break;
7907         }
7908         case 7:  /* Chop */
7909         {
7910           if (attribute_flag[0] != 0)
7911             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7912               &geometry,exception);
7913           if (attribute_flag[1] != 0)
7914             geometry.width=argument_list[1].integer_reference;
7915           if (attribute_flag[2] != 0)
7916             geometry.height=argument_list[2].integer_reference;
7917           if (attribute_flag[3] != 0)
7918             geometry.x=argument_list[3].integer_reference;
7919           if (attribute_flag[4] != 0)
7920             geometry.y=argument_list[4].integer_reference;
7921           image=ChopImage(image,&geometry,exception);
7922           break;
7923         }
7924         case 8:  /* Crop */
7925         {
7926           if (attribute_flag[6] != 0)
7927             image->gravity=(GravityType) argument_list[6].integer_reference;
7928           if (attribute_flag[0] != 0)
7929             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7930               &geometry,exception);
7931           if (attribute_flag[1] != 0)
7932             geometry.width=argument_list[1].integer_reference;
7933           if (attribute_flag[2] != 0)
7934             geometry.height=argument_list[2].integer_reference;
7935           if (attribute_flag[3] != 0)
7936             geometry.x=argument_list[3].integer_reference;
7937           if (attribute_flag[4] != 0)
7938             geometry.y=argument_list[4].integer_reference;
7939           if (attribute_flag[5] != 0)
7940             image->fuzz=StringToDoubleInterval(
7941               argument_list[5].string_reference,(double) QuantumRange+1.0);
7942           image=CropImage(image,&geometry,exception);
7943           break;
7944         }
7945         case 9:  /* Despeckle */
7946         {
7947           image=DespeckleImage(image,exception);
7948           break;
7949         }
7950         case 10:  /* Edge */
7951         {
7952           if (attribute_flag[0] != 0)
7953             geometry_info.rho=argument_list[0].real_reference;
7954           image=EdgeImage(image,geometry_info.rho,exception);
7955           break;
7956         }
7957         case 11:  /* Emboss */
7958         {
7959           if (attribute_flag[0] != 0)
7960             {
7961               flags=ParseGeometry(argument_list[0].string_reference,
7962                 &geometry_info);
7963               if ((flags & SigmaValue) == 0)
7964                 geometry_info.sigma=1.0;
7965             }
7966           if (attribute_flag[1] != 0)
7967             geometry_info.rho=argument_list[1].real_reference;
7968           if (attribute_flag[2] != 0)
7969             geometry_info.sigma=argument_list[2].real_reference;
7970           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7971             exception);
7972           break;
7973         }
7974         case 12:  /* Enhance */
7975         {
7976           image=EnhanceImage(image,exception);
7977           break;
7978         }
7979         case 13:  /* Flip */
7980         {
7981           image=FlipImage(image,exception);
7982           break;
7983         }
7984         case 14:  /* Flop */
7985         {
7986           image=FlopImage(image,exception);
7987           break;
7988         }
7989         case 15:  /* Frame */
7990         {
7991           CompositeOperator
7992             compose;
7993
7994           FrameInfo
7995             frame_info;
7996
7997           if (attribute_flag[0] != 0)
7998             {
7999               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8000                 &geometry,exception);
8001               frame_info.width=geometry.width;
8002               frame_info.height=geometry.height;
8003               frame_info.outer_bevel=geometry.x;
8004               frame_info.inner_bevel=geometry.y;
8005             }
8006           if (attribute_flag[1] != 0)
8007             frame_info.width=argument_list[1].integer_reference;
8008           if (attribute_flag[2] != 0)
8009             frame_info.height=argument_list[2].integer_reference;
8010           if (attribute_flag[3] != 0)
8011             frame_info.inner_bevel=argument_list[3].integer_reference;
8012           if (attribute_flag[4] != 0)
8013             frame_info.outer_bevel=argument_list[4].integer_reference;
8014           if (attribute_flag[5] != 0)
8015             QueryColorCompliance(argument_list[5].string_reference,
8016               AllCompliance,&fill_color,exception);
8017           if (attribute_flag[6] != 0)
8018             QueryColorCompliance(argument_list[6].string_reference,
8019               AllCompliance,&fill_color,exception);
8020           frame_info.x=(ssize_t) frame_info.width;
8021           frame_info.y=(ssize_t) frame_info.height;
8022           frame_info.width=image->columns+2*frame_info.x;
8023           frame_info.height=image->rows+2*frame_info.y;
8024           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8025             image->matte_color=fill_color;
8026           compose=image->compose;
8027           if (attribute_flag[7] != 0)
8028             compose=(CompositeOperator) argument_list[7].integer_reference;
8029           image=FrameImage(image,&frame_info,compose,exception);
8030           break;
8031         }
8032         case 16:  /* Implode */
8033         {
8034           PixelInterpolateMethod
8035             method;
8036
8037           if (attribute_flag[0] == 0)
8038             argument_list[0].real_reference=0.5;
8039           method=UndefinedInterpolatePixel;
8040           if (attribute_flag[1] != 0)
8041             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8042           image=ImplodeImage(image,argument_list[0].real_reference,
8043             method,exception);
8044           break;
8045         }
8046         case 17:  /* Magnify */
8047         {
8048           image=MagnifyImage(image,exception);
8049           break;
8050         }
8051         case 18:  /* MedianFilter */
8052         {
8053           if (attribute_flag[0] != 0)
8054             {
8055               flags=ParseGeometry(argument_list[0].string_reference,
8056                 &geometry_info);
8057               if ((flags & SigmaValue) == 0)
8058                 geometry_info.sigma=geometry_info.rho;
8059             }
8060           if (attribute_flag[1] != 0)
8061             geometry_info.rho=argument_list[1].real_reference;
8062           if (attribute_flag[2] != 0)
8063             geometry_info.sigma=argument_list[2].real_reference;
8064           if (attribute_flag[3] != 0)
8065             channel=(ChannelType) argument_list[3].integer_reference;
8066           channel_mask=SetImageChannelMask(image,channel);
8067           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8068             (size_t) geometry_info.sigma,exception);
8069           if (image != (Image *) NULL)
8070             (void) SetImageChannelMask(image,channel_mask);
8071           break;
8072         }
8073         case 19:  /* Minify */
8074         {
8075           image=MinifyImage(image,exception);
8076           break;
8077         }
8078         case 20:  /* OilPaint */
8079         {
8080           if (attribute_flag[0] == 0)
8081             argument_list[0].real_reference=0.0;
8082           if (attribute_flag[1] == 0)
8083             argument_list[1].real_reference=1.0;
8084           image=OilPaintImage(image,argument_list[0].real_reference,
8085             argument_list[1].real_reference,exception);
8086           break;
8087         }
8088         case 21:  /* ReduceNoise */
8089         {
8090           if (attribute_flag[0] != 0)
8091             {
8092               flags=ParseGeometry(argument_list[0].string_reference,
8093                 &geometry_info);
8094               if ((flags & SigmaValue) == 0)
8095                 geometry_info.sigma=1.0;
8096             }
8097           if (attribute_flag[1] != 0)
8098             geometry_info.rho=argument_list[1].real_reference;
8099           if (attribute_flag[2] != 0)
8100             geometry_info.sigma=argument_list[2].real_reference;
8101           if (attribute_flag[3] != 0)
8102             channel=(ChannelType) argument_list[3].integer_reference;
8103           channel_mask=SetImageChannelMask(image,channel);
8104           image=StatisticImage(image,NonpeakStatistic,(size_t)
8105             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8106           if (image != (Image *) NULL)
8107             (void) SetImageChannelMask(image,channel_mask);
8108           break;
8109         }
8110         case 22:  /* Roll */
8111         {
8112           if (attribute_flag[0] != 0)
8113             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8114               &geometry,exception);
8115           if (attribute_flag[1] != 0)
8116             geometry.x=argument_list[1].integer_reference;
8117           if (attribute_flag[2] != 0)
8118             geometry.y=argument_list[2].integer_reference;
8119           image=RollImage(image,geometry.x,geometry.y,exception);
8120           break;
8121         }
8122         case 23:  /* Rotate */
8123         {
8124           if (attribute_flag[0] == 0)
8125             argument_list[0].real_reference=90.0;
8126           if (attribute_flag[1] != 0)
8127             {
8128               QueryColorCompliance(argument_list[1].string_reference,
8129                 AllCompliance,&image->background_color,exception);
8130               if ((image->background_color.alpha_trait == BlendPixelTrait) &&
8131                   (image->alpha_trait != BlendPixelTrait))
8132                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8133             }
8134           image=RotateImage(image,argument_list[0].real_reference,exception);
8135           break;
8136         }
8137         case 24:  /* Sample */
8138         {
8139           if (attribute_flag[0] != 0)
8140             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8141               &geometry,exception);
8142           if (attribute_flag[1] != 0)
8143             geometry.width=argument_list[1].integer_reference;
8144           if (attribute_flag[2] != 0)
8145             geometry.height=argument_list[2].integer_reference;
8146           image=SampleImage(image,geometry.width,geometry.height,exception);
8147           break;
8148         }
8149         case 25:  /* Scale */
8150         {
8151           if (attribute_flag[0] != 0)
8152             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8153               &geometry,exception);
8154           if (attribute_flag[1] != 0)
8155             geometry.width=argument_list[1].integer_reference;
8156           if (attribute_flag[2] != 0)
8157             geometry.height=argument_list[2].integer_reference;
8158           image=ScaleImage(image,geometry.width,geometry.height,exception);
8159           break;
8160         }
8161         case 26:  /* Shade */
8162         {
8163           if (attribute_flag[0] != 0)
8164             {
8165               flags=ParseGeometry(argument_list[0].string_reference,
8166                 &geometry_info);
8167               if ((flags & SigmaValue) == 0)
8168                 geometry_info.sigma=0.0;
8169             }
8170           if (attribute_flag[1] != 0)
8171             geometry_info.rho=argument_list[1].real_reference;
8172           if (attribute_flag[2] != 0)
8173             geometry_info.sigma=argument_list[2].real_reference;
8174           image=ShadeImage(image,
8175             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8176             geometry_info.rho,geometry_info.sigma,exception);
8177           break;
8178         }
8179         case 27:  /* Sharpen */
8180         {
8181           if (attribute_flag[0] != 0)
8182             {
8183               flags=ParseGeometry(argument_list[0].string_reference,
8184                 &geometry_info);
8185               if ((flags & SigmaValue) == 0)
8186                 geometry_info.sigma=1.0;
8187             }
8188           if (attribute_flag[1] != 0)
8189             geometry_info.rho=argument_list[1].real_reference;
8190           if (attribute_flag[2] != 0)
8191             geometry_info.sigma=argument_list[2].real_reference;
8192           if (attribute_flag[3] != 0)
8193             channel=(ChannelType) argument_list[3].integer_reference;
8194           channel_mask=SetImageChannelMask(image,channel);
8195           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8196             exception);
8197           if (image != (Image *) NULL)
8198             (void) SetImageChannelMask(image,channel_mask);
8199           break;
8200         }
8201         case 28:  /* Shear */
8202         {
8203           if (attribute_flag[0] != 0)
8204             {
8205               flags=ParseGeometry(argument_list[0].string_reference,
8206                 &geometry_info);
8207               if ((flags & SigmaValue) == 0)
8208                 geometry_info.sigma=geometry_info.rho;
8209             }
8210           if (attribute_flag[1] != 0)
8211             geometry_info.rho=argument_list[1].real_reference;
8212           if (attribute_flag[2] != 0)
8213             geometry_info.sigma=argument_list[2].real_reference;
8214           if (attribute_flag[3] != 0)
8215             QueryColorCompliance(argument_list[3].string_reference,
8216               AllCompliance,&image->background_color,exception);
8217           if (attribute_flag[4] != 0)
8218             QueryColorCompliance(argument_list[4].string_reference,
8219               AllCompliance,&image->background_color,exception);
8220           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8221             exception);
8222           break;
8223         }
8224         case 29:  /* Spread */
8225         {
8226           PixelInterpolateMethod
8227             method;
8228
8229           if (attribute_flag[0] == 0)
8230             argument_list[0].real_reference=1.0;
8231           method=UndefinedInterpolatePixel;
8232           if (attribute_flag[1] != 0)
8233             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8234           image=SpreadImage(image,argument_list[0].real_reference,method,
8235             exception);
8236           break;
8237         }
8238         case 30:  /* Swirl */
8239         {
8240           PixelInterpolateMethod
8241             method;
8242
8243           if (attribute_flag[0] == 0)
8244             argument_list[0].real_reference=50.0;
8245           method=UndefinedInterpolatePixel;
8246           if (attribute_flag[1] != 0)
8247             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8248           image=SwirlImage(image,argument_list[0].real_reference,
8249             method,exception);
8250           break;
8251         }
8252         case 31:  /* Resize */
8253         case 32:  /* Zoom */
8254         {
8255           if (attribute_flag[0] != 0)
8256             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8257               &geometry,exception);
8258           if (attribute_flag[1] != 0)
8259             geometry.width=argument_list[1].integer_reference;
8260           if (attribute_flag[2] != 0)
8261             geometry.height=argument_list[2].integer_reference;
8262           if (attribute_flag[3] == 0)
8263             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8264           if (attribute_flag[4] != 0)
8265             SetImageArtifact(image,"filter:support",
8266               argument_list[4].string_reference);
8267           image=ResizeImage(image,geometry.width,geometry.height,
8268             (FilterTypes) argument_list[3].integer_reference,
8269             exception);
8270           break;
8271         }
8272         case 33:  /* Annotate */
8273         {
8274           DrawInfo
8275             *draw_info;
8276
8277           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8278             (DrawInfo *) NULL);
8279           if (attribute_flag[0] != 0)
8280             {
8281               char
8282                 *text;
8283
8284               text=InterpretImageProperties(info ? info->image_info :
8285                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8286                 exception);
8287               (void) CloneString(&draw_info->text,text);
8288               text=DestroyString(text);
8289             }
8290           if (attribute_flag[1] != 0)
8291             (void) CloneString(&draw_info->font,
8292               argument_list[1].string_reference);
8293           if (attribute_flag[2] != 0)
8294             draw_info->pointsize=argument_list[2].real_reference;
8295           if (attribute_flag[3] != 0)
8296             (void) CloneString(&draw_info->density,
8297               argument_list[3].string_reference);
8298           if (attribute_flag[4] != 0)
8299             (void) QueryColorCompliance(argument_list[4].string_reference,
8300               AllCompliance,&draw_info->undercolor,exception);
8301           if (attribute_flag[5] != 0)
8302             {
8303               (void) QueryColorCompliance(argument_list[5].string_reference,
8304                 AllCompliance,&draw_info->stroke,exception);
8305               if (argument_list[5].image_reference != (Image *) NULL)
8306                 draw_info->stroke_pattern=CloneImage(
8307                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8308             }
8309           if (attribute_flag[6] != 0)
8310             {
8311               (void) QueryColorCompliance(argument_list[6].string_reference,
8312                 AllCompliance,&draw_info->fill,exception);
8313               if (argument_list[6].image_reference != (Image *) NULL)
8314                 draw_info->fill_pattern=CloneImage(
8315                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8316             }
8317           if (attribute_flag[7] != 0)
8318             {
8319               (void) CloneString(&draw_info->geometry,
8320                 argument_list[7].string_reference);
8321               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8322                 &geometry,exception);
8323               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8324                 geometry_info.sigma=geometry_info.xi;
8325             }
8326           if (attribute_flag[8] != 0)
8327             (void) QueryColorCompliance(argument_list[8].string_reference,
8328               AllCompliance,&draw_info->fill,exception);
8329           if (attribute_flag[11] != 0)
8330             draw_info->gravity=(GravityType)
8331               argument_list[11].integer_reference;
8332           if (attribute_flag[25] != 0)
8333             {
8334               AV
8335                 *av;
8336
8337               av=(AV *) argument_list[25].array_reference;
8338               if ((av_len(av) != 3) && (av_len(av) != 5))
8339                 {
8340                   ThrowPerlException(exception,OptionError,
8341                     "affine matrix must have 4 or 6 elements",PackageName);
8342                   goto PerlException;
8343                 }
8344               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8345               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8346               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8347               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8348               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8349                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8350                 {
8351                   ThrowPerlException(exception,OptionError,
8352                     "affine matrix is singular",PackageName);
8353                    goto PerlException;
8354                 }
8355               if (av_len(av) == 5)
8356                 {
8357                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8358                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8359                 }
8360             }
8361           for (j=12; j < 17; j++)
8362           {
8363             if (attribute_flag[j] == 0)
8364               continue;
8365             value=argument_list[j].string_reference;
8366             angle=argument_list[j].real_reference;
8367             current=draw_info->affine;
8368             GetAffineMatrix(&affine);
8369             switch (j)
8370             {
8371               case 12:
8372               {
8373                 /*
8374                   Translate.
8375                 */
8376                 flags=ParseGeometry(value,&geometry_info);
8377                 affine.tx=geometry_info.xi;
8378                 affine.ty=geometry_info.psi;
8379                 if ((flags & PsiValue) == 0)
8380                   affine.ty=affine.tx;
8381                 break;
8382               }
8383               case 13:
8384               {
8385                 /*
8386                   Scale.
8387                 */
8388                 flags=ParseGeometry(value,&geometry_info);
8389                 affine.sx=geometry_info.rho;
8390                 affine.sy=geometry_info.sigma;
8391                 if ((flags & SigmaValue) == 0)
8392                   affine.sy=affine.sx;
8393                 break;
8394               }
8395               case 14:
8396               {
8397                 /*
8398                   Rotate.
8399                 */
8400                 if (angle == 0.0)
8401                   break;
8402                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8403                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8404                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8405                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8406                 break;
8407               }
8408               case 15:
8409               {
8410                 /*
8411                   SkewX.
8412                 */
8413                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8414                 break;
8415               }
8416               case 16:
8417               {
8418                 /*
8419                   SkewY.
8420                 */
8421                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8422                 break;
8423               }
8424             }
8425             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8426             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8427             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8428             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8429             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8430               current.tx;
8431             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8432               current.ty;
8433           }
8434           if (attribute_flag[9] == 0)
8435             argument_list[9].real_reference=0.0;
8436           if (attribute_flag[10] == 0)
8437             argument_list[10].real_reference=0.0;
8438           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8439             {
8440               char
8441                 geometry[MaxTextExtent];
8442
8443               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8444                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8445                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8446               (void) CloneString(&draw_info->geometry,geometry);
8447             }
8448           if (attribute_flag[17] != 0)
8449             draw_info->stroke_width=argument_list[17].real_reference;
8450           if (attribute_flag[18] != 0)
8451             {
8452               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8453                 MagickTrue : MagickFalse;
8454               draw_info->stroke_antialias=draw_info->text_antialias;
8455             }
8456           if (attribute_flag[19] != 0)
8457             (void) CloneString(&draw_info->family,
8458               argument_list[19].string_reference);
8459           if (attribute_flag[20] != 0)
8460             draw_info->style=(StyleType) argument_list[20].integer_reference;
8461           if (attribute_flag[21] != 0)
8462             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8463           if (attribute_flag[22] != 0)
8464             draw_info->weight=argument_list[22].integer_reference;
8465           if (attribute_flag[23] != 0)
8466             draw_info->align=(AlignType) argument_list[23].integer_reference;
8467           if (attribute_flag[24] != 0)
8468             (void) CloneString(&draw_info->encoding,
8469               argument_list[24].string_reference);
8470           if (attribute_flag[25] != 0)
8471             draw_info->fill_pattern=CloneImage(
8472               argument_list[25].image_reference,0,0,MagickTrue,exception);
8473           if (attribute_flag[26] != 0)
8474             draw_info->fill_pattern=CloneImage(
8475               argument_list[26].image_reference,0,0,MagickTrue,exception);
8476           if (attribute_flag[27] != 0)
8477             draw_info->stroke_pattern=CloneImage(
8478               argument_list[27].image_reference,0,0,MagickTrue,exception);
8479           if (attribute_flag[29] != 0)
8480             draw_info->kerning=argument_list[29].real_reference;
8481           if (attribute_flag[30] != 0)
8482             draw_info->interline_spacing=argument_list[30].real_reference;
8483           if (attribute_flag[31] != 0)
8484             draw_info->interword_spacing=argument_list[31].real_reference;
8485           if (attribute_flag[32] != 0)
8486             draw_info->direction=(DirectionType)
8487               argument_list[32].integer_reference;
8488           (void) AnnotateImage(image,draw_info,exception);
8489           draw_info=DestroyDrawInfo(draw_info);
8490           break;
8491         }
8492         case 34:  /* ColorFloodfill */
8493         {
8494           DrawInfo
8495             *draw_info;
8496
8497           MagickBooleanType
8498             invert;
8499
8500           PixelInfo
8501             target;
8502
8503           draw_info=CloneDrawInfo(info ? info->image_info :
8504             (ImageInfo *) NULL,(DrawInfo *) NULL);
8505           if (attribute_flag[0] != 0)
8506             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8507               &geometry,exception);
8508           if (attribute_flag[1] != 0)
8509             geometry.x=argument_list[1].integer_reference;
8510           if (attribute_flag[2] != 0)
8511             geometry.y=argument_list[2].integer_reference;
8512           if (attribute_flag[3] != 0)
8513             (void) QueryColorCompliance(argument_list[3].string_reference,
8514               AllCompliance,&draw_info->fill,exception);
8515           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8516             geometry.x,geometry.y,&target,exception);
8517           invert=MagickFalse;
8518           if (attribute_flag[4] != 0)
8519             {
8520               QueryColorCompliance(argument_list[4].string_reference,
8521                 AllCompliance,&target,exception);
8522               invert=MagickTrue;
8523             }
8524           if (attribute_flag[5] != 0)
8525             image->fuzz=StringToDoubleInterval(
8526               argument_list[5].string_reference,(double) QuantumRange+1.0);
8527           if (attribute_flag[6] != 0)
8528             invert=(MagickBooleanType) argument_list[6].integer_reference;
8529           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8530             geometry.y,invert,exception);
8531           draw_info=DestroyDrawInfo(draw_info);
8532           break;
8533         }
8534         case 35:  /* Composite */
8535         {
8536           char
8537             composite_geometry[MaxTextExtent];
8538
8539           Image
8540             *composite_image,
8541             *rotate_image;
8542
8543           MagickBooleanType
8544             clip_to_self;
8545
8546           compose=OverCompositeOp;
8547           if (attribute_flag[0] != 0)
8548             composite_image=argument_list[0].image_reference;
8549           else
8550             {
8551               ThrowPerlException(exception,OptionError,
8552                 "CompositeImageRequired",PackageName);
8553               goto PerlException;
8554             }
8555           /*
8556             Parameter Handling used for BOTH normal and tiled composition.
8557           */
8558           if (attribute_flag[1] != 0) /* compose */
8559             compose=(CompositeOperator) argument_list[1].integer_reference;
8560           if (attribute_flag[6] != 0) /* opacity  */
8561             {
8562               if (compose != DissolveCompositeOp)
8563                 (void) SetImageAlpha(composite_image,(Quantum)
8564                   StringToDoubleInterval(argument_list[6].string_reference,
8565                   (double) QuantumRange+1.0),exception);
8566               else
8567                 {
8568                   CacheView
8569                     *composite_view;
8570
8571                   double
8572                     opacity;
8573
8574                   MagickBooleanType
8575                     sync;
8576
8577                   register ssize_t
8578                     x;
8579
8580                   register Quantum
8581                     *q;
8582
8583                   ssize_t
8584                     y;
8585
8586                   /*
8587                     Handle dissolve composite operator (patch by
8588                     Kevin A. McGrail).
8589                   */
8590                   (void) CloneString(&image->geometry,
8591                     argument_list[6].string_reference);
8592                   opacity=(Quantum) StringToDoubleInterval(
8593                     argument_list[6].string_reference,(double) QuantumRange+
8594                     1.0);
8595                   if (composite_image->alpha_trait == BlendPixelTrait)
8596                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8597                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8598                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8599                   {
8600                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8601                       composite_image->columns,1,exception);
8602                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8603                     {
8604                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8605                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8606                           q);
8607                       q+=GetPixelChannels(composite_image);
8608                     }
8609                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8610                     if (sync == MagickFalse)
8611                       break;
8612                   }
8613                   composite_view=DestroyCacheView(composite_view);
8614                 }
8615             }
8616           if (attribute_flag[9] != 0)    /* "color=>" */
8617             QueryColorCompliance(argument_list[9].string_reference,
8618               AllCompliance,&composite_image->background_color,exception);
8619           if (attribute_flag[12] != 0) /* "interpolate=>" */
8620             image->interpolate=(PixelInterpolateMethod)
8621               argument_list[12].integer_reference;
8622           if (attribute_flag[13] != 0)   /* "args=>" */
8623             (void) SetImageArtifact(composite_image,"compose:args",
8624               argument_list[13].string_reference);
8625           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8626             (void) SetImageArtifact(composite_image,"compose:args",
8627               argument_list[14].string_reference);
8628           clip_to_self=MagickTrue;
8629           if (attribute_flag[15] != 0)
8630             clip_to_self=(MagickBooleanType)
8631               argument_list[15].integer_reference;
8632           /*
8633             Tiling Composition (with orthogonal rotate).
8634           */
8635           rotate_image=(Image *) NULL;
8636           if (attribute_flag[8] != 0)   /* "rotate=>" */
8637             {
8638                /*
8639                  Rotate image.
8640                */
8641                rotate_image=RotateImage(composite_image,
8642                  argument_list[8].real_reference,exception);
8643                if (rotate_image == (Image *) NULL)
8644                  break;
8645             }
8646           if ((attribute_flag[7] != 0) &&
8647               (argument_list[7].integer_reference != 0)) /* tile */
8648             {
8649               ssize_t
8650                 x,
8651                 y;
8652
8653               /*
8654                 Tile the composite image.
8655               */
8656              if (attribute_flag[8] != 0)   /* "tile=>" */
8657                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8658                  "false");
8659              else
8660                (void) SetImageArtifact(composite_image,
8661                  "compose:outside-overlay","false");
8662              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8663                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8664                 {
8665                   if (attribute_flag[8] != 0) /* rotate */
8666                     (void) CompositeImage(image,rotate_image,compose,
8667                       MagickTrue,x,y,exception);
8668                   else
8669                     (void) CompositeImage(image,composite_image,compose,
8670                       MagickTrue,x,y,exception);
8671                 }
8672               if (attribute_flag[8] != 0) /* rotate */
8673                 rotate_image=DestroyImage(rotate_image);
8674               break;
8675             }
8676           /*
8677             Parameter Handling used used ONLY for normal composition.
8678           */
8679           if (attribute_flag[5] != 0) /* gravity */
8680             image->gravity=(GravityType) argument_list[5].integer_reference;
8681           if (attribute_flag[2] != 0) /* geometry offset */
8682             {
8683               SetGeometry(image,&geometry);
8684               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8685                 &geometry);
8686               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8687                 &geometry);
8688             }
8689           if (attribute_flag[3] != 0) /* x offset */
8690             geometry.x=argument_list[3].integer_reference;
8691           if (attribute_flag[4] != 0) /* y offset */
8692             geometry.y=argument_list[4].integer_reference;
8693           if (attribute_flag[10] != 0) /* mask */
8694             {
8695               if ((image->compose == DisplaceCompositeOp) ||
8696                   (image->compose == DistortCompositeOp))
8697                 {
8698                   /*
8699                     Merge Y displacement into X displacement image.
8700                   */
8701                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8702                     exception);
8703                   (void) CompositeImage(composite_image,
8704                     argument_list[10].image_reference,CopyGreenCompositeOp,
8705                     MagickTrue,0,0,exception);
8706                 }
8707               else
8708                 {
8709                   Image
8710                     *mask_image;
8711
8712                   /*
8713                     Set a blending mask for the composition.
8714                   */
8715                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8716                     MagickTrue,exception);
8717                   (void) SetImageMask(composite_image,mask_image,exception);
8718                   mask_image=DestroyImage(mask_image);
8719                 }
8720             }
8721           if (attribute_flag[11] != 0) /* channel */
8722             channel=(ChannelType) argument_list[11].integer_reference;
8723           /*
8724             Composite two images (normal composition).
8725           */
8726           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8727             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8728             (double) composite_image->rows,(double) geometry.x,(double)
8729             geometry.y);
8730           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8731             exception);
8732           channel_mask=SetImageChannelMask(image,channel);
8733           if (attribute_flag[8] == 0) /* no rotate */
8734             CompositeImage(image,composite_image,compose,clip_to_self,
8735               geometry.x,geometry.y,exception);
8736           else
8737             {
8738               /*
8739                 Position adjust rotated image then composite.
8740               */
8741               geometry.x-=(ssize_t) (rotate_image->columns-
8742                 composite_image->columns)/2;
8743               geometry.y-=(ssize_t) (rotate_image->rows-
8744                 composite_image->rows)/2;
8745               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8746                 geometry.y,exception);
8747               rotate_image=DestroyImage(rotate_image);
8748             }
8749           if (attribute_flag[10] != 0) /* mask */
8750             {
8751               if ((image->compose == DisplaceCompositeOp) ||
8752                   (image->compose == DistortCompositeOp))
8753                 composite_image=DestroyImage(composite_image);
8754               else
8755                 (void) SetImageMask(image,(Image *) NULL,exception);
8756             }
8757           (void) SetImageChannelMask(image,channel_mask);
8758           break;
8759         }
8760         case 36:  /* Contrast */
8761         {
8762           if (attribute_flag[0] == 0)
8763             argument_list[0].integer_reference=0;
8764           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8765             MagickTrue : MagickFalse,exception);
8766           break;
8767         }
8768         case 37:  /* CycleColormap */
8769         {
8770           if (attribute_flag[0] == 0)
8771             argument_list[0].integer_reference=6;
8772           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8773             exception);
8774           break;
8775         }
8776         case 38:  /* Draw */
8777         {
8778           DrawInfo
8779             *draw_info;
8780
8781           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8782             (DrawInfo *) NULL);
8783           (void) CloneString(&draw_info->primitive,"point");
8784           if (attribute_flag[0] != 0)
8785             {
8786               if (argument_list[0].integer_reference < 0)
8787                 (void) CloneString(&draw_info->primitive,
8788                   argument_list[0].string_reference);
8789               else
8790                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8791                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8792             }
8793           if (attribute_flag[1] != 0)
8794             {
8795               if (LocaleCompare(draw_info->primitive,"path") == 0)
8796                 {
8797                   (void) ConcatenateString(&draw_info->primitive," '");
8798                   ConcatenateString(&draw_info->primitive,
8799                     argument_list[1].string_reference);
8800                   (void) ConcatenateString(&draw_info->primitive,"'");
8801                 }
8802               else
8803                 {
8804                   (void) ConcatenateString(&draw_info->primitive," ");
8805                   ConcatenateString(&draw_info->primitive,
8806                     argument_list[1].string_reference);
8807                 }
8808             }
8809           if (attribute_flag[2] != 0)
8810             {
8811               (void) ConcatenateString(&draw_info->primitive," ");
8812               (void) ConcatenateString(&draw_info->primitive,
8813                 CommandOptionToMnemonic(MagickMethodOptions,
8814                 argument_list[2].integer_reference));
8815             }
8816           if (attribute_flag[3] != 0)
8817             {
8818               (void) QueryColorCompliance(argument_list[3].string_reference,
8819                 AllCompliance,&draw_info->stroke,exception);
8820               if (argument_list[3].image_reference != (Image *) NULL)
8821                 draw_info->stroke_pattern=CloneImage(
8822                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8823             }
8824           if (attribute_flag[4] != 0)
8825             {
8826               (void) QueryColorCompliance(argument_list[4].string_reference,
8827                 AllCompliance,&draw_info->fill,exception);
8828               if (argument_list[4].image_reference != (Image *) NULL)
8829                 draw_info->fill_pattern=CloneImage(
8830                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8831             }
8832           if (attribute_flag[5] != 0)
8833             draw_info->stroke_width=argument_list[5].real_reference;
8834           if (attribute_flag[6] != 0)
8835             (void) CloneString(&draw_info->font,
8836               argument_list[6].string_reference);
8837           if (attribute_flag[7] != 0)
8838             (void) QueryColorCompliance(argument_list[7].string_reference,
8839               AllCompliance,&draw_info->border_color,exception);
8840           if (attribute_flag[8] != 0)
8841             draw_info->affine.tx=argument_list[8].real_reference;
8842           if (attribute_flag[9] != 0)
8843             draw_info->affine.ty=argument_list[9].real_reference;
8844           if (attribute_flag[20] != 0)
8845             {
8846               AV
8847                 *av;
8848
8849               av=(AV *) argument_list[20].array_reference;
8850               if ((av_len(av) != 3) && (av_len(av) != 5))
8851                 {
8852                   ThrowPerlException(exception,OptionError,
8853                     "affine matrix must have 4 or 6 elements",PackageName);
8854                   goto PerlException;
8855                 }
8856               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8857               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8858               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8859               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8860               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8861                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8862                 {
8863                   ThrowPerlException(exception,OptionError,
8864                     "affine matrix is singular",PackageName);
8865                    goto PerlException;
8866                 }
8867               if (av_len(av) == 5)
8868                 {
8869                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8870                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8871                 }
8872             }
8873           for (j=10; j < 15; j++)
8874           {
8875             if (attribute_flag[j] == 0)
8876               continue;
8877             value=argument_list[j].string_reference;
8878             angle=argument_list[j].real_reference;
8879             current=draw_info->affine;
8880             GetAffineMatrix(&affine);
8881             switch (j)
8882             {
8883               case 10:
8884               {
8885                 /*
8886                   Translate.
8887                 */
8888                 flags=ParseGeometry(value,&geometry_info);
8889                 affine.tx=geometry_info.xi;
8890                 affine.ty=geometry_info.psi;
8891                 if ((flags & PsiValue) == 0)
8892                   affine.ty=affine.tx;
8893                 break;
8894               }
8895               case 11:
8896               {
8897                 /*
8898                   Scale.
8899                 */
8900                 flags=ParseGeometry(value,&geometry_info);
8901                 affine.sx=geometry_info.rho;
8902                 affine.sy=geometry_info.sigma;
8903                 if ((flags & SigmaValue) == 0)
8904                   affine.sy=affine.sx;
8905                 break;
8906               }
8907               case 12:
8908               {
8909                 /*
8910                   Rotate.
8911                 */
8912                 if (angle == 0.0)
8913                   break;
8914                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8915                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8916                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8917                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8918                 break;
8919               }
8920               case 13:
8921               {
8922                 /*
8923                   SkewX.
8924                 */
8925                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8926                 break;
8927               }
8928               case 14:
8929               {
8930                 /*
8931                   SkewY.
8932                 */
8933                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8934                 break;
8935               }
8936             }
8937             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8938             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8939             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8940             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8941             draw_info->affine.tx=
8942               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8943             draw_info->affine.ty=
8944               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8945           }
8946           if (attribute_flag[15] != 0)
8947             draw_info->fill_pattern=CloneImage(
8948               argument_list[15].image_reference,0,0,MagickTrue,exception);
8949           if (attribute_flag[16] != 0)
8950             draw_info->pointsize=argument_list[16].real_reference;
8951           if (attribute_flag[17] != 0)
8952             {
8953               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8954                 ? MagickTrue : MagickFalse;
8955               draw_info->text_antialias=draw_info->stroke_antialias;
8956             }
8957           if (attribute_flag[18] != 0)
8958             (void) CloneString(&draw_info->density,
8959               argument_list[18].string_reference);
8960           if (attribute_flag[19] != 0)
8961             draw_info->stroke_width=argument_list[19].real_reference;
8962           if (attribute_flag[21] != 0)
8963             draw_info->dash_offset=argument_list[21].real_reference;
8964           if (attribute_flag[22] != 0)
8965             {
8966               AV
8967                 *av;
8968
8969               av=(AV *) argument_list[22].array_reference;
8970               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8971                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8972               if (draw_info->dash_pattern != (double *) NULL)
8973                 {
8974                   for (i=0; i <= av_len(av); i++)
8975                     draw_info->dash_pattern[i]=(double)
8976                       SvNV(*(av_fetch(av,i,0)));
8977                   draw_info->dash_pattern[i]=0.0;
8978                 }
8979             }
8980           if (attribute_flag[23] != 0)
8981             image->interpolate=(PixelInterpolateMethod)
8982               argument_list[23].integer_reference;
8983           if ((attribute_flag[24] != 0) &&
8984               (draw_info->fill_pattern != (Image *) NULL))
8985             flags=ParsePageGeometry(draw_info->fill_pattern,
8986               argument_list[24].string_reference,
8987               &draw_info->fill_pattern->tile_offset,exception);
8988           if (attribute_flag[25] != 0)
8989             {
8990               (void) ConcatenateString(&draw_info->primitive," '");
8991               (void) ConcatenateString(&draw_info->primitive,
8992                 argument_list[25].string_reference);
8993               (void) ConcatenateString(&draw_info->primitive,"'");
8994             }
8995           if (attribute_flag[26] != 0)
8996             draw_info->fill_pattern=CloneImage(
8997               argument_list[26].image_reference,0,0,MagickTrue,exception);
8998           if (attribute_flag[27] != 0)
8999             draw_info->stroke_pattern=CloneImage(
9000               argument_list[27].image_reference,0,0,MagickTrue,exception);
9001           if (attribute_flag[28] != 0)
9002             (void) CloneString(&draw_info->primitive,
9003               argument_list[28].string_reference);
9004           if (attribute_flag[29] != 0)
9005             draw_info->kerning=argument_list[29].real_reference;
9006           if (attribute_flag[30] != 0)
9007             draw_info->interline_spacing=argument_list[30].real_reference;
9008           if (attribute_flag[31] != 0)
9009             draw_info->interword_spacing=argument_list[31].real_reference;
9010           if (attribute_flag[32] != 0)
9011             draw_info->direction=(DirectionType)
9012               argument_list[32].integer_reference;
9013           DrawImage(image,draw_info,exception);
9014           draw_info=DestroyDrawInfo(draw_info);
9015           break;
9016         }
9017         case 39:  /* Equalize */
9018         {
9019           if (attribute_flag[0] != 0)
9020             channel=(ChannelType) argument_list[0].integer_reference;
9021           channel_mask=SetImageChannelMask(image,channel);
9022           EqualizeImage(image,exception);
9023           (void) SetImageChannelMask(image,channel_mask);
9024           break;
9025         }
9026         case 40:  /* Gamma */
9027         {
9028           if (attribute_flag[1] != 0)
9029             channel=(ChannelType) argument_list[1].integer_reference;
9030           if (attribute_flag[2] == 0)
9031             argument_list[2].real_reference=1.0;
9032           if (attribute_flag[3] == 0)
9033             argument_list[3].real_reference=1.0;
9034           if (attribute_flag[4] == 0)
9035             argument_list[4].real_reference=1.0;
9036           if (attribute_flag[0] == 0)
9037             {
9038               (void) FormatLocaleString(message,MaxTextExtent,
9039                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9040                 (double) argument_list[3].real_reference,
9041                 (double) argument_list[4].real_reference);
9042               argument_list[0].string_reference=message;
9043             }
9044           (void) GammaImage(image,StringToDouble(
9045             argument_list[0].string_reference,(char **) NULL),exception);
9046           break;
9047         }
9048         case 41:  /* Map */
9049         {
9050           QuantizeInfo
9051             *quantize_info;
9052
9053           if (attribute_flag[0] == 0)
9054             {
9055               ThrowPerlException(exception,OptionError,"MapImageRequired",
9056                 PackageName);
9057               goto PerlException;
9058             }
9059           quantize_info=AcquireQuantizeInfo(info->image_info);
9060           if (attribute_flag[1] != 0)
9061             quantize_info->dither_method=(DitherMethod)
9062               argument_list[1].integer_reference;
9063           (void) RemapImages(quantize_info,image,
9064             argument_list[0].image_reference,exception);
9065           quantize_info=DestroyQuantizeInfo(quantize_info);
9066           break;
9067         }
9068         case 42:  /* MatteFloodfill */
9069         {
9070           DrawInfo
9071             *draw_info;
9072
9073           MagickBooleanType
9074             invert;
9075
9076           PixelInfo
9077             target;
9078
9079           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9080             (DrawInfo *) NULL);
9081           if (attribute_flag[0] != 0)
9082             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9083               &geometry,exception);
9084           if (attribute_flag[1] != 0)
9085             geometry.x=argument_list[1].integer_reference;
9086           if (attribute_flag[2] != 0)
9087             geometry.y=argument_list[2].integer_reference;
9088           if (image->alpha_trait != BlendPixelTrait)
9089             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9090           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9091             geometry.x,geometry.y,&target,exception);
9092           if (attribute_flag[4] != 0)
9093             QueryColorCompliance(argument_list[4].string_reference,
9094               AllCompliance,&target,exception);
9095           if (attribute_flag[3] != 0)
9096             target.alpha=StringToDoubleInterval(
9097               argument_list[3].string_reference,(double) (double) QuantumRange+
9098               1.0);
9099           if (attribute_flag[5] != 0)
9100             image->fuzz=StringToDoubleInterval(
9101               argument_list[5].string_reference,(double) QuantumRange+1.0);
9102           invert=MagickFalse;
9103           if (attribute_flag[6] != 0)
9104             invert=(MagickBooleanType) argument_list[6].integer_reference;
9105           channel_mask=SetImageChannelMask(image,AlphaChannel);
9106           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9107             geometry.y,invert,exception);
9108           (void) SetImageChannelMask(image,channel_mask);
9109           draw_info=DestroyDrawInfo(draw_info);
9110           break;
9111         }
9112         case 43:  /* Modulate */
9113         {
9114           char
9115             modulate[MaxTextExtent];
9116
9117           geometry_info.rho=100.0;
9118           geometry_info.sigma=100.0;
9119           geometry_info.xi=100.0;
9120           if (attribute_flag[0] != 0)
9121             (void)ParseGeometry(argument_list[0].string_reference,
9122               &geometry_info);
9123           if (attribute_flag[1] != 0)
9124             geometry_info.xi=argument_list[1].real_reference;
9125           if (attribute_flag[2] != 0)
9126             geometry_info.sigma=argument_list[2].real_reference;
9127           if (attribute_flag[3] != 0)
9128             {
9129               geometry_info.sigma=argument_list[3].real_reference;
9130               SetImageArtifact(image,"modulate:colorspace","HWB");
9131             }
9132           if (attribute_flag[4] != 0)
9133             {
9134               geometry_info.rho=argument_list[4].real_reference;
9135               SetImageArtifact(image,"modulate:colorspace","HSB");
9136             }
9137           if (attribute_flag[5] != 0)
9138             {
9139               geometry_info.sigma=argument_list[5].real_reference;
9140               SetImageArtifact(image,"modulate:colorspace","HSL");
9141             }
9142           if (attribute_flag[6] != 0)
9143             {
9144               geometry_info.rho=argument_list[6].real_reference;
9145               SetImageArtifact(image,"modulate:colorspace","HWB");
9146             }
9147           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
9148             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9149           (void) ModulateImage(image,modulate,exception);
9150           break;
9151         }
9152         case 44:  /* Negate */
9153         {
9154           if (attribute_flag[0] == 0)
9155             argument_list[0].integer_reference=0;
9156           if (attribute_flag[1] != 0)
9157             channel=(ChannelType) argument_list[1].integer_reference;
9158           channel_mask=SetImageChannelMask(image,channel);
9159           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9160             MagickTrue : MagickFalse,exception);
9161           (void) SetImageChannelMask(image,channel_mask);
9162           break;
9163         }
9164         case 45:  /* Normalize */
9165         {
9166           if (attribute_flag[0] != 0)
9167             channel=(ChannelType) argument_list[0].integer_reference;
9168           channel_mask=SetImageChannelMask(image,channel);
9169           NormalizeImage(image,exception);
9170           (void) SetImageChannelMask(image,channel_mask);
9171           break;
9172         }
9173         case 46:  /* NumberColors */
9174           break;
9175         case 47:  /* Opaque */
9176         {
9177           MagickBooleanType
9178             invert;
9179
9180           PixelInfo
9181             fill_color,
9182             target;
9183
9184           (void) QueryColorCompliance("none",AllCompliance,&target,
9185              exception);
9186           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9187             exception);
9188           if (attribute_flag[0] != 0)
9189             (void) QueryColorCompliance(argument_list[0].string_reference,
9190               AllCompliance,&target,exception);
9191           if (attribute_flag[1] != 0)
9192             (void) QueryColorCompliance(argument_list[1].string_reference,
9193               AllCompliance,&fill_color,exception);
9194           if (attribute_flag[2] != 0)
9195             image->fuzz=StringToDoubleInterval(
9196               argument_list[2].string_reference,(double) QuantumRange+1.0);
9197           if (attribute_flag[3] != 0)
9198             channel=(ChannelType) argument_list[3].integer_reference;
9199           invert=MagickFalse;
9200           if (attribute_flag[4] != 0)
9201             invert=(MagickBooleanType) argument_list[4].integer_reference;
9202           channel_mask=SetImageChannelMask(image,channel);
9203           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9204           (void) SetImageChannelMask(image,channel_mask);
9205           break;
9206         }
9207         case 48:  /* Quantize */
9208         {
9209           QuantizeInfo
9210             *quantize_info;
9211
9212           quantize_info=AcquireQuantizeInfo(info->image_info);
9213           if (attribute_flag[0] != 0)
9214             quantize_info->number_colors=(size_t)
9215               argument_list[0].integer_reference;
9216           if (attribute_flag[1] != 0)
9217             quantize_info->tree_depth=(size_t)
9218               argument_list[1].integer_reference;
9219           if (attribute_flag[2] != 0)
9220             quantize_info->colorspace=(ColorspaceType)
9221               argument_list[2].integer_reference;
9222           if (attribute_flag[3] != 0)
9223             quantize_info->dither_method=(DitherMethod)
9224               argument_list[3].integer_reference;
9225               MagickTrue : MagickFalse;
9226           if (attribute_flag[4] != 0)
9227             quantize_info->measure_error=
9228               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9229           if (attribute_flag[6] != 0)
9230             (void) QueryColorCompliance(argument_list[6].string_reference,
9231               &image->transparent_color,exception);
9232           if (attribute_flag[7] != 0)
9233             quantize_info->dither_method=(DitherMethod)
9234               argument_list[7].integer_reference;
9235           if (attribute_flag[5] && argument_list[5].integer_reference)
9236               (void) QuantizeImages(quantize_info,image,exception);
9237           else if ((image->storage_class == DirectClass) ||
9238               (image->colors > quantize_info->number_colors) ||
9239               (quantize_info->colorspace == GRAYColorspace))
9240             (void) QuantizeImage(quantize_info,image,exception);
9241           else
9242             CompressImageColormap(image,exception);
9243           quantize_info=DestroyQuantizeInfo(quantize_info);
9244           break;
9245         }
9246         case 49:  /* Raise */
9247         {
9248           if (attribute_flag[0] != 0)
9249             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9250               &geometry,exception);
9251           if (attribute_flag[1] != 0)
9252             geometry.width=argument_list[1].integer_reference;
9253           if (attribute_flag[2] != 0)
9254             geometry.height=argument_list[2].integer_reference;
9255           if (attribute_flag[3] == 0)
9256             argument_list[3].integer_reference=1;
9257           (void) RaiseImage(image,&geometry,
9258             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9259             exception);
9260           break;
9261         }
9262         case 50:  /* Segment */
9263         {
9264           ColorspaceType
9265             colorspace;
9266
9267           double
9268             cluster_threshold,
9269             smoothing_threshold;
9270
9271           MagickBooleanType
9272             verbose;
9273
9274           cluster_threshold=1.0;
9275           smoothing_threshold=1.5;
9276           colorspace=sRGBColorspace;
9277           verbose=MagickFalse;
9278           if (attribute_flag[0] != 0)
9279             {
9280               flags=ParseGeometry(argument_list[0].string_reference,
9281                 &geometry_info);
9282               cluster_threshold=geometry_info.rho;
9283               if (flags & SigmaValue)
9284                 smoothing_threshold=geometry_info.sigma;
9285             }
9286           if (attribute_flag[1] != 0)
9287             cluster_threshold=argument_list[1].real_reference;
9288           if (attribute_flag[2] != 0)
9289             smoothing_threshold=argument_list[2].real_reference;
9290           if (attribute_flag[3] != 0)
9291             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9292           if (attribute_flag[4] != 0)
9293             verbose=argument_list[4].integer_reference != 0 ?
9294               MagickTrue : MagickFalse;
9295           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9296             smoothing_threshold,exception);
9297           break;
9298         }
9299         case 51:  /* Signature */
9300         {
9301           (void) SignatureImage(image,exception);
9302           break;
9303         }
9304         case 52:  /* Solarize */
9305         {
9306           geometry_info.rho=QuantumRange/2.0;
9307           if (attribute_flag[0] != 0)
9308             flags=ParseGeometry(argument_list[0].string_reference,
9309               &geometry_info);
9310           if (attribute_flag[1] != 0)
9311             geometry_info.rho=StringToDoubleInterval(
9312               argument_list[1].string_reference,(double) QuantumRange+1.0);
9313           (void) SolarizeImage(image,geometry_info.rho,exception);
9314           break;
9315         }
9316         case 53:  /* Sync */
9317         {
9318           (void) SyncImage(image,exception);
9319           break;
9320         }
9321         case 54:  /* Texture */
9322         {
9323           if (attribute_flag[0] == 0)
9324             break;
9325           TextureImage(image,argument_list[0].image_reference,exception);
9326           break;
9327         }
9328         case 55:  /* Evalute */
9329         {
9330           MagickEvaluateOperator
9331             op;
9332
9333           op=SetEvaluateOperator;
9334           if (attribute_flag[0] == MagickFalse)
9335             argument_list[0].real_reference=0.0;
9336           if (attribute_flag[1] != MagickFalse)
9337             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9338           if (attribute_flag[2] != MagickFalse)
9339             channel=(ChannelType) argument_list[2].integer_reference;
9340           channel_mask=SetImageChannelMask(image,channel);
9341           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9342             exception);
9343           (void) SetImageChannelMask(image,channel_mask);
9344           break;
9345         }
9346         case 56:  /* Transparent */
9347         {
9348           double
9349             opacity;
9350
9351           MagickBooleanType
9352             invert;
9353
9354           PixelInfo
9355             target;
9356
9357           (void) QueryColorCompliance("none",AllCompliance,&target,
9358             exception);
9359           if (attribute_flag[0] != 0)
9360             (void) QueryColorCompliance(argument_list[0].string_reference,
9361               AllCompliance,&target,exception);
9362           opacity=TransparentAlpha;
9363           if (attribute_flag[1] != 0)
9364             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9365               (double) QuantumRange+1.0);
9366           if (attribute_flag[2] != 0)
9367             image->fuzz=StringToDoubleInterval(
9368               argument_list[2].string_reference,(double) QuantumRange+1.0);
9369           if (attribute_flag[3] == 0)
9370             argument_list[3].integer_reference=0;
9371           invert=MagickFalse;
9372           if (attribute_flag[3] != 0)
9373             invert=(MagickBooleanType) argument_list[3].integer_reference;
9374           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9375             invert,exception);
9376           break;
9377         }
9378         case 57:  /* Threshold */
9379         {
9380           double
9381             threshold;
9382
9383           if (attribute_flag[0] == 0)
9384             argument_list[0].string_reference="50%";
9385           if (attribute_flag[1] != 0)
9386             channel=(ChannelType) argument_list[1].integer_reference;
9387           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9388             (double) QuantumRange+1.0);
9389           channel_mask=SetImageChannelMask(image,channel);
9390           (void) BilevelImage(image,threshold,exception);
9391           (void) SetImageChannelMask(image,channel_mask);
9392           break;
9393         }
9394         case 58:  /* Charcoal */
9395         {
9396           if (attribute_flag[0] != 0)
9397             {
9398               flags=ParseGeometry(argument_list[0].string_reference,
9399                 &geometry_info);
9400               if ((flags & SigmaValue) == 0)
9401                 geometry_info.sigma=1.0;
9402             }
9403           if (attribute_flag[1] != 0)
9404             geometry_info.rho=argument_list[1].real_reference;
9405           if (attribute_flag[2] != 0)
9406             geometry_info.sigma=argument_list[2].real_reference;
9407           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9408             exception);
9409           break;
9410         }
9411         case 59:  /* Trim */
9412         {
9413           if (attribute_flag[0] != 0)
9414             image->fuzz=StringToDoubleInterval(
9415               argument_list[0].string_reference,(double) QuantumRange+1.0);
9416           image=TrimImage(image,exception);
9417           break;
9418         }
9419         case 60:  /* Wave */
9420         {
9421           PixelInterpolateMethod
9422             method;
9423
9424           if (attribute_flag[0] != 0)
9425             {
9426               flags=ParseGeometry(argument_list[0].string_reference,
9427                 &geometry_info);
9428               if ((flags & SigmaValue) == 0)
9429                 geometry_info.sigma=1.0;
9430             }
9431           if (attribute_flag[1] != 0)
9432             geometry_info.rho=argument_list[1].real_reference;
9433           if (attribute_flag[2] != 0)
9434             geometry_info.sigma=argument_list[2].real_reference;
9435           method=UndefinedInterpolatePixel;
9436           if (attribute_flag[3] != 0)
9437             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9438           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9439             method,exception);
9440           break;
9441         }
9442         case 61:  /* Separate */
9443         {
9444           if (attribute_flag[0] != 0)
9445             channel=(ChannelType) argument_list[0].integer_reference;
9446           image=SeparateImage(image,channel,exception);
9447           break;
9448         }
9449         case 63:  /* Stereo */
9450         {
9451           if (attribute_flag[0] == 0)
9452             {
9453               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9454                 PackageName);
9455               goto PerlException;
9456             }
9457           if (attribute_flag[1] != 0)
9458             geometry.x=argument_list[1].integer_reference;
9459           if (attribute_flag[2] != 0)
9460             geometry.y=argument_list[2].integer_reference;
9461           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9462             geometry.x,geometry.y,exception);
9463           break;
9464         }
9465         case 64:  /* Stegano */
9466         {
9467           if (attribute_flag[0] == 0)
9468             {
9469               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9470                 PackageName);
9471               goto PerlException;
9472             }
9473           if (attribute_flag[1] == 0)
9474             argument_list[1].integer_reference=0;
9475           image->offset=argument_list[1].integer_reference;
9476           image=SteganoImage(image,argument_list[0].image_reference,exception);
9477           break;
9478         }
9479         case 65:  /* Deconstruct */
9480         {
9481           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9482           break;
9483         }
9484         case 66:  /* GaussianBlur */
9485         {
9486           if (attribute_flag[0] != 0)
9487             {
9488               flags=ParseGeometry(argument_list[0].string_reference,
9489                 &geometry_info);
9490               if ((flags & SigmaValue) == 0)
9491                 geometry_info.sigma=1.0;
9492             }
9493           if (attribute_flag[1] != 0)
9494             geometry_info.rho=argument_list[1].real_reference;
9495           if (attribute_flag[2] != 0)
9496             geometry_info.sigma=argument_list[2].real_reference;
9497           if (attribute_flag[3] != 0)
9498             channel=(ChannelType) argument_list[3].integer_reference;
9499           channel_mask=SetImageChannelMask(image,channel);
9500           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9501             exception);
9502           if (image != (Image *) NULL)
9503             (void) SetImageChannelMask(image,channel_mask);
9504           break;
9505         }
9506         case 67:  /* Convolve */
9507         {
9508           KernelInfo
9509             *kernel;
9510
9511           kernel=(KernelInfo *) NULL;
9512           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9513             break;
9514           if (attribute_flag[0] != 0)
9515             {
9516               AV
9517                 *av;
9518
9519               size_t
9520                 order;
9521
9522               kernel=AcquireKernelInfo((const char *) NULL);
9523               if (kernel == (KernelInfo *) NULL)
9524                 break;
9525               av=(AV *) argument_list[0].array_reference;
9526               order=(size_t) sqrt(av_len(av)+1);
9527               kernel->width=order;
9528               kernel->height=order;
9529               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9530                 order*sizeof(*kernel->values));
9531               if (kernel->values == (MagickRealType *) NULL)
9532                 {
9533                   kernel=DestroyKernelInfo(kernel);
9534                   ThrowPerlException(exception,ResourceLimitFatalError,
9535                     "MemoryAllocationFailed",PackageName);
9536                   goto PerlException;
9537                 }
9538               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9539                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9540               for ( ; j < (ssize_t) (order*order); j++)
9541                 kernel->values[j]=0.0;
9542             }
9543           if (attribute_flag[1] != 0)
9544             channel=(ChannelType) argument_list[1].integer_reference;
9545           if (attribute_flag[2] != 0)
9546             SetImageArtifact(image,"filter:blur",
9547               argument_list[2].string_reference);
9548           if (attribute_flag[3] != 0)
9549             {
9550               kernel=AcquireKernelInfo(argument_list[3].string_reference);
9551               if (kernel == (KernelInfo *) NULL)
9552                 break;
9553             }
9554           channel_mask=SetImageChannelMask(image,channel);
9555           image=ConvolveImage(image,kernel,exception);
9556           if (image != (Image *) NULL)
9557             (void) SetImageChannelMask(image,channel_mask);
9558           kernel=DestroyKernelInfo(kernel);
9559           break;
9560         }
9561         case 68:  /* Profile */
9562         {
9563           const char
9564             *name;
9565
9566           Image
9567             *profile_image;
9568
9569           ImageInfo
9570             *profile_info;
9571
9572           StringInfo
9573             *profile;
9574
9575           name="*";
9576           if (attribute_flag[0] != 0)
9577             name=argument_list[0].string_reference;
9578           if (attribute_flag[2] != 0)
9579             image->rendering_intent=(RenderingIntent)
9580               argument_list[2].integer_reference;
9581           if (attribute_flag[3] != 0)
9582             image->black_point_compensation=
9583               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9584           if (attribute_flag[1] != 0)
9585             {
9586               if (argument_list[1].length == 0)
9587                 {
9588                   /*
9589                     Remove a profile from the image.
9590                   */
9591                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9592                     exception);
9593                   break;
9594                 }
9595               /*
9596                 Associate user supplied profile with the image.
9597               */
9598               profile=AcquireStringInfo(argument_list[1].length);
9599               SetStringInfoDatum(profile,(const unsigned char *)
9600                 argument_list[1].string_reference);
9601               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9602                 (size_t) GetStringInfoLength(profile),exception);
9603               profile=DestroyStringInfo(profile);
9604               break;
9605             }
9606           /*
9607             Associate a profile with the image.
9608           */
9609           profile_info=CloneImageInfo(info ? info->image_info :
9610             (ImageInfo *) NULL);
9611           profile_image=ReadImages(profile_info,name,exception);
9612           if (profile_image == (Image *) NULL)
9613             break;
9614           ResetImageProfileIterator(profile_image);
9615           name=GetNextImageProfile(profile_image);
9616           while (name != (const char *) NULL)
9617           {
9618             const StringInfo
9619               *profile;
9620
9621             profile=GetImageProfile(profile_image,name);
9622             if (profile != (const StringInfo *) NULL)
9623               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9624                 (size_t) GetStringInfoLength(profile),exception);
9625             name=GetNextImageProfile(profile_image);
9626           }
9627           profile_image=DestroyImage(profile_image);
9628           profile_info=DestroyImageInfo(profile_info);
9629           break;
9630         }
9631         case 69:  /* UnsharpMask */
9632         {
9633           if (attribute_flag[0] != 0)
9634             {
9635               flags=ParseGeometry(argument_list[0].string_reference,
9636                 &geometry_info);
9637               if ((flags & SigmaValue) == 0)
9638                 geometry_info.sigma=1.0;
9639               if ((flags & XiValue) == 0)
9640                 geometry_info.xi=1.0;
9641               if ((flags & PsiValue) == 0)
9642                 geometry_info.psi=0.5;
9643             }
9644           if (attribute_flag[1] != 0)
9645             geometry_info.rho=argument_list[1].real_reference;
9646           if (attribute_flag[2] != 0)
9647             geometry_info.sigma=argument_list[2].real_reference;
9648           if (attribute_flag[3] != 0)
9649             geometry_info.xi=argument_list[3].real_reference;
9650           if (attribute_flag[4] != 0)
9651             geometry_info.psi=argument_list[4].real_reference;
9652           if (attribute_flag[5] != 0)
9653             channel=(ChannelType) argument_list[5].integer_reference;
9654           channel_mask=SetImageChannelMask(image,channel);
9655           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9656             geometry_info.xi,geometry_info.psi,exception);
9657           if (image != (Image *) NULL)
9658             (void) SetImageChannelMask(image,channel_mask);
9659           break;
9660         }
9661         case 70:  /* MotionBlur */
9662         {
9663           if (attribute_flag[0] != 0)
9664             {
9665               flags=ParseGeometry(argument_list[0].string_reference,
9666                 &geometry_info);
9667               if ((flags & SigmaValue) == 0)
9668                 geometry_info.sigma=1.0;
9669               if ((flags & XiValue) == 0)
9670                 geometry_info.xi=1.0;
9671             }
9672           if (attribute_flag[1] != 0)
9673             geometry_info.rho=argument_list[1].real_reference;
9674           if (attribute_flag[2] != 0)
9675             geometry_info.sigma=argument_list[2].real_reference;
9676           if (attribute_flag[3] != 0)
9677             geometry_info.xi=argument_list[3].real_reference;
9678           if (attribute_flag[4] != 0)
9679             channel=(ChannelType) argument_list[4].integer_reference;
9680           channel_mask=SetImageChannelMask(image,channel);
9681           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9682             geometry_info.xi,exception);
9683           if (image != (Image *) NULL)
9684             (void) SetImageChannelMask(image,channel_mask);
9685           break;
9686         }
9687         case 71:  /* OrderedDither */
9688         {
9689           if (attribute_flag[0] == 0)
9690             argument_list[0].string_reference="o8x8";
9691           if (attribute_flag[1] != 0)
9692             channel=(ChannelType) argument_list[1].integer_reference;
9693           channel_mask=SetImageChannelMask(image,channel);
9694           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9695             exception);
9696           (void) SetImageChannelMask(image,channel_mask);
9697           break;
9698         }
9699         case 72:  /* Shave */
9700         {
9701           if (attribute_flag[0] != 0)
9702             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9703               &geometry,exception);
9704           if (attribute_flag[1] != 0)
9705             geometry.width=argument_list[1].integer_reference;
9706           if (attribute_flag[2] != 0)
9707             geometry.height=argument_list[2].integer_reference;
9708           image=ShaveImage(image,&geometry,exception);
9709           break;
9710         }
9711         case 73:  /* Level */
9712         {
9713           double
9714             black_point,
9715             gamma,
9716             white_point;
9717
9718           black_point=0.0;
9719           white_point=(double) image->columns*image->rows;
9720           gamma=1.0;
9721           if (attribute_flag[0] != 0)
9722             {
9723               flags=ParseGeometry(argument_list[0].string_reference,
9724                 &geometry_info);
9725               black_point=geometry_info.rho;
9726               if ((flags & SigmaValue) != 0)
9727                 white_point=geometry_info.sigma;
9728               if ((flags & XiValue) != 0)
9729                 gamma=geometry_info.xi;
9730               if ((flags & PercentValue) != 0)
9731                 {
9732                   black_point*=(double) (QuantumRange/100.0);
9733                   white_point*=(double) (QuantumRange/100.0);
9734                 }
9735               if ((flags & SigmaValue) == 0)
9736                 white_point=(double) QuantumRange-black_point;
9737             }
9738           if (attribute_flag[1] != 0)
9739             black_point=argument_list[1].real_reference;
9740           if (attribute_flag[2] != 0)
9741             white_point=argument_list[2].real_reference;
9742           if (attribute_flag[3] != 0)
9743             gamma=argument_list[3].real_reference;
9744           if (attribute_flag[4] != 0)
9745             channel=(ChannelType) argument_list[4].integer_reference;
9746           if (attribute_flag[5] != 0)
9747             {
9748               argument_list[0].real_reference=argument_list[5].real_reference;
9749               attribute_flag[0]=attribute_flag[5];
9750             }
9751           channel_mask=SetImageChannelMask(image,channel);
9752           (void) LevelImage(image,black_point,white_point,gamma,exception);
9753           (void) SetImageChannelMask(image,channel_mask);
9754           break;
9755         }
9756         case 74:  /* Clip */
9757         {
9758           if (attribute_flag[0] == 0)
9759             argument_list[0].string_reference="#1";
9760           if (attribute_flag[1] == 0)
9761             argument_list[1].integer_reference=MagickTrue;
9762           (void) ClipImagePath(image,argument_list[0].string_reference,
9763             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9764             exception);
9765           break;
9766         }
9767         case 75:  /* AffineTransform */
9768         {
9769           DrawInfo
9770             *draw_info;
9771
9772           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9773             (DrawInfo *) NULL);
9774           if (attribute_flag[0] != 0)
9775             {
9776               AV
9777                 *av;
9778
9779               av=(AV *) argument_list[0].array_reference;
9780               if ((av_len(av) != 3) && (av_len(av) != 5))
9781                 {
9782                   ThrowPerlException(exception,OptionError,
9783                     "affine matrix must have 4 or 6 elements",PackageName);
9784                   goto PerlException;
9785                 }
9786               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9787               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9788               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9789               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9790               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9791                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9792                 {
9793                   ThrowPerlException(exception,OptionError,
9794                     "affine matrix is singular",PackageName);
9795                    goto PerlException;
9796                 }
9797               if (av_len(av) == 5)
9798                 {
9799                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9800                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9801                 }
9802             }
9803           for (j=1; j < 6; j++)
9804           {
9805             if (attribute_flag[j] == 0)
9806               continue;
9807             value=argument_list[j].string_reference;
9808             angle=argument_list[j].real_reference;
9809             current=draw_info->affine;
9810             GetAffineMatrix(&affine);
9811             switch (j)
9812             {
9813               case 1:
9814               {
9815                 /*
9816                   Translate.
9817                 */
9818                 flags=ParseGeometry(value,&geometry_info);
9819                 affine.tx=geometry_info.xi;
9820                 affine.ty=geometry_info.psi;
9821                 if ((flags & PsiValue) == 0)
9822                   affine.ty=affine.tx;
9823                 break;
9824               }
9825               case 2:
9826               {
9827                 /*
9828                   Scale.
9829                 */
9830                 flags=ParseGeometry(value,&geometry_info);
9831                 affine.sx=geometry_info.rho;
9832                 affine.sy=geometry_info.sigma;
9833                 if ((flags & SigmaValue) == 0)
9834                   affine.sy=affine.sx;
9835                 break;
9836               }
9837               case 3:
9838               {
9839                 /*
9840                   Rotate.
9841                 */
9842                 if (angle == 0.0)
9843                   break;
9844                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9845                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9846                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9847                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9848                 break;
9849               }
9850               case 4:
9851               {
9852                 /*
9853                   SkewX.
9854                 */
9855                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9856                 break;
9857               }
9858               case 5:
9859               {
9860                 /*
9861                   SkewY.
9862                 */
9863                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9864                 break;
9865               }
9866             }
9867             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9868             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9869             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9870             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9871             draw_info->affine.tx=
9872               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9873             draw_info->affine.ty=
9874               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9875           }
9876           if (attribute_flag[6] != 0)
9877             image->interpolate=(PixelInterpolateMethod)
9878               argument_list[6].integer_reference;
9879           if (attribute_flag[7] != 0)
9880             QueryColorCompliance(argument_list[7].string_reference,
9881               AllCompliance,&image->background_color,exception);
9882           image=AffineTransformImage(image,&draw_info->affine,exception);
9883           draw_info=DestroyDrawInfo(draw_info);
9884           break;
9885         }
9886         case 76:  /* Difference */
9887         {
9888           if (attribute_flag[0] == 0)
9889             {
9890               ThrowPerlException(exception,OptionError,
9891                 "ReferenceImageRequired",PackageName);
9892               goto PerlException;
9893             }
9894           if (attribute_flag[1] != 0)
9895             image->fuzz=StringToDoubleInterval(
9896               argument_list[1].string_reference,(double) QuantumRange+1.0);
9897           (void) IsImagesEqual(image,argument_list[0].image_reference,
9898             exception);
9899           break;
9900         }
9901         case 77:  /* AdaptiveThreshold */
9902         {
9903           if (attribute_flag[0] != 0)
9904             {
9905               flags=ParseGeometry(argument_list[0].string_reference,
9906                 &geometry_info);
9907               if ((flags & PercentValue) != 0)
9908                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9909             }
9910           if (attribute_flag[1] != 0)
9911             geometry_info.rho=argument_list[1].integer_reference;
9912           if (attribute_flag[2] != 0)
9913             geometry_info.sigma=argument_list[2].integer_reference;
9914           if (attribute_flag[3] != 0)
9915             geometry_info.xi=argument_list[3].integer_reference;;
9916           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9917             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9918           break;
9919         }
9920         case 78:  /* Resample */
9921         {
9922           size_t
9923             height,
9924             width;
9925
9926           if (attribute_flag[0] != 0)
9927             {
9928               flags=ParseGeometry(argument_list[0].string_reference,
9929                 &geometry_info);
9930               if ((flags & SigmaValue) == 0)
9931                 geometry_info.sigma=geometry_info.rho;
9932             }
9933           if (attribute_flag[1] != 0)
9934             geometry_info.rho=argument_list[1].real_reference;
9935           if (attribute_flag[2] != 0)
9936             geometry_info.sigma=argument_list[2].real_reference;
9937           if (attribute_flag[3] == 0)
9938             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9939           if (attribute_flag[4] == 0)
9940             SetImageArtifact(image,"filter:support",
9941               argument_list[4].string_reference);
9942           width=(size_t) (geometry_info.rho*image->columns/
9943             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9944           height=(size_t) (geometry_info.sigma*image->rows/
9945             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9946           image=ResizeImage(image,width,height,(FilterTypes)
9947             argument_list[3].integer_reference,exception);
9948           if (image != (Image *) NULL)
9949             {
9950               image->resolution.x=geometry_info.rho;
9951               image->resolution.y=geometry_info.sigma;
9952             }
9953           break;
9954         }
9955         case 79:  /* Describe */
9956         {
9957           if (attribute_flag[0] == 0)
9958             argument_list[0].file_reference=(FILE *) NULL;
9959           if (attribute_flag[1] != 0)
9960             (void) SetImageArtifact(image,"identify:features",
9961               argument_list[1].string_reference);
9962           (void) IdentifyImage(image,argument_list[0].file_reference,
9963             MagickTrue,exception);
9964           break;
9965         }
9966         case 80:  /* BlackThreshold */
9967         {
9968           if (attribute_flag[0] == 0)
9969             argument_list[0].string_reference="50%";
9970           if (attribute_flag[2] != 0)
9971             channel=(ChannelType) argument_list[2].integer_reference;
9972           channel_mask=SetImageChannelMask(image,channel);
9973           BlackThresholdImage(image,argument_list[0].string_reference,
9974             exception);
9975           (void) SetImageChannelMask(image,channel_mask);
9976           break;
9977         }
9978         case 81:  /* WhiteThreshold */
9979         {
9980           if (attribute_flag[0] == 0)
9981             argument_list[0].string_reference="50%";
9982           if (attribute_flag[2] != 0)
9983             channel=(ChannelType) argument_list[2].integer_reference;
9984           channel_mask=SetImageChannelMask(image,channel);
9985           WhiteThresholdImage(image,argument_list[0].string_reference,
9986             exception);
9987           (void) SetImageChannelMask(image,channel_mask);
9988           break;
9989         }
9990         case 82:  /* RadialBlur */
9991         {
9992           if (attribute_flag[0] != 0)
9993             {
9994               flags=ParseGeometry(argument_list[0].string_reference,
9995                 &geometry_info);
9996             }
9997           if (attribute_flag[1] != 0)
9998             geometry_info.rho=argument_list[1].real_reference;
9999           if (attribute_flag[2] != 0)
10000             channel=(ChannelType) argument_list[2].integer_reference;
10001           channel_mask=SetImageChannelMask(image,channel);
10002           image=RotationalBlurImage(image,geometry_info.rho,exception);
10003           if (image != (Image *) NULL)
10004             (void) SetImageChannelMask(image,channel_mask);
10005           break;
10006         }
10007         case 83:  /* Thumbnail */
10008         {
10009           if (attribute_flag[0] != 0)
10010             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10011               &geometry,exception);
10012           if (attribute_flag[1] != 0)
10013             geometry.width=argument_list[1].integer_reference;
10014           if (attribute_flag[2] != 0)
10015             geometry.height=argument_list[2].integer_reference;
10016           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10017           break;
10018         }
10019         case 84:  /* Strip */
10020         {
10021           (void) StripImage(image,exception);
10022           break;
10023         }
10024         case 85:  /* Tint */
10025         {
10026           PixelInfo
10027             tint;
10028
10029           GetPixelInfo(image,&tint);
10030           if (attribute_flag[0] != 0)
10031             (void) QueryColorCompliance(argument_list[0].string_reference,
10032               AllCompliance,&tint,exception);
10033           if (attribute_flag[1] == 0)
10034             argument_list[1].string_reference="100";
10035           image=TintImage(image,argument_list[1].string_reference,&tint,
10036             exception);
10037           break;
10038         }
10039         case 86:  /* Channel */
10040         {
10041           if (attribute_flag[0] != 0)
10042             channel=(ChannelType) argument_list[0].integer_reference;
10043           image=SeparateImage(image,channel,exception);
10044           break;
10045         }
10046         case 87:  /* Splice */
10047         {
10048           if (attribute_flag[0] != 0)
10049             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10050               &geometry,exception);
10051           if (attribute_flag[1] != 0)
10052             geometry.width=argument_list[1].integer_reference;
10053           if (attribute_flag[2] != 0)
10054             geometry.height=argument_list[2].integer_reference;
10055           if (attribute_flag[3] != 0)
10056             geometry.x=argument_list[3].integer_reference;
10057           if (attribute_flag[4] != 0)
10058             geometry.y=argument_list[4].integer_reference;
10059           if (attribute_flag[5] != 0)
10060             image->fuzz=StringToDoubleInterval(
10061               argument_list[5].string_reference,(double) QuantumRange+1.0);
10062           if (attribute_flag[6] != 0)
10063             (void) QueryColorCompliance(argument_list[6].string_reference,
10064               AllCompliance,&image->background_color,exception);
10065           if (attribute_flag[7] != 0)
10066             image->gravity=(GravityType) argument_list[7].integer_reference;
10067           image=SpliceImage(image,&geometry,exception);
10068           break;
10069         }
10070         case 88:  /* Posterize */
10071         {
10072           if (attribute_flag[0] == 0)
10073             argument_list[0].integer_reference=3;
10074           if (attribute_flag[1] == 0)
10075             argument_list[1].integer_reference=0;
10076           (void) PosterizeImage(image,argument_list[0].integer_reference,
10077             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10078             NoDitherMethod,exception);
10079           break;
10080         }
10081         case 89:  /* Shadow */
10082         {
10083           if (attribute_flag[0] != 0)
10084             {
10085               flags=ParseGeometry(argument_list[0].string_reference,
10086                 &geometry_info);
10087               if ((flags & SigmaValue) == 0)
10088                 geometry_info.sigma=1.0;
10089               if ((flags & XiValue) == 0)
10090                 geometry_info.xi=4.0;
10091               if ((flags & PsiValue) == 0)
10092                 geometry_info.psi=4.0;
10093             }
10094           if (attribute_flag[1] != 0)
10095             geometry_info.rho=argument_list[1].real_reference;
10096           if (attribute_flag[2] != 0)
10097             geometry_info.sigma=argument_list[2].real_reference;
10098           if (attribute_flag[3] != 0)
10099             geometry_info.xi=argument_list[3].integer_reference;
10100           if (attribute_flag[4] != 0)
10101             geometry_info.psi=argument_list[4].integer_reference;
10102           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10103             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10104             ceil(geometry_info.psi-0.5),exception);
10105           break;
10106         }
10107         case 90:  /* Identify */
10108         {
10109           if (attribute_flag[0] == 0)
10110             argument_list[0].file_reference=(FILE *) NULL;
10111           if (attribute_flag[1] != 0)
10112             (void) SetImageArtifact(image,"identify:features",
10113               argument_list[1].string_reference);
10114           if ((attribute_flag[2] != 0) &&
10115               (argument_list[2].integer_reference != 0))
10116             (void) SetImageArtifact(image,"identify:unique","true");
10117           (void) IdentifyImage(image,argument_list[0].file_reference,
10118             MagickTrue,exception);
10119           break;
10120         }
10121         case 91:  /* SepiaTone */
10122         {
10123           if (attribute_flag[0] == 0)
10124             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10125           image=SepiaToneImage(image,argument_list[0].real_reference,
10126             exception);
10127           break;
10128         }
10129         case 92:  /* SigmoidalContrast */
10130         {
10131           MagickBooleanType
10132             sharpen;
10133
10134           if (attribute_flag[0] != 0)
10135             {
10136               flags=ParseGeometry(argument_list[0].string_reference,
10137                 &geometry_info);
10138               if ((flags & SigmaValue) == 0)
10139                 geometry_info.sigma=QuantumRange/2.0;
10140               if ((flags & PercentValue) != 0)
10141                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10142             }
10143           if (attribute_flag[1] != 0)
10144             geometry_info.rho=argument_list[1].real_reference;
10145           if (attribute_flag[2] != 0)
10146             geometry_info.sigma=argument_list[2].real_reference;
10147           if (attribute_flag[3] != 0)
10148             channel=(ChannelType) argument_list[3].integer_reference;
10149           sharpen=MagickTrue;
10150           if (attribute_flag[4] != 0)
10151             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10152               MagickFalse;
10153           channel_mask=SetImageChannelMask(image,channel);
10154           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10155             geometry_info.sigma,exception);
10156           (void) SetImageChannelMask(image,channel_mask);
10157           break;
10158         }
10159         case 93:  /* Extent */
10160         {
10161           if (attribute_flag[7] != 0)
10162             image->gravity=(GravityType) argument_list[7].integer_reference;
10163           if (attribute_flag[0] != 0)
10164             {
10165               int
10166                 flags;
10167
10168               flags=ParseGravityGeometry(image,
10169                 argument_list[0].string_reference,&geometry,exception);
10170               (void) flags;
10171               if (geometry.width == 0)
10172                 geometry.width=image->columns;
10173               if (geometry.height == 0)
10174                 geometry.height=image->rows;
10175             }
10176           if (attribute_flag[1] != 0)
10177             geometry.width=argument_list[1].integer_reference;
10178           if (attribute_flag[2] != 0)
10179             geometry.height=argument_list[2].integer_reference;
10180           if (attribute_flag[3] != 0)
10181             geometry.x=argument_list[3].integer_reference;
10182           if (attribute_flag[4] != 0)
10183             geometry.y=argument_list[4].integer_reference;
10184           if (attribute_flag[5] != 0)
10185             image->fuzz=StringToDoubleInterval(
10186               argument_list[5].string_reference,(double) QuantumRange+1.0);
10187           if (attribute_flag[6] != 0)
10188             (void) QueryColorCompliance(argument_list[6].string_reference,
10189               AllCompliance,&image->background_color,exception);
10190           image=ExtentImage(image,&geometry,exception);
10191           break;
10192         }
10193         case 94:  /* Vignette */
10194         {
10195           if (attribute_flag[0] != 0)
10196             {
10197               flags=ParseGeometry(argument_list[0].string_reference,
10198                 &geometry_info);
10199               if ((flags & SigmaValue) == 0)
10200                 geometry_info.sigma=1.0;
10201               if ((flags & XiValue) == 0)
10202                 geometry_info.xi=0.1*image->columns;
10203               if ((flags & PsiValue) == 0)
10204                 geometry_info.psi=0.1*image->rows;
10205             }
10206           if (attribute_flag[1] != 0)
10207             geometry_info.rho=argument_list[1].real_reference;
10208           if (attribute_flag[2] != 0)
10209             geometry_info.sigma=argument_list[2].real_reference;
10210           if (attribute_flag[3] != 0)
10211             geometry_info.xi=argument_list[3].integer_reference;
10212           if (attribute_flag[4] != 0)
10213             geometry_info.psi=argument_list[4].integer_reference;
10214           if (attribute_flag[5] != 0)
10215             (void) QueryColorCompliance(argument_list[5].string_reference,
10216               AllCompliance,&image->background_color,exception);
10217           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10218             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10219             ceil(geometry_info.psi-0.5),exception);
10220           break;
10221         }
10222         case 95:  /* ContrastStretch */
10223         {
10224           double
10225             black_point,
10226             white_point;
10227
10228           black_point=0.0;
10229           white_point=(double) image->columns*image->rows;
10230           if (attribute_flag[0] != 0)
10231             {
10232               flags=ParseGeometry(argument_list[0].string_reference,
10233                 &geometry_info);
10234               black_point=geometry_info.rho;
10235               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10236                 black_point;
10237               if ((flags & PercentValue) != 0)
10238                 {
10239                   black_point*=(double) image->columns*image->rows/100.0;
10240                   white_point*=(double) image->columns*image->rows/100.0;
10241                 }
10242               white_point=(double) image->columns*image->rows-
10243                 white_point;
10244             }
10245           if (attribute_flag[1] != 0)
10246             black_point=argument_list[1].real_reference;
10247           if (attribute_flag[2] != 0)
10248             white_point=argument_list[2].real_reference;
10249           if (attribute_flag[4] != 0)
10250             channel=(ChannelType) argument_list[4].integer_reference;
10251           channel_mask=SetImageChannelMask(image,channel);
10252           (void) ContrastStretchImage(image,black_point,white_point,exception);
10253           (void) SetImageChannelMask(image,channel_mask);
10254           break;
10255         }
10256         case 96:  /* Sans0 */
10257         {
10258           break;
10259         }
10260         case 97:  /* Sans1 */
10261         {
10262           break;
10263         }
10264         case 98:  /* AdaptiveSharpen */
10265         {
10266           if (attribute_flag[0] != 0)
10267             {
10268               flags=ParseGeometry(argument_list[0].string_reference,
10269                 &geometry_info);
10270               if ((flags & SigmaValue) == 0)
10271                 geometry_info.sigma=1.0;
10272               if ((flags & XiValue) == 0)
10273                 geometry_info.xi=0.0;
10274             }
10275           if (attribute_flag[1] != 0)
10276             geometry_info.rho=argument_list[1].real_reference;
10277           if (attribute_flag[2] != 0)
10278             geometry_info.sigma=argument_list[2].real_reference;
10279           if (attribute_flag[3] != 0)
10280             geometry_info.xi=argument_list[3].real_reference;
10281           if (attribute_flag[4] != 0)
10282             channel=(ChannelType) argument_list[4].integer_reference;
10283           channel_mask=SetImageChannelMask(image,channel);
10284           image=AdaptiveSharpenImage(image,geometry_info.rho,
10285             geometry_info.sigma,exception);
10286           if (image != (Image *) NULL)
10287             (void) SetImageChannelMask(image,channel_mask);
10288           break;
10289         }
10290         case 99:  /* Transpose */
10291         {
10292           image=TransposeImage(image,exception);
10293           break;
10294         }
10295         case 100:  /* Tranverse */
10296         {
10297           image=TransverseImage(image,exception);
10298           break;
10299         }
10300         case 101:  /* AutoOrient */
10301         {
10302           image=AutoOrientImage(image,image->orientation,exception);
10303           break;
10304         }
10305         case 102:  /* AdaptiveBlur */
10306         {
10307           if (attribute_flag[0] != 0)
10308             {
10309               flags=ParseGeometry(argument_list[0].string_reference,
10310                 &geometry_info);
10311               if ((flags & SigmaValue) == 0)
10312                 geometry_info.sigma=1.0;
10313               if ((flags & XiValue) == 0)
10314                 geometry_info.xi=0.0;
10315             }
10316           if (attribute_flag[1] != 0)
10317             geometry_info.rho=argument_list[1].real_reference;
10318           if (attribute_flag[2] != 0)
10319             geometry_info.sigma=argument_list[2].real_reference;
10320           if (attribute_flag[3] != 0)
10321             channel=(ChannelType) argument_list[3].integer_reference;
10322           channel_mask=SetImageChannelMask(image,channel);
10323           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10324             exception);
10325           if (image != (Image *) NULL)
10326             (void) SetImageChannelMask(image,channel_mask);
10327           break;
10328         }
10329         case 103:  /* Sketch */
10330         {
10331           if (attribute_flag[0] != 0)
10332             {
10333               flags=ParseGeometry(argument_list[0].string_reference,
10334                 &geometry_info);
10335               if ((flags & SigmaValue) == 0)
10336                 geometry_info.sigma=1.0;
10337               if ((flags & XiValue) == 0)
10338                 geometry_info.xi=1.0;
10339             }
10340           if (attribute_flag[1] != 0)
10341             geometry_info.rho=argument_list[1].real_reference;
10342           if (attribute_flag[2] != 0)
10343             geometry_info.sigma=argument_list[2].real_reference;
10344           if (attribute_flag[3] != 0)
10345             geometry_info.xi=argument_list[3].real_reference;
10346           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10347             geometry_info.xi,exception);
10348           break;
10349         }
10350         case 104:  /* UniqueColors */
10351         {
10352           image=UniqueImageColors(image,exception);
10353           break;
10354         }
10355         case 105:  /* AdaptiveResize */
10356         {
10357           if (attribute_flag[0] != 0)
10358             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10359               &geometry,exception);
10360           if (attribute_flag[1] != 0)
10361             geometry.width=argument_list[1].integer_reference;
10362           if (attribute_flag[2] != 0)
10363             geometry.height=argument_list[2].integer_reference;
10364           if (attribute_flag[3] != 0)
10365             image->filter=(FilterTypes) argument_list[4].integer_reference;
10366           if (attribute_flag[4] != 0)
10367             SetImageArtifact(image,"filter:support",
10368               argument_list[4].string_reference);
10369           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10370             exception);
10371           break;
10372         }
10373         case 106:  /* ClipMask */
10374         {
10375           Image
10376             *mask_image;
10377
10378           if (attribute_flag[0] == 0)
10379             {
10380               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10381                 PackageName);
10382               goto PerlException;
10383             }
10384           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10385             exception);
10386           (void) SetImageMask(image,mask_image,exception);
10387           mask_image=DestroyImage(mask_image);
10388           break;
10389         }
10390         case 107:  /* LinearStretch */
10391         {
10392            double
10393              black_point,
10394              white_point;
10395
10396            black_point=0.0;
10397            white_point=(double) image->columns*image->rows;
10398            if (attribute_flag[0] != 0)
10399              {
10400                flags=ParseGeometry(argument_list[0].string_reference,
10401                  &geometry_info);
10402                if ((flags & SigmaValue) != 0)
10403                   white_point=geometry_info.sigma;
10404                if ((flags & PercentValue) != 0)
10405                  {
10406                    black_point*=(double) image->columns*image->rows/100.0;
10407                    white_point*=(double) image->columns*image->rows/100.0;
10408                  }
10409                if ((flags & SigmaValue) == 0)
10410                  white_point=(double) image->columns*image->rows-black_point;
10411              }
10412           if (attribute_flag[1] != 0)
10413             black_point=argument_list[1].real_reference;
10414           if (attribute_flag[2] != 0)
10415             white_point=argument_list[2].real_reference;
10416           (void) LinearStretchImage(image,black_point,white_point,exception);
10417           break;
10418         }
10419         case 108:  /* ColorMatrix */
10420         {
10421           AV
10422             *av;
10423
10424           double
10425             *color_matrix;
10426
10427           KernelInfo
10428             *kernel_info;
10429
10430           size_t
10431             order;
10432
10433           if (attribute_flag[0] == 0)
10434             break;
10435           av=(AV *) argument_list[0].array_reference;
10436           order=(size_t) sqrt(av_len(av)+1);
10437           color_matrix=(double *) AcquireQuantumMemory(order,order*
10438             sizeof(*color_matrix));
10439           if (color_matrix == (double *) NULL)
10440             {
10441               ThrowPerlException(exception,ResourceLimitFatalError,
10442                 "MemoryAllocationFailed",PackageName);
10443               goto PerlException;
10444            }
10445           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10446             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10447           for ( ; j < (ssize_t) (order*order); j++)
10448             color_matrix[j]=0.0;
10449           kernel_info=AcquireKernelInfo((const char *) NULL);
10450           if (kernel_info == (KernelInfo *) NULL)
10451             break;
10452           kernel_info->width=order;
10453           kernel_info->height=order;
10454           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10455             order*sizeof(*kernel_info->values));
10456           if (kernel_info->values != (MagickRealType *) NULL)
10457             {
10458               for (i=0; i < (ssize_t) (order*order); i++)
10459                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10460               image=ColorMatrixImage(image,kernel_info,exception);
10461             }
10462           kernel_info=DestroyKernelInfo(kernel_info);
10463           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10464           break;
10465         }
10466         case 109:  /* Mask */
10467         {
10468           Image
10469             *mask_image;
10470
10471           if (attribute_flag[0] == 0)
10472             {
10473               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10474                 PackageName);
10475               goto PerlException;
10476             }
10477           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10478             MagickTrue,exception);
10479           (void) SetImageMask(image,mask_image,exception);
10480           mask_image=DestroyImage(mask_image);
10481           break;
10482         }
10483         case 110:  /* Polaroid */
10484         {
10485           char
10486             *caption;
10487
10488           DrawInfo
10489             *draw_info;
10490
10491           double
10492             angle;
10493
10494           PixelInterpolateMethod
10495             method;
10496
10497           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10498             (DrawInfo *) NULL);
10499           caption=(char *) NULL;
10500           if (attribute_flag[0] != 0)
10501             caption=InterpretImageProperties(info ? info->image_info :
10502               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10503               exception);
10504           angle=0.0;
10505           if (attribute_flag[1] != 0)
10506             angle=argument_list[1].real_reference;
10507           if (attribute_flag[2] != 0)
10508             (void) CloneString(&draw_info->font,
10509               argument_list[2].string_reference);
10510           if (attribute_flag[3] != 0)
10511             (void) QueryColorCompliance(argument_list[3].string_reference,
10512               AllCompliance,&draw_info->stroke,exception);
10513           if (attribute_flag[4] != 0)
10514             (void) QueryColorCompliance(argument_list[4].string_reference,
10515               AllCompliance,&draw_info->fill,exception);
10516           if (attribute_flag[5] != 0)
10517             draw_info->stroke_width=argument_list[5].real_reference;
10518           if (attribute_flag[6] != 0)
10519             draw_info->pointsize=argument_list[6].real_reference;
10520           if (attribute_flag[7] != 0)
10521             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10522           if (attribute_flag[8] != 0)
10523             (void) QueryColorCompliance(argument_list[8].string_reference,
10524               AllCompliance,&image->background_color,exception);
10525           method=UndefinedInterpolatePixel;
10526           if (attribute_flag[9] != 0)
10527             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10528           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10529           draw_info=DestroyDrawInfo(draw_info);
10530           if (caption != (char *) NULL)
10531             caption=DestroyString(caption);
10532           break;
10533         }
10534         case 111:  /* FloodfillPaint */
10535         {
10536           DrawInfo
10537             *draw_info;
10538
10539           MagickBooleanType
10540             invert;
10541
10542           PixelInfo
10543             target;
10544
10545           draw_info=CloneDrawInfo(info ? info->image_info :
10546             (ImageInfo *) NULL,(DrawInfo *) NULL);
10547           if (attribute_flag[0] != 0)
10548             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10549               &geometry,exception);
10550           if (attribute_flag[1] != 0)
10551             geometry.x=argument_list[1].integer_reference;
10552           if (attribute_flag[2] != 0)
10553             geometry.y=argument_list[2].integer_reference;
10554           if (attribute_flag[3] != 0)
10555             (void) QueryColorCompliance(argument_list[3].string_reference,
10556               AllCompliance,&draw_info->fill,exception);
10557           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10558             geometry.x,geometry.y,&target,exception);
10559           if (attribute_flag[4] != 0)
10560             QueryColorCompliance(argument_list[4].string_reference,
10561               AllCompliance,&target,exception);
10562           if (attribute_flag[5] != 0)
10563             image->fuzz=StringToDoubleInterval(
10564               argument_list[5].string_reference,(double) QuantumRange+1.0);
10565           if (attribute_flag[6] != 0)
10566             channel=(ChannelType) argument_list[6].integer_reference;
10567           invert=MagickFalse;
10568           if (attribute_flag[7] != 0)
10569             invert=(MagickBooleanType) argument_list[7].integer_reference;
10570           channel_mask=SetImageChannelMask(image,channel);
10571           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10572             geometry.y,invert,exception);
10573           (void) SetImageChannelMask(image,channel_mask);
10574           draw_info=DestroyDrawInfo(draw_info);
10575           break;
10576         }
10577         case 112:  /* Distort */
10578         {
10579           AV
10580             *av;
10581
10582           double
10583             *coordinates;
10584
10585           DistortImageMethod
10586             method;
10587
10588           size_t
10589             number_coordinates;
10590
10591           VirtualPixelMethod
10592             virtual_pixel;
10593
10594           if (attribute_flag[0] == 0)
10595             break;
10596           method=UndefinedDistortion;
10597           if (attribute_flag[1] != 0)
10598             method=(DistortImageMethod) argument_list[1].integer_reference;
10599           av=(AV *) argument_list[0].array_reference;
10600           number_coordinates=(size_t) av_len(av)+1;
10601           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10602             sizeof(*coordinates));
10603           if (coordinates == (double *) NULL)
10604             {
10605               ThrowPerlException(exception,ResourceLimitFatalError,
10606                 "MemoryAllocationFailed",PackageName);
10607               goto PerlException;
10608             }
10609           for (j=0; j < (ssize_t) number_coordinates; j++)
10610             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10611           virtual_pixel=UndefinedVirtualPixelMethod;
10612           if (attribute_flag[2] != 0)
10613             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10614               argument_list[2].integer_reference,exception);
10615           image=DistortImage(image,method,number_coordinates,coordinates,
10616             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10617             exception);
10618           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10619             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10620               exception);
10621           coordinates=(double *) RelinquishMagickMemory(coordinates);
10622           break;
10623         }
10624         case 113:  /* Clut */
10625         {
10626           PixelInterpolateMethod
10627             method;
10628
10629           if (attribute_flag[0] == 0)
10630             {
10631               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10632                 PackageName);
10633               goto PerlException;
10634             }
10635           method=UndefinedInterpolatePixel;
10636           if (attribute_flag[1] != 0)
10637             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10638           if (attribute_flag[2] != 0)
10639             channel=(ChannelType) argument_list[2].integer_reference;
10640           channel_mask=SetImageChannelMask(image,channel);
10641           (void) ClutImage(image,argument_list[0].image_reference,method,
10642             exception);
10643           (void) SetImageChannelMask(image,channel_mask);
10644           break;
10645         }
10646         case 114:  /* LiquidRescale */
10647         {
10648           if (attribute_flag[0] != 0)
10649             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10650               &geometry,exception);
10651           if (attribute_flag[1] != 0)
10652             geometry.width=argument_list[1].integer_reference;
10653           if (attribute_flag[2] != 0)
10654             geometry.height=argument_list[2].integer_reference;
10655           if (attribute_flag[3] == 0)
10656             argument_list[3].real_reference=1.0;
10657           if (attribute_flag[4] == 0)
10658             argument_list[4].real_reference=0.0;
10659           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10660             argument_list[3].real_reference,argument_list[4].real_reference,
10661             exception);
10662           break;
10663         }
10664         case 115:  /* EncipherImage */
10665         {
10666           (void) EncipherImage(image,argument_list[0].string_reference,
10667             exception);
10668           break;
10669         }
10670         case 116:  /* DecipherImage */
10671         {
10672           (void) DecipherImage(image,argument_list[0].string_reference,
10673             exception);
10674           break;
10675         }
10676         case 117:  /* Deskew */
10677         {
10678           geometry_info.rho=QuantumRange/2.0;
10679           if (attribute_flag[0] != 0)
10680             flags=ParseGeometry(argument_list[0].string_reference,
10681               &geometry_info);
10682           if (attribute_flag[1] != 0)
10683             geometry_info.rho=StringToDoubleInterval(
10684               argument_list[1].string_reference,(double) QuantumRange+1.0);
10685           image=DeskewImage(image,geometry_info.rho,exception);
10686           break;
10687         }
10688         case 118:  /* Remap */
10689         {
10690           QuantizeInfo
10691             *quantize_info;
10692
10693           if (attribute_flag[0] == 0)
10694             {
10695               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10696                 PackageName);
10697               goto PerlException;
10698             }
10699           quantize_info=AcquireQuantizeInfo(info->image_info);
10700           if (attribute_flag[1] != 0)
10701             quantize_info->dither_method=(DitherMethod)
10702               argument_list[1].integer_reference;
10703           (void) RemapImages(quantize_info,image,
10704             argument_list[0].image_reference,exception);
10705           quantize_info=DestroyQuantizeInfo(quantize_info);
10706           break;
10707         }
10708         case 119:  /* SparseColor */
10709         {
10710           AV
10711             *av;
10712
10713           double
10714             *coordinates;
10715
10716           SparseColorMethod
10717             method;
10718
10719           size_t
10720             number_coordinates;
10721
10722           VirtualPixelMethod
10723             virtual_pixel;
10724
10725           if (attribute_flag[0] == 0)
10726             break;
10727           method=UndefinedColorInterpolate;
10728           if (attribute_flag[1] != 0)
10729             method=(SparseColorMethod) argument_list[1].integer_reference;
10730           av=(AV *) argument_list[0].array_reference;
10731           number_coordinates=(size_t) av_len(av)+1;
10732           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10733             sizeof(*coordinates));
10734           if (coordinates == (double *) NULL)
10735             {
10736               ThrowPerlException(exception,ResourceLimitFatalError,
10737                 "MemoryAllocationFailed",PackageName);
10738               goto PerlException;
10739             }
10740           for (j=0; j < (ssize_t) number_coordinates; j++)
10741             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10742           virtual_pixel=UndefinedVirtualPixelMethod;
10743           if (attribute_flag[2] != 0)
10744             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10745               argument_list[2].integer_reference,exception);
10746           if (attribute_flag[3] != 0)
10747             channel=(ChannelType) argument_list[3].integer_reference;
10748           channel_mask=SetImageChannelMask(image,channel);
10749           image=SparseColorImage(image,method,number_coordinates,coordinates,
10750             exception);
10751           if (image != (Image *) NULL)
10752             (void) SetImageChannelMask(image,channel_mask);
10753           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10754             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10755               exception);
10756           coordinates=(double *) RelinquishMagickMemory(coordinates);
10757           break;
10758         }
10759         case 120:  /* Function */
10760         {
10761           AV
10762             *av;
10763
10764           double
10765             *parameters;
10766
10767           MagickFunction
10768             function;
10769
10770           size_t
10771             number_parameters;
10772
10773           VirtualPixelMethod
10774             virtual_pixel;
10775
10776           if (attribute_flag[0] == 0)
10777             break;
10778           function=UndefinedFunction;
10779           if (attribute_flag[1] != 0)
10780             function=(MagickFunction) argument_list[1].integer_reference;
10781           av=(AV *) argument_list[0].array_reference;
10782           number_parameters=(size_t) av_len(av)+1;
10783           parameters=(double *) AcquireQuantumMemory(number_parameters,
10784             sizeof(*parameters));
10785           if (parameters == (double *) NULL)
10786             {
10787               ThrowPerlException(exception,ResourceLimitFatalError,
10788                 "MemoryAllocationFailed",PackageName);
10789               goto PerlException;
10790             }
10791           for (j=0; j < (ssize_t) number_parameters; j++)
10792             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10793           virtual_pixel=UndefinedVirtualPixelMethod;
10794           if (attribute_flag[2] != 0)
10795             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10796               argument_list[2].integer_reference,exception);
10797           (void) FunctionImage(image,function,number_parameters,parameters,
10798             exception);
10799           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10800             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10801               exception);
10802           parameters=(double *) RelinquishMagickMemory(parameters);
10803           break;
10804         }
10805         case 121:  /* SelectiveBlur */
10806         {
10807           if (attribute_flag[0] != 0)
10808             {
10809               flags=ParseGeometry(argument_list[0].string_reference,
10810                 &geometry_info);
10811               if ((flags & SigmaValue) == 0)
10812                 geometry_info.sigma=1.0;
10813               if ((flags & PercentValue) != 0)
10814                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10815             }
10816           if (attribute_flag[1] != 0)
10817             geometry_info.rho=argument_list[1].real_reference;
10818           if (attribute_flag[2] != 0)
10819             geometry_info.sigma=argument_list[2].real_reference;
10820           if (attribute_flag[3] != 0)
10821             geometry_info.xi=argument_list[3].integer_reference;;
10822           if (attribute_flag[5] != 0)
10823             channel=(ChannelType) argument_list[5].integer_reference;
10824           channel_mask=SetImageChannelMask(image,channel);
10825           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10826             geometry_info.xi,exception);
10827           if (image != (Image *) NULL)
10828             (void) SetImageChannelMask(image,channel_mask);
10829           break;
10830         }
10831         case 122:  /* HaldClut */
10832         {
10833           if (attribute_flag[0] == 0)
10834             {
10835               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10836                 PackageName);
10837               goto PerlException;
10838             }
10839           if (attribute_flag[1] != 0)
10840             channel=(ChannelType) argument_list[1].integer_reference;
10841           channel_mask=SetImageChannelMask(image,channel);
10842           (void) HaldClutImage(image,argument_list[0].image_reference,
10843             exception);
10844           (void) SetImageChannelMask(image,channel_mask);
10845           break;
10846         }
10847         case 123:  /* BlueShift */
10848         {
10849           if (attribute_flag[0] != 0)
10850             (void) ParseGeometry(argument_list[0].string_reference,
10851               &geometry_info);
10852           image=BlueShiftImage(image,geometry_info.rho,exception);
10853           break;
10854         }
10855         case 124:  /* ForwardFourierTransformImage */
10856         {
10857           image=ForwardFourierTransformImage(image,
10858             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10859             exception);
10860           break;
10861         }
10862         case 125:  /* InverseFourierTransformImage */
10863         {
10864           image=InverseFourierTransformImage(image,image->next,
10865             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10866             exception);
10867           break;
10868         }
10869         case 126:  /* ColorDecisionList */
10870         {
10871           if (attribute_flag[0] == 0)
10872             argument_list[0].string_reference=(char *) NULL;
10873           (void) ColorDecisionListImage(image,
10874             argument_list[0].string_reference,exception);
10875           break;
10876         }
10877         case 127:  /* AutoGamma */
10878         {
10879           if (attribute_flag[0] != 0)
10880             channel=(ChannelType) argument_list[0].integer_reference;
10881           channel_mask=SetImageChannelMask(image,channel);
10882           (void) AutoGammaImage(image,exception);
10883           (void) SetImageChannelMask(image,channel_mask);
10884           break;
10885         }
10886         case 128:  /* AutoLevel */
10887         {
10888           if (attribute_flag[0] != 0)
10889             channel=(ChannelType) argument_list[0].integer_reference;
10890           channel_mask=SetImageChannelMask(image,channel);
10891           (void) AutoLevelImage(image,exception);
10892           (void) SetImageChannelMask(image,channel_mask);
10893           break;
10894         }
10895         case 129:  /* LevelColors */
10896         {
10897           PixelInfo
10898             black_point,
10899             white_point;
10900
10901           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10902             exception);
10903           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10904             exception);
10905           if (attribute_flag[1] != 0)
10906              (void) QueryColorCompliance(
10907                argument_list[1].string_reference,AllCompliance,&black_point,
10908                exception);
10909           if (attribute_flag[2] != 0)
10910              (void) QueryColorCompliance(
10911                argument_list[2].string_reference,AllCompliance,&white_point,
10912                exception);
10913           if (attribute_flag[3] != 0)
10914             channel=(ChannelType) argument_list[3].integer_reference;
10915           channel_mask=SetImageChannelMask(image,channel);
10916           (void) LevelImageColors(image,&black_point,&white_point,
10917             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10918             exception);
10919           (void) SetImageChannelMask(image,channel_mask);
10920           break;
10921         }
10922         case 130:  /* Clamp */
10923         {
10924           if (attribute_flag[0] != 0)
10925             channel=(ChannelType) argument_list[0].integer_reference;
10926           channel_mask=SetImageChannelMask(image,channel);
10927           (void) ClampImage(image,exception);
10928           (void) SetImageChannelMask(image,channel_mask);
10929           break;
10930         }
10931         case 131:  /* BrightnessContrast */
10932         {
10933           double
10934             brightness,
10935             contrast;
10936
10937           brightness=0.0;
10938           contrast=0.0;
10939           if (attribute_flag[0] != 0)
10940             {
10941               flags=ParseGeometry(argument_list[0].string_reference,
10942                 &geometry_info);
10943               brightness=geometry_info.rho;
10944               if ((flags & SigmaValue) == 0)
10945                 contrast=geometry_info.sigma;
10946             }
10947           if (attribute_flag[1] != 0)
10948             brightness=argument_list[1].real_reference;
10949           if (attribute_flag[2] != 0)
10950             contrast=argument_list[2].real_reference;
10951           if (attribute_flag[4] != 0)
10952             channel=(ChannelType) argument_list[4].integer_reference;
10953           channel_mask=SetImageChannelMask(image,channel);
10954           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10955           (void) SetImageChannelMask(image,channel_mask);
10956           break;
10957         }
10958         case 132:  /* Morphology */
10959         {
10960           KernelInfo
10961             *kernel;
10962
10963           MorphologyMethod
10964             method;
10965
10966           ssize_t
10967             iterations;
10968
10969           if (attribute_flag[0] == 0)
10970             break;
10971           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10972           if (kernel == (KernelInfo *) NULL)
10973             break;
10974           if (attribute_flag[1] != 0)
10975             channel=(ChannelType) argument_list[1].integer_reference;
10976           method=UndefinedMorphology;
10977           if (attribute_flag[2] != 0)
10978             method=argument_list[2].integer_reference;
10979           iterations=1;
10980           if (attribute_flag[3] != 0)
10981             iterations=argument_list[3].integer_reference;
10982           channel_mask=SetImageChannelMask(image,channel);
10983           image=MorphologyImage(image,method,iterations,kernel,exception);
10984           if (image != (Image *) NULL)
10985             (void) SetImageChannelMask(image,channel_mask);
10986           kernel=DestroyKernelInfo(kernel);
10987           break;
10988         }
10989         case 133:  /* Mode */
10990         {
10991           if (attribute_flag[0] != 0)
10992             {
10993               flags=ParseGeometry(argument_list[0].string_reference,
10994                 &geometry_info);
10995               if ((flags & SigmaValue) == 0)
10996                 geometry_info.sigma=1.0;
10997             }
10998           if (attribute_flag[1] != 0)
10999             geometry_info.rho=argument_list[1].real_reference;
11000           if (attribute_flag[2] != 0)
11001             geometry_info.sigma=argument_list[2].real_reference;
11002           if (attribute_flag[3] != 0)
11003             channel=(ChannelType) argument_list[3].integer_reference;
11004           channel_mask=SetImageChannelMask(image,channel);
11005           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11006             (size_t) geometry_info.sigma,exception);
11007           if (image != (Image *) NULL)
11008             (void) SetImageChannelMask(image,channel_mask);
11009           break;
11010         }
11011         case 134:  /* Statistic */
11012         {
11013           StatisticType
11014             statistic;
11015
11016           statistic=UndefinedStatistic;
11017           if (attribute_flag[0] != 0)
11018             {
11019               flags=ParseGeometry(argument_list[0].string_reference,
11020                 &geometry_info);
11021               if ((flags & SigmaValue) == 0)
11022                 geometry_info.sigma=1.0;
11023             }
11024           if (attribute_flag[1] != 0)
11025             geometry_info.rho=argument_list[1].real_reference;
11026           if (attribute_flag[2] != 0)
11027             geometry_info.sigma=argument_list[2].real_reference;
11028           if (attribute_flag[3] != 0)
11029             channel=(ChannelType) argument_list[3].integer_reference;
11030           if (attribute_flag[4] != 0)
11031             statistic=(StatisticType) argument_list[4].integer_reference;
11032           channel_mask=SetImageChannelMask(image,channel);
11033           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11034             (size_t) geometry_info.sigma,exception);
11035           if (image != (Image *) NULL)
11036             (void) SetImageChannelMask(image,channel_mask);
11037           break;
11038         }
11039         case 135:  /* Perceptible */
11040         {
11041           double
11042             epsilon;
11043
11044           epsilon=MagickEpsilon;
11045           if (attribute_flag[0] != 0)
11046             epsilon=argument_list[0].real_reference;
11047           if (attribute_flag[1] != 0)
11048             channel=(ChannelType) argument_list[1].integer_reference;
11049           channel_mask=SetImageChannelMask(image,channel);
11050           (void) PerceptibleImage(image,epsilon,exception);
11051           (void) SetImageChannelMask(image,channel_mask);
11052           break;
11053         }
11054         case 136:  /* Poly */
11055         {
11056           AV
11057             *av;
11058
11059           double
11060             *terms;
11061
11062           size_t
11063             number_terms;
11064
11065           if (attribute_flag[0] == 0)
11066             break;
11067           if (attribute_flag[1] != 0)
11068             channel=(ChannelType) argument_list[1].integer_reference;
11069           av=(AV *) argument_list[0].array_reference;
11070           number_terms=(size_t) av_len(av);
11071           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11072           if (terms == (double *) NULL)
11073             {
11074               ThrowPerlException(exception,ResourceLimitFatalError,
11075                 "MemoryAllocationFailed",PackageName);
11076               goto PerlException;
11077             }
11078           for (j=0; j < av_len(av); j++)
11079             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11080           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11081           terms=(double *) RelinquishMagickMemory(terms);
11082           break;
11083         }
11084         case 137:  /* Grayscale */
11085         {
11086           PixelIntensityMethod
11087             method;
11088
11089           method=UndefinedPixelIntensityMethod;
11090           if (attribute_flag[0] != 0)
11091             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11092           (void) GrayscaleImage(image,method,exception);
11093           break;
11094         }
11095       }
11096       if (next != (Image *) NULL)
11097         (void) CatchImageException(next);
11098       if (region_image != (Image *) NULL)
11099         {
11100           /*
11101             Composite region.
11102           */
11103           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11104             region_info.x,region_info.y,exception);
11105           (void) status;
11106           (void) CatchImageException(region_image);
11107           image=DestroyImage(image);
11108           image=region_image;
11109         }
11110       if (image != (Image *) NULL)
11111         {
11112           number_images++;
11113           if (next && (next != image))
11114             {
11115               image->next=next->next;
11116               if (image->next != (Image *) NULL)
11117                 image->next->previous=image;
11118               DeleteImageFromRegistry(*pv,next);
11119             }
11120           sv_setiv(*pv,PTR2IV(image));
11121           next=image;
11122         }
11123       if (*pv)
11124         pv++;
11125     }
11126
11127   PerlException:
11128     if (reference_vector)
11129       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11130     InheritPerlException(exception,perl_exception);
11131     exception=DestroyExceptionInfo(exception);
11132     sv_setiv(perl_exception,(IV) number_images);
11133     SvPOK_on(perl_exception);
11134     ST(0)=sv_2mortal(perl_exception);
11135     XSRETURN(1);
11136   }
11137 \f
11138 #
11139 ###############################################################################
11140 #                                                                             #
11141 #                                                                             #
11142 #                                                                             #
11143 #   M o n t a g e                                                             #
11144 #                                                                             #
11145 #                                                                             #
11146 #                                                                             #
11147 ###############################################################################
11148 #
11149 #
11150 void
11151 Montage(ref,...)
11152   Image::Magick ref=NO_INIT
11153   ALIAS:
11154     MontageImage  = 1
11155     montage       = 2
11156     montageimage  = 3
11157   PPCODE:
11158   {
11159     AV
11160       *av;
11161
11162     char
11163       *attribute;
11164
11165     ExceptionInfo
11166       *exception;
11167
11168     HV
11169       *hv;
11170
11171     Image
11172       *image,
11173       *next;
11174
11175     PixelInfo
11176       transparent_color;
11177
11178     MontageInfo
11179       *montage_info;
11180
11181     register ssize_t
11182       i;
11183
11184     ssize_t
11185       sp;
11186
11187     struct PackageInfo
11188       *info;
11189
11190     SV
11191       *av_reference,
11192       *perl_exception,
11193       *reference,
11194       *rv,
11195       *sv;
11196
11197     PERL_UNUSED_VAR(ref);
11198     PERL_UNUSED_VAR(ix);
11199     exception=AcquireExceptionInfo();
11200     perl_exception=newSVpv("",0);
11201     sv=NULL;
11202     attribute=NULL;
11203     if (sv_isobject(ST(0)) == 0)
11204       {
11205         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11206           PackageName);
11207         goto PerlException;
11208       }
11209     reference=SvRV(ST(0));
11210     hv=SvSTASH(reference);
11211     av=newAV();
11212     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11213     SvREFCNT_dec(av);
11214     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11215     if (image == (Image *) NULL)
11216       {
11217         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11218           PackageName);
11219         goto PerlException;
11220       }
11221     /*
11222       Get options.
11223     */
11224     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11225     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11226     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11227       exception);
11228     for (i=2; i < items; i+=2)
11229     {
11230       attribute=(char *) SvPV(ST(i-1),na);
11231       switch (*attribute)
11232       {
11233         case 'B':
11234         case 'b':
11235         {
11236           if (LocaleCompare(attribute,"background") == 0)
11237             {
11238               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11239                 &montage_info->background_color,exception);
11240               for (next=image; next; next=next->next)
11241                 next->background_color=montage_info->background_color;
11242               break;
11243             }
11244           if (LocaleCompare(attribute,"border") == 0)
11245             {
11246               montage_info->border_width=SvIV(ST(i));
11247               break;
11248             }
11249           if (LocaleCompare(attribute,"bordercolor") == 0)
11250             {
11251               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11252                 &montage_info->border_color,exception);
11253               for (next=image; next; next=next->next)
11254                 next->border_color=montage_info->border_color;
11255               break;
11256             }
11257           if (LocaleCompare(attribute,"borderwidth") == 0)
11258             {
11259               montage_info->border_width=SvIV(ST(i));
11260               break;
11261             }
11262           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11263             attribute);
11264           break;
11265         }
11266         case 'C':
11267         case 'c':
11268         {
11269           if (LocaleCompare(attribute,"compose") == 0)
11270             {
11271               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11272                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11273               if (sp < 0)
11274                 {
11275                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11276                     SvPV(ST(i),na));
11277                   break;
11278                 }
11279               for (next=image; next; next=next->next)
11280                 next->compose=(CompositeOperator) sp;
11281               break;
11282             }
11283           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11284             attribute);
11285           break;
11286         }
11287         case 'F':
11288         case 'f':
11289         {
11290           if (LocaleCompare(attribute,"fill") == 0)
11291             {
11292               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11293                 &montage_info->fill,exception);
11294               break;
11295             }
11296           if (LocaleCompare(attribute,"font") == 0)
11297             {
11298               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11299               break;
11300             }
11301           if (LocaleCompare(attribute,"frame") == 0)
11302             {
11303               char
11304                 *p;
11305
11306               p=SvPV(ST(i),na);
11307               if (IsGeometry(p) == MagickFalse)
11308                 {
11309                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11310                     p);
11311                   break;
11312                 }
11313               (void) CloneString(&montage_info->frame,p);
11314               if (*p == '\0')
11315                 montage_info->frame=(char *) NULL;
11316               break;
11317             }
11318           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11319             attribute);
11320           break;
11321         }
11322         case 'G':
11323         case 'g':
11324         {
11325           if (LocaleCompare(attribute,"geometry") == 0)
11326             {
11327               char
11328                 *p;
11329
11330               p=SvPV(ST(i),na);
11331               if (IsGeometry(p) == MagickFalse)
11332                 {
11333                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11334                     p);
11335                   break;
11336                 }
11337              (void) CloneString(&montage_info->geometry,p);
11338              if (*p == '\0')
11339                montage_info->geometry=(char *) NULL;
11340              break;
11341            }
11342          if (LocaleCompare(attribute,"gravity") == 0)
11343            {
11344              ssize_t
11345                in;
11346
11347              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11348                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11349              if (in < 0)
11350                {
11351                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11352                    SvPV(ST(i),na));
11353                  return;
11354                }
11355              montage_info->gravity=(GravityType) in;
11356              for (next=image; next; next=next->next)
11357                next->gravity=(GravityType) in;
11358              break;
11359            }
11360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11361             attribute);
11362           break;
11363         }
11364         case 'L':
11365         case 'l':
11366         {
11367           if (LocaleCompare(attribute,"label") == 0)
11368             {
11369               for (next=image; next; next=next->next)
11370                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11371                   info ? info->image_info : (ImageInfo *) NULL,next,
11372                   SvPV(ST(i),na),exception),exception);
11373               break;
11374             }
11375           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11376             attribute);
11377           break;
11378         }
11379         case 'M':
11380         case 'm':
11381         {
11382           if (LocaleCompare(attribute,"mattecolor") == 0)
11383             {
11384               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11385                 &montage_info->matte_color,exception);
11386               for (next=image; next; next=next->next)
11387                 next->matte_color=montage_info->matte_color;
11388               break;
11389             }
11390           if (LocaleCompare(attribute,"mode") == 0)
11391             {
11392               ssize_t
11393                 in;
11394
11395               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11396                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11397               switch (in)
11398               {
11399                 default:
11400                 {
11401                   ThrowPerlException(exception,OptionError,
11402                     "UnrecognizedModeType",SvPV(ST(i),na));
11403                   break;
11404                 }
11405                 case FrameMode:
11406                 {
11407                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11408                   montage_info->shadow=MagickTrue;
11409                   break;
11410                 }
11411                 case UnframeMode:
11412                 {
11413                   montage_info->frame=(char *) NULL;
11414                   montage_info->shadow=MagickFalse;
11415                   montage_info->border_width=0;
11416                   break;
11417                 }
11418                 case ConcatenateMode:
11419                 {
11420                   montage_info->frame=(char *) NULL;
11421                   montage_info->shadow=MagickFalse;
11422                   (void) CloneString(&montage_info->geometry,"+0+0");
11423                   montage_info->border_width=0;
11424                 }
11425               }
11426               break;
11427             }
11428           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11429             attribute);
11430           break;
11431         }
11432         case 'P':
11433         case 'p':
11434         {
11435           if (LocaleCompare(attribute,"pointsize") == 0)
11436             {
11437               montage_info->pointsize=SvIV(ST(i));
11438               break;
11439             }
11440           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11441             attribute);
11442           break;
11443         }
11444         case 'S':
11445         case 's':
11446         {
11447           if (LocaleCompare(attribute,"shadow") == 0)
11448             {
11449               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11450                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11451               if (sp < 0)
11452                 {
11453                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11454                     SvPV(ST(i),na));
11455                   break;
11456                 }
11457              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11458              break;
11459             }
11460           if (LocaleCompare(attribute,"stroke") == 0)
11461             {
11462               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11463                 &montage_info->stroke,exception);
11464               break;
11465             }
11466           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11467             attribute);
11468           break;
11469         }
11470         case 'T':
11471         case 't':
11472         {
11473           if (LocaleCompare(attribute,"texture") == 0)
11474             {
11475               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11476               break;
11477             }
11478           if (LocaleCompare(attribute,"tile") == 0)
11479             {
11480               char *p=SvPV(ST(i),na);
11481               if (IsGeometry(p) == MagickFalse)
11482                 {
11483                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11484                     p);
11485                   break;
11486                 }
11487               (void) CloneString(&montage_info->tile,p);
11488               if (*p == '\0')
11489                 montage_info->tile=(char *) NULL;
11490               break;
11491             }
11492           if (LocaleCompare(attribute,"title") == 0)
11493             {
11494               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11495               break;
11496             }
11497           if (LocaleCompare(attribute,"transparent") == 0)
11498             {
11499               PixelInfo
11500                 transparent_color;
11501
11502               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11503                 &transparent_color,exception);
11504               for (next=image; next; next=next->next)
11505                 (void) TransparentPaintImage(next,&transparent_color,
11506                   TransparentAlpha,MagickFalse,exception);
11507               break;
11508             }
11509           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11510             attribute);
11511           break;
11512         }
11513         default:
11514         {
11515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11516             attribute);
11517           break;
11518         }
11519       }
11520     }
11521     image=MontageImageList(info->image_info,montage_info,image,exception);
11522     montage_info=DestroyMontageInfo(montage_info);
11523     if (image == (Image *) NULL)
11524       goto PerlException;
11525     if (transparent_color.alpha != TransparentAlpha)
11526       for (next=image; next; next=next->next)
11527         (void) TransparentPaintImage(next,&transparent_color,
11528           TransparentAlpha,MagickFalse,exception);
11529     for (  ; image; image=image->next)
11530     {
11531       AddImageToRegistry(sv,image);
11532       rv=newRV(sv);
11533       av_push(av,sv_bless(rv,hv));
11534       SvREFCNT_dec(sv);
11535     }
11536     exception=DestroyExceptionInfo(exception);
11537     ST(0)=av_reference;
11538     SvREFCNT_dec(perl_exception);
11539     XSRETURN(1);
11540
11541   PerlException:
11542     InheritPerlException(exception,perl_exception);
11543     exception=DestroyExceptionInfo(exception);
11544     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11545     SvPOK_on(perl_exception);
11546     ST(0)=sv_2mortal(perl_exception);
11547     XSRETURN(1);
11548   }
11549 \f
11550 #
11551 ###############################################################################
11552 #                                                                             #
11553 #                                                                             #
11554 #                                                                             #
11555 #   M o r p h                                                                 #
11556 #                                                                             #
11557 #                                                                             #
11558 #                                                                             #
11559 ###############################################################################
11560 #
11561 #
11562 void
11563 Morph(ref,...)
11564   Image::Magick ref=NO_INIT
11565   ALIAS:
11566     MorphImage  = 1
11567     morph       = 2
11568     morphimage  = 3
11569   PPCODE:
11570   {
11571     AV
11572       *av;
11573
11574     char
11575       *attribute;
11576
11577     ExceptionInfo
11578       *exception;
11579
11580     HV
11581       *hv;
11582
11583     Image
11584       *image;
11585
11586     register ssize_t
11587       i;
11588
11589     ssize_t
11590       number_frames;
11591
11592     struct PackageInfo
11593       *info;
11594
11595     SV
11596       *av_reference,
11597       *perl_exception,
11598       *reference,
11599       *rv,
11600       *sv;
11601
11602     PERL_UNUSED_VAR(ref);
11603     PERL_UNUSED_VAR(ix);
11604     exception=AcquireExceptionInfo();
11605     perl_exception=newSVpv("",0);
11606     sv=NULL;
11607     av=NULL;
11608     attribute=NULL;
11609     if (sv_isobject(ST(0)) == 0)
11610       {
11611         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11612           PackageName);
11613         goto PerlException;
11614       }
11615     reference=SvRV(ST(0));
11616     hv=SvSTASH(reference);
11617     av=newAV();
11618     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11619     SvREFCNT_dec(av);
11620     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11621     if (image == (Image *) NULL)
11622       {
11623         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11624           PackageName);
11625         goto PerlException;
11626       }
11627     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11628     /*
11629       Get attribute.
11630     */
11631     number_frames=30;
11632     for (i=2; i < items; i+=2)
11633     {
11634       attribute=(char *) SvPV(ST(i-1),na);
11635       switch (*attribute)
11636       {
11637         case 'F':
11638         case 'f':
11639         {
11640           if (LocaleCompare(attribute,"frames") == 0)
11641             {
11642               number_frames=SvIV(ST(i));
11643               break;
11644             }
11645           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11646             attribute);
11647           break;
11648         }
11649         default:
11650         {
11651           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11652             attribute);
11653           break;
11654         }
11655       }
11656     }
11657     image=MorphImages(image,number_frames,exception);
11658     if (image == (Image *) NULL)
11659       goto PerlException;
11660     for ( ; image; image=image->next)
11661     {
11662       AddImageToRegistry(sv,image);
11663       rv=newRV(sv);
11664       av_push(av,sv_bless(rv,hv));
11665       SvREFCNT_dec(sv);
11666     }
11667     exception=DestroyExceptionInfo(exception);
11668     ST(0)=av_reference;
11669     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11670     XSRETURN(1);
11671
11672   PerlException:
11673     InheritPerlException(exception,perl_exception);
11674     exception=DestroyExceptionInfo(exception);
11675     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11676     SvPOK_on(perl_exception);
11677     ST(0)=sv_2mortal(perl_exception);
11678     XSRETURN(1);
11679   }
11680 \f
11681 #
11682 ###############################################################################
11683 #                                                                             #
11684 #                                                                             #
11685 #                                                                             #
11686 #   M o s a i c                                                               #
11687 #                                                                             #
11688 #                                                                             #
11689 #                                                                             #
11690 ###############################################################################
11691 #
11692 #
11693 void
11694 Mosaic(ref)
11695   Image::Magick ref=NO_INIT
11696   ALIAS:
11697     MosaicImage   = 1
11698     mosaic        = 2
11699     mosaicimage   = 3
11700   PPCODE:
11701   {
11702     AV
11703       *av;
11704
11705     ExceptionInfo
11706       *exception;
11707
11708     HV
11709       *hv;
11710
11711     Image
11712       *image;
11713
11714     struct PackageInfo
11715       *info;
11716
11717     SV
11718       *perl_exception,
11719       *reference,
11720       *rv,
11721       *sv;
11722
11723     PERL_UNUSED_VAR(ref);
11724     PERL_UNUSED_VAR(ix);
11725     exception=AcquireExceptionInfo();
11726     perl_exception=newSVpv("",0);
11727     sv=NULL;
11728     if (sv_isobject(ST(0)) == 0)
11729       {
11730         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11731           PackageName);
11732         goto PerlException;
11733       }
11734     reference=SvRV(ST(0));
11735     hv=SvSTASH(reference);
11736     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11737     if (image == (Image *) NULL)
11738       {
11739         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11740           PackageName);
11741         goto PerlException;
11742       }
11743     image=MergeImageLayers(image,MosaicLayer,exception);
11744     /*
11745       Create blessed Perl array for the returned image.
11746     */
11747     av=newAV();
11748     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11749     SvREFCNT_dec(av);
11750     AddImageToRegistry(sv,image);
11751     rv=newRV(sv);
11752     av_push(av,sv_bless(rv,hv));
11753     SvREFCNT_dec(sv);
11754     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11755     (void) CopyMagickString(info->image_info->filename,image->filename,
11756       MaxTextExtent);
11757     SetImageInfo(info->image_info,0,exception);
11758     exception=DestroyExceptionInfo(exception);
11759     SvREFCNT_dec(perl_exception);
11760     XSRETURN(1);
11761
11762   PerlException:
11763     InheritPerlException(exception,perl_exception);
11764     exception=DestroyExceptionInfo(exception);
11765     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11766     SvPOK_on(perl_exception);  /* return messages in string context */
11767     ST(0)=sv_2mortal(perl_exception);
11768     XSRETURN(1);
11769   }
11770 \f
11771 #
11772 ###############################################################################
11773 #                                                                             #
11774 #                                                                             #
11775 #                                                                             #
11776 #   P i n g                                                                   #
11777 #                                                                             #
11778 #                                                                             #
11779 #                                                                             #
11780 ###############################################################################
11781 #
11782 #
11783 void
11784 Ping(ref,...)
11785   Image::Magick ref=NO_INIT
11786   ALIAS:
11787     PingImage  = 1
11788     ping       = 2
11789     pingimage  = 3
11790   PPCODE:
11791   {
11792     AV
11793       *av;
11794
11795     char
11796       **keep,
11797       **list;
11798
11799     ExceptionInfo
11800       *exception;
11801
11802     Image
11803       *image,
11804       *next;
11805
11806     int
11807       n;
11808
11809     MagickBooleanType
11810       status;
11811
11812     register char
11813       **p;
11814
11815     register ssize_t
11816       i;
11817
11818     ssize_t
11819       ac;
11820
11821     STRLEN
11822       *length;
11823
11824     struct PackageInfo
11825       *info,
11826       *package_info;
11827
11828     SV
11829       *perl_exception,
11830       *reference;
11831
11832     size_t
11833       count;
11834
11835     PERL_UNUSED_VAR(ref);
11836     PERL_UNUSED_VAR(ix);
11837     exception=AcquireExceptionInfo();
11838     perl_exception=newSVpv("",0);
11839     package_info=(struct PackageInfo *) NULL;
11840     ac=(items < 2) ? 1 : items-1;
11841     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11842     keep=list;
11843     length=(STRLEN *) NULL;
11844     if (list == (char **) NULL)
11845       {
11846         ThrowPerlException(exception,ResourceLimitError,
11847           "MemoryAllocationFailed",PackageName);
11848         goto PerlException;
11849       }
11850     keep=list;
11851     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11852     if (length == (STRLEN *) NULL)
11853       {
11854         ThrowPerlException(exception,ResourceLimitError,
11855           "MemoryAllocationFailed",PackageName);
11856         goto PerlException;
11857       }
11858     if (sv_isobject(ST(0)) == 0)
11859       {
11860         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11861           PackageName);
11862         goto PerlException;
11863       }
11864     reference=SvRV(ST(0));
11865     if (SvTYPE(reference) != SVt_PVAV)
11866       {
11867         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11868           PackageName);
11869         goto PerlException;
11870       }
11871     av=(AV *) reference;
11872     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11873       exception);
11874     package_info=ClonePackageInfo(info,exception);
11875     n=1;
11876     if (items <= 1)
11877       *list=(char *) (*package_info->image_info->filename ?
11878         package_info->image_info->filename : "XC:black");
11879     else
11880       for (n=0, i=0; i < ac; i++)
11881       {
11882         list[n]=(char *) SvPV(ST(i+1),length[n]);
11883         if ((items >= 3) && strEQcase(list[n],"blob"))
11884           {
11885             void
11886               *blob;
11887
11888             i++;
11889             blob=(void *) (SvPV(ST(i+1),length[n]));
11890             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11891           }
11892         if ((items >= 3) && strEQcase(list[n],"filename"))
11893           continue;
11894         if ((items >= 3) && strEQcase(list[n],"file"))
11895           {
11896             FILE
11897               *file;
11898
11899             PerlIO
11900               *io_info;
11901
11902             i++;
11903             io_info=IoIFP(sv_2io(ST(i+1)));
11904             if (io_info == (PerlIO *) NULL)
11905               {
11906                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11907                   PackageName);
11908                 continue;
11909               }
11910             file=PerlIO_findFILE(io_info);
11911             if (file == (FILE *) NULL)
11912               {
11913                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11914                   PackageName);
11915                 continue;
11916               }
11917             SetImageInfoFile(package_info->image_info,file);
11918           }
11919         if ((items >= 3) && strEQcase(list[n],"magick"))
11920           continue;
11921         n++;
11922       }
11923     list[n]=(char *) NULL;
11924     keep=list;
11925     status=ExpandFilenames(&n,&list);
11926     if (status == MagickFalse)
11927       {
11928         ThrowPerlException(exception,ResourceLimitError,
11929           "MemoryAllocationFailed",PackageName);
11930         goto PerlException;
11931       }
11932     count=0;
11933     for (i=0; i < n; i++)
11934     {
11935       (void) CopyMagickString(package_info->image_info->filename,list[i],
11936         MaxTextExtent);
11937       image=PingImage(package_info->image_info,exception);
11938       if (image == (Image *) NULL)
11939         break;
11940       if ((package_info->image_info->file != (FILE *) NULL) ||
11941           (package_info->image_info->blob != (void *) NULL))
11942         DisassociateImageStream(image);
11943       count+=GetImageListLength(image);
11944       EXTEND(sp,4*count);
11945       for (next=image; next; next=next->next)
11946       {
11947         PUSHs(sv_2mortal(newSViv(next->columns)));
11948         PUSHs(sv_2mortal(newSViv(next->rows)));
11949         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11950         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11951       }
11952       image=DestroyImageList(image);
11953     }
11954     /*
11955       Free resources.
11956     */
11957     for (i=0; i < n; i++)
11958       if (list[i] != (char *) NULL)
11959         for (p=keep; list[i] != *p++; )
11960           if (*p == NULL)
11961             {
11962               list[i]=(char *) RelinquishMagickMemory(list[i]);
11963               break;
11964             }
11965
11966   PerlException:
11967     if (package_info != (struct PackageInfo *) NULL)
11968       DestroyPackageInfo(package_info);
11969     if (list && (list != keep))
11970       list=(char **) RelinquishMagickMemory(list);
11971     if (keep)
11972       keep=(char **) RelinquishMagickMemory(keep);
11973     if (length)
11974       length=(STRLEN *) RelinquishMagickMemory(length);
11975     InheritPerlException(exception,perl_exception);
11976     exception=DestroyExceptionInfo(exception);
11977     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11978   }
11979 \f
11980 #
11981 ###############################################################################
11982 #                                                                             #
11983 #                                                                             #
11984 #                                                                             #
11985 #   P r e v i e w                                                             #
11986 #                                                                             #
11987 #                                                                             #
11988 #                                                                             #
11989 ###############################################################################
11990 #
11991 #
11992 void
11993 Preview(ref,...)
11994   Image::Magick ref=NO_INIT
11995   ALIAS:
11996     PreviewImage = 1
11997     preview      = 2
11998     previewimage = 3
11999   PPCODE:
12000   {
12001     AV
12002       *av;
12003
12004     ExceptionInfo
12005       *exception;
12006
12007     HV
12008       *hv;
12009
12010     Image
12011       *image,
12012       *preview_image;
12013
12014     PreviewType
12015       preview_type;
12016
12017     struct PackageInfo
12018       *info;
12019
12020     SV
12021       *av_reference,
12022       *perl_exception,
12023       *reference,
12024       *rv,
12025       *sv;
12026
12027     PERL_UNUSED_VAR(ref);
12028     PERL_UNUSED_VAR(ix);
12029     exception=AcquireExceptionInfo();
12030     perl_exception=newSVpv("",0);
12031     sv=NULL;
12032     av=NULL;
12033     if (sv_isobject(ST(0)) == 0)
12034       {
12035         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12036           PackageName);
12037         goto PerlException;
12038       }
12039     reference=SvRV(ST(0));
12040     hv=SvSTASH(reference);
12041     av=newAV();
12042     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12043     SvREFCNT_dec(av);
12044     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12045     if (image == (Image *) NULL)
12046       {
12047         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12048           PackageName);
12049         goto PerlException;
12050       }
12051     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12052     preview_type=GammaPreview;
12053     if (items > 1)
12054       preview_type=(PreviewType)
12055         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12056     for ( ; image; image=image->next)
12057     {
12058       preview_image=PreviewImage(image,preview_type,exception);
12059       if (preview_image == (Image *) NULL)
12060         goto PerlException;
12061       AddImageToRegistry(sv,preview_image);
12062       rv=newRV(sv);
12063       av_push(av,sv_bless(rv,hv));
12064       SvREFCNT_dec(sv);
12065     }
12066     exception=DestroyExceptionInfo(exception);
12067     ST(0)=av_reference;
12068     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12069     XSRETURN(1);
12070
12071   PerlException:
12072     InheritPerlException(exception,perl_exception);
12073     exception=DestroyExceptionInfo(exception);
12074     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12075     SvPOK_on(perl_exception);
12076     ST(0)=sv_2mortal(perl_exception);
12077     XSRETURN(1);
12078   }
12079 \f
12080 #
12081 ###############################################################################
12082 #                                                                             #
12083 #                                                                             #
12084 #                                                                             #
12085 #   Q u e r y C o l o r                                                       #
12086 #                                                                             #
12087 #                                                                             #
12088 #                                                                             #
12089 ###############################################################################
12090 #
12091 #
12092 void
12093 QueryColor(ref,...)
12094   Image::Magick ref=NO_INIT
12095   ALIAS:
12096     querycolor = 1
12097   PPCODE:
12098   {
12099     char
12100       *name;
12101
12102     ExceptionInfo
12103       *exception;
12104
12105     PixelInfo
12106       color;
12107
12108     register ssize_t
12109       i;
12110
12111     SV
12112       *perl_exception;
12113
12114     PERL_UNUSED_VAR(ref);
12115     PERL_UNUSED_VAR(ix);
12116     exception=AcquireExceptionInfo();
12117     perl_exception=newSVpv("",0);
12118     if (items == 1)
12119       {
12120         const ColorInfo
12121           **colorlist;
12122
12123         size_t
12124           colors;
12125
12126         colorlist=GetColorInfoList("*",&colors,exception);
12127         EXTEND(sp,colors);
12128         for (i=0; i < (ssize_t) colors; i++)
12129         {
12130           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12131         }
12132         colorlist=(const ColorInfo **)
12133           RelinquishMagickMemory((ColorInfo **) colorlist);
12134         goto PerlException;
12135       }
12136     EXTEND(sp,5*items);
12137     for (i=1; i < items; i++)
12138     {
12139       name=(char *) SvPV(ST(i),na);
12140       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12141         {
12142           PUSHs(&sv_undef);
12143           continue;
12144         }
12145       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12146       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12147       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12148       if (color.colorspace == CMYKColorspace)
12149         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12150       if (color.alpha_trait == BlendPixelTrait)
12151         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12152     }
12153
12154   PerlException:
12155     InheritPerlException(exception,perl_exception);
12156     exception=DestroyExceptionInfo(exception);
12157     SvREFCNT_dec(perl_exception);
12158   }
12159 \f
12160 #
12161 ###############################################################################
12162 #                                                                             #
12163 #                                                                             #
12164 #                                                                             #
12165 #   Q u e r y C o l o r N a m e                                               #
12166 #                                                                             #
12167 #                                                                             #
12168 #                                                                             #
12169 ###############################################################################
12170 #
12171 #
12172 void
12173 QueryColorname(ref,...)
12174   Image::Magick ref=NO_INIT
12175   ALIAS:
12176     querycolorname = 1
12177   PPCODE:
12178   {
12179     AV
12180       *av;
12181
12182     char
12183       message[MaxTextExtent];
12184
12185     ExceptionInfo
12186       *exception;
12187
12188     Image
12189       *image;
12190
12191     PixelInfo
12192       target_color;
12193
12194     register ssize_t
12195       i;
12196
12197     struct PackageInfo
12198       *info;
12199
12200     SV
12201       *perl_exception,
12202       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12203
12204     PERL_UNUSED_VAR(ref);
12205     PERL_UNUSED_VAR(ix);
12206     exception=AcquireExceptionInfo();
12207     perl_exception=newSVpv("",0);
12208     reference=SvRV(ST(0));
12209     av=(AV *) reference;
12210     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12211       exception);
12212     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12213     if (image == (Image *) NULL)
12214       {
12215         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12216           PackageName);
12217         goto PerlException;
12218       }
12219     EXTEND(sp,items);
12220     for (i=1; i < items; i++)
12221     {
12222       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12223         exception);
12224       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12225         exception);
12226       PUSHs(sv_2mortal(newSVpv(message,0)));
12227     }
12228
12229   PerlException:
12230     InheritPerlException(exception,perl_exception);
12231     exception=DestroyExceptionInfo(exception);
12232     SvREFCNT_dec(perl_exception);
12233   }
12234 \f
12235 #
12236 ###############################################################################
12237 #                                                                             #
12238 #                                                                             #
12239 #                                                                             #
12240 #   Q u e r y F o n t                                                         #
12241 #                                                                             #
12242 #                                                                             #
12243 #                                                                             #
12244 ###############################################################################
12245 #
12246 #
12247 void
12248 QueryFont(ref,...)
12249   Image::Magick ref=NO_INIT
12250   ALIAS:
12251     queryfont = 1
12252   PPCODE:
12253   {
12254     char
12255       *name,
12256       message[MaxTextExtent];
12257
12258     ExceptionInfo
12259       *exception;
12260
12261     register ssize_t
12262       i;
12263
12264     SV
12265       *perl_exception;
12266
12267     volatile const TypeInfo
12268       *type_info;
12269
12270     PERL_UNUSED_VAR(ref);
12271     PERL_UNUSED_VAR(ix);
12272     exception=AcquireExceptionInfo();
12273     perl_exception=newSVpv("",0);
12274     if (items == 1)
12275       {
12276         const TypeInfo
12277           **typelist;
12278
12279         size_t
12280           types;
12281
12282         typelist=GetTypeInfoList("*",&types,exception);
12283         EXTEND(sp,types);
12284         for (i=0; i < (ssize_t) types; i++)
12285         {
12286           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12287         }
12288         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12289           typelist);
12290         goto PerlException;
12291       }
12292     EXTEND(sp,10*items);
12293     for (i=1; i < items; i++)
12294     {
12295       name=(char *) SvPV(ST(i),na);
12296       type_info=GetTypeInfo(name,exception);
12297       if (type_info == (TypeInfo *) NULL)
12298         {
12299           PUSHs(&sv_undef);
12300           continue;
12301         }
12302       if (type_info->name == (char *) NULL)
12303         PUSHs(&sv_undef);
12304       else
12305         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12306       if (type_info->description == (char *) NULL)
12307         PUSHs(&sv_undef);
12308       else
12309         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12310       if (type_info->family == (char *) NULL)
12311         PUSHs(&sv_undef);
12312       else
12313         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12314       if (type_info->style == UndefinedStyle)
12315         PUSHs(&sv_undef);
12316       else
12317         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12318           type_info->style),0)));
12319       if (type_info->stretch == UndefinedStretch)
12320         PUSHs(&sv_undef);
12321       else
12322         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12323           type_info->stretch),0)));
12324       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
12325         type_info->weight);
12326       PUSHs(sv_2mortal(newSVpv(message,0)));
12327       if (type_info->encoding == (char *) NULL)
12328         PUSHs(&sv_undef);
12329       else
12330         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12331       if (type_info->foundry == (char *) NULL)
12332         PUSHs(&sv_undef);
12333       else
12334         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12335       if (type_info->format == (char *) NULL)
12336         PUSHs(&sv_undef);
12337       else
12338         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12339       if (type_info->metrics == (char *) NULL)
12340         PUSHs(&sv_undef);
12341       else
12342         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12343       if (type_info->glyphs == (char *) NULL)
12344         PUSHs(&sv_undef);
12345       else
12346         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12347     }
12348
12349   PerlException:
12350     InheritPerlException(exception,perl_exception);
12351     exception=DestroyExceptionInfo(exception);
12352     SvREFCNT_dec(perl_exception);
12353   }
12354 \f
12355 #
12356 ###############################################################################
12357 #                                                                             #
12358 #                                                                             #
12359 #                                                                             #
12360 #   Q u e r y F o n t M e t r i c s                                           #
12361 #                                                                             #
12362 #                                                                             #
12363 #                                                                             #
12364 ###############################################################################
12365 #
12366 #
12367 void
12368 QueryFontMetrics(ref,...)
12369   Image::Magick ref=NO_INIT
12370   ALIAS:
12371     queryfontmetrics = 1
12372   PPCODE:
12373   {
12374     AffineMatrix
12375       affine,
12376       current;
12377
12378     AV
12379       *av;
12380
12381     char
12382       *attribute;
12383
12384     double
12385       x,
12386       y;
12387
12388     DrawInfo
12389       *draw_info;
12390
12391     ExceptionInfo
12392       *exception;
12393
12394     GeometryInfo
12395       geometry_info;
12396
12397     Image
12398       *image;
12399
12400     MagickBooleanType
12401       status;
12402
12403     MagickStatusType
12404       flags;
12405
12406     register ssize_t
12407       i;
12408
12409     ssize_t
12410       type;
12411
12412     struct PackageInfo
12413       *info,
12414       *package_info;
12415
12416     SV
12417       *perl_exception,
12418       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12419
12420     TypeMetric
12421       metrics;
12422
12423     PERL_UNUSED_VAR(ref);
12424     PERL_UNUSED_VAR(ix);
12425     exception=AcquireExceptionInfo();
12426     package_info=(struct PackageInfo *) NULL;
12427     perl_exception=newSVpv("",0);
12428     reference=SvRV(ST(0));
12429     av=(AV *) reference;
12430     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12431       exception);
12432     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12433     if (image == (Image *) NULL)
12434       {
12435         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12436           PackageName);
12437         goto PerlException;
12438       }
12439     package_info=ClonePackageInfo(info,exception);
12440     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12441     CloneString(&draw_info->text,"");
12442     current=draw_info->affine;
12443     GetAffineMatrix(&affine);
12444     x=0.0;
12445     y=0.0;
12446     EXTEND(sp,7*items);
12447     for (i=2; i < items; i+=2)
12448     {
12449       attribute=(char *) SvPV(ST(i-1),na);
12450       switch (*attribute)
12451       {
12452         case 'A':
12453         case 'a':
12454         {
12455           if (LocaleCompare(attribute,"antialias") == 0)
12456             {
12457               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12458                 SvPV(ST(i),na));
12459               if (type < 0)
12460                 {
12461                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12462                     SvPV(ST(i),na));
12463                   break;
12464                 }
12465               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12466               break;
12467             }
12468           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12469             attribute);
12470           break;
12471         }
12472         case 'd':
12473         case 'D':
12474         {
12475           if (LocaleCompare(attribute,"density") == 0)
12476             {
12477               CloneString(&draw_info->density,SvPV(ST(i),na));
12478               break;
12479             }
12480           if (LocaleCompare(attribute,"direction") == 0)
12481             {
12482               draw_info->direction=(DirectionType) ParseCommandOption(
12483                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12484               break;
12485             }
12486           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12487             attribute);
12488           break;
12489         }
12490         case 'e':
12491         case 'E':
12492         {
12493           if (LocaleCompare(attribute,"encoding") == 0)
12494             {
12495               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12496               break;
12497             }
12498           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12499             attribute);
12500           break;
12501         }
12502         case 'f':
12503         case 'F':
12504         {
12505           if (LocaleCompare(attribute,"family") == 0)
12506             {
12507               CloneString(&draw_info->family,SvPV(ST(i),na));
12508               break;
12509             }
12510           if (LocaleCompare(attribute,"fill") == 0)
12511             {
12512               if (info)
12513                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12514                   &draw_info->fill,exception);
12515               break;
12516             }
12517           if (LocaleCompare(attribute,"font") == 0)
12518             {
12519               CloneString(&draw_info->font,SvPV(ST(i),na));
12520               break;
12521             }
12522           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12523             attribute);
12524           break;
12525         }
12526         case 'g':
12527         case 'G':
12528         {
12529           if (LocaleCompare(attribute,"geometry") == 0)
12530             {
12531               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12532               break;
12533             }
12534           if (LocaleCompare(attribute,"gravity") == 0)
12535             {
12536               draw_info->gravity=(GravityType) ParseCommandOption(
12537                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12538               break;
12539             }
12540           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12541             attribute);
12542           break;
12543         }
12544         case 'i':
12545         case 'I':
12546         {
12547           if (LocaleCompare(attribute,"interline-spacing") == 0)
12548             {
12549               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12550               draw_info->interline_spacing=geometry_info.rho;
12551               break;
12552             }
12553           if (LocaleCompare(attribute,"interword-spacing") == 0)
12554             {
12555               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12556               draw_info->interword_spacing=geometry_info.rho;
12557               break;
12558             }
12559           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12560             attribute);
12561           break;
12562         }
12563         case 'k':
12564         case 'K':
12565         {
12566           if (LocaleCompare(attribute,"kerning") == 0)
12567             {
12568               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12569               draw_info->kerning=geometry_info.rho;
12570               break;
12571             }
12572           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12573             attribute);
12574           break;
12575         }
12576         case 'p':
12577         case 'P':
12578         {
12579           if (LocaleCompare(attribute,"pointsize") == 0)
12580             {
12581               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12582               draw_info->pointsize=geometry_info.rho;
12583               break;
12584             }
12585           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12586             attribute);
12587           break;
12588         }
12589         case 'r':
12590         case 'R':
12591         {
12592           if (LocaleCompare(attribute,"rotate") == 0)
12593             {
12594               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12595               affine.rx=geometry_info.rho;
12596               affine.ry=geometry_info.sigma;
12597               if ((flags & SigmaValue) == 0)
12598                 affine.ry=affine.rx;
12599               break;
12600             }
12601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12602             attribute);
12603           break;
12604         }
12605         case 's':
12606         case 'S':
12607         {
12608           if (LocaleCompare(attribute,"scale") == 0)
12609             {
12610               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12611               affine.sx=geometry_info.rho;
12612               affine.sy=geometry_info.sigma;
12613               if ((flags & SigmaValue) == 0)
12614                 affine.sy=affine.sx;
12615               break;
12616             }
12617           if (LocaleCompare(attribute,"skew") == 0)
12618             {
12619               double
12620                 x_angle,
12621                 y_angle;
12622
12623               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12624               x_angle=geometry_info.rho;
12625               y_angle=geometry_info.sigma;
12626               if ((flags & SigmaValue) == 0)
12627                 y_angle=x_angle;
12628               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12629               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12630               break;
12631             }
12632           if (LocaleCompare(attribute,"stroke") == 0)
12633             {
12634               if (info)
12635                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12636                   &draw_info->stroke,exception);
12637               break;
12638             }
12639           if (LocaleCompare(attribute,"style") == 0)
12640             {
12641               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12642                 SvPV(ST(i),na));
12643               if (type < 0)
12644                 {
12645                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12646                     SvPV(ST(i),na));
12647                   break;
12648                 }
12649               draw_info->style=(StyleType) type;
12650               break;
12651             }
12652           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12653             attribute);
12654           break;
12655         }
12656         case 't':
12657         case 'T':
12658         {
12659           if (LocaleCompare(attribute,"text") == 0)
12660             {
12661               CloneString(&draw_info->text,SvPV(ST(i),na));
12662               break;
12663             }
12664           if (LocaleCompare(attribute,"translate") == 0)
12665             {
12666               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12667               affine.tx=geometry_info.rho;
12668               affine.ty=geometry_info.sigma;
12669               if ((flags & SigmaValue) == 0)
12670                 affine.ty=affine.tx;
12671               break;
12672             }
12673           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12674             attribute);
12675           break;
12676         }
12677         case 'w':
12678         case 'W':
12679         {
12680           if (LocaleCompare(attribute,"weight") == 0)
12681             {
12682               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12683               draw_info->weight=(size_t) geometry_info.rho;
12684               break;
12685             }
12686           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12687             attribute);
12688           break;
12689         }
12690         case 'x':
12691         case 'X':
12692         {
12693           if (LocaleCompare(attribute,"x") == 0)
12694             {
12695               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12696               x=geometry_info.rho;
12697               break;
12698             }
12699           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12700             attribute);
12701           break;
12702         }
12703         case 'y':
12704         case 'Y':
12705         {
12706           if (LocaleCompare(attribute,"y") == 0)
12707             {
12708               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12709               y=geometry_info.rho;
12710               break;
12711             }
12712           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12713             attribute);
12714           break;
12715         }
12716         default:
12717         {
12718           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12719             attribute);
12720           break;
12721         }
12722       }
12723     }
12724     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12725     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12726     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12727     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12728     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12729     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12730     if (draw_info->geometry == (char *) NULL)
12731       {
12732         draw_info->geometry=AcquireString((char *) NULL);
12733         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12734           "%.15g,%.15g",x,y);
12735       }
12736     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12737     (void) CatchImageException(image);
12738     if (status == MagickFalse)
12739       PUSHs(&sv_undef);
12740     else
12741       {
12742         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12743         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12744         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12745         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12746         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12747         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12748         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12749         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12750         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12751         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12752         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12753         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12754         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12755       }
12756     draw_info=DestroyDrawInfo(draw_info);
12757
12758   PerlException:
12759     if (package_info != (struct PackageInfo *) NULL)
12760       DestroyPackageInfo(package_info);
12761     InheritPerlException(exception,perl_exception);
12762     exception=DestroyExceptionInfo(exception);
12763     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12764   }
12765 \f
12766 #
12767 ###############################################################################
12768 #                                                                             #
12769 #                                                                             #
12770 #                                                                             #
12771 #   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                         #
12772 #                                                                             #
12773 #                                                                             #
12774 #                                                                             #
12775 ###############################################################################
12776 #
12777 #
12778 void
12779 QueryMultilineFontMetrics(ref,...)
12780   Image::Magick ref=NO_INIT
12781   ALIAS:
12782     querymultilinefontmetrics = 1
12783   PPCODE:
12784   {
12785     AffineMatrix
12786       affine,
12787       current;
12788
12789     AV
12790       *av;
12791
12792     char
12793       *attribute;
12794
12795     double
12796       x,
12797       y;
12798
12799     DrawInfo
12800       *draw_info;
12801
12802     ExceptionInfo
12803       *exception;
12804
12805     GeometryInfo
12806       geometry_info;
12807
12808     Image
12809       *image;
12810
12811     MagickBooleanType
12812       status;
12813
12814     MagickStatusType
12815       flags;
12816
12817     register ssize_t
12818       i;
12819
12820     ssize_t
12821       type;
12822
12823     struct PackageInfo
12824       *info,
12825       *package_info;
12826
12827     SV
12828       *perl_exception,
12829       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12830
12831     TypeMetric
12832       metrics;
12833
12834     PERL_UNUSED_VAR(ref);
12835     PERL_UNUSED_VAR(ix);
12836     exception=AcquireExceptionInfo();
12837     package_info=(struct PackageInfo *) NULL;
12838     perl_exception=newSVpv("",0);
12839     reference=SvRV(ST(0));
12840     av=(AV *) reference;
12841     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12842       exception);
12843     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12844     if (image == (Image *) NULL)
12845       {
12846         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12847           PackageName);
12848         goto PerlException;
12849       }
12850     package_info=ClonePackageInfo(info,exception);
12851     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12852     CloneString(&draw_info->text,"");
12853     current=draw_info->affine;
12854     GetAffineMatrix(&affine);
12855     x=0.0;
12856     y=0.0;
12857     EXTEND(sp,7*items);
12858     for (i=2; i < items; i+=2)
12859     {
12860       attribute=(char *) SvPV(ST(i-1),na);
12861       switch (*attribute)
12862       {
12863         case 'A':
12864         case 'a':
12865         {
12866           if (LocaleCompare(attribute,"antialias") == 0)
12867             {
12868               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12869                 SvPV(ST(i),na));
12870               if (type < 0)
12871                 {
12872                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12873                     SvPV(ST(i),na));
12874                   break;
12875                 }
12876               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12877               break;
12878             }
12879           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12880             attribute);
12881           break;
12882         }
12883         case 'd':
12884         case 'D':
12885         {
12886           if (LocaleCompare(attribute,"density") == 0)
12887             {
12888               CloneString(&draw_info->density,SvPV(ST(i),na));
12889               break;
12890             }
12891           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12892             attribute);
12893           break;
12894         }
12895         case 'e':
12896         case 'E':
12897         {
12898           if (LocaleCompare(attribute,"encoding") == 0)
12899             {
12900               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12901               break;
12902             }
12903           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12904             attribute);
12905           break;
12906         }
12907         case 'f':
12908         case 'F':
12909         {
12910           if (LocaleCompare(attribute,"family") == 0)
12911             {
12912               CloneString(&draw_info->family,SvPV(ST(i),na));
12913               break;
12914             }
12915           if (LocaleCompare(attribute,"fill") == 0)
12916             {
12917               if (info)
12918                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12919                   &draw_info->fill,exception);
12920               break;
12921             }
12922           if (LocaleCompare(attribute,"font") == 0)
12923             {
12924               CloneString(&draw_info->font,SvPV(ST(i),na));
12925               break;
12926             }
12927           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12928             attribute);
12929           break;
12930         }
12931         case 'g':
12932         case 'G':
12933         {
12934           if (LocaleCompare(attribute,"geometry") == 0)
12935             {
12936               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12937               break;
12938             }
12939           if (LocaleCompare(attribute,"gravity") == 0)
12940             {
12941               draw_info->gravity=(GravityType) ParseCommandOption(
12942                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12943               break;
12944             }
12945           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12946             attribute);
12947           break;
12948         }
12949         case 'p':
12950         case 'P':
12951         {
12952           if (LocaleCompare(attribute,"pointsize") == 0)
12953             {
12954               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12955               draw_info->pointsize=geometry_info.rho;
12956               break;
12957             }
12958           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12959             attribute);
12960           break;
12961         }
12962         case 'r':
12963         case 'R':
12964         {
12965           if (LocaleCompare(attribute,"rotate") == 0)
12966             {
12967               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12968               affine.rx=geometry_info.rho;
12969               affine.ry=geometry_info.sigma;
12970               if ((flags & SigmaValue) == 0)
12971                 affine.ry=affine.rx;
12972               break;
12973             }
12974           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12975             attribute);
12976           break;
12977         }
12978         case 's':
12979         case 'S':
12980         {
12981           if (LocaleCompare(attribute,"scale") == 0)
12982             {
12983               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12984               affine.sx=geometry_info.rho;
12985               affine.sy=geometry_info.sigma;
12986               if ((flags & SigmaValue) == 0)
12987                 affine.sy=affine.sx;
12988               break;
12989             }
12990           if (LocaleCompare(attribute,"skew") == 0)
12991             {
12992               double
12993                 x_angle,
12994                 y_angle;
12995
12996               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12997               x_angle=geometry_info.rho;
12998               y_angle=geometry_info.sigma;
12999               if ((flags & SigmaValue) == 0)
13000                 y_angle=x_angle;
13001               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13002               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13003               break;
13004             }
13005           if (LocaleCompare(attribute,"stroke") == 0)
13006             {
13007               if (info)
13008                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13009                   &draw_info->stroke,exception);
13010               break;
13011             }
13012           if (LocaleCompare(attribute,"style") == 0)
13013             {
13014               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13015                 SvPV(ST(i),na));
13016               if (type < 0)
13017                 {
13018                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13019                     SvPV(ST(i),na));
13020                   break;
13021                 }
13022               draw_info->style=(StyleType) type;
13023               break;
13024             }
13025           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13026             attribute);
13027           break;
13028         }
13029         case 't':
13030         case 'T':
13031         {
13032           if (LocaleCompare(attribute,"text") == 0)
13033             {
13034               CloneString(&draw_info->text,SvPV(ST(i),na));
13035               break;
13036             }
13037           if (LocaleCompare(attribute,"translate") == 0)
13038             {
13039               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13040               affine.tx=geometry_info.rho;
13041               affine.ty=geometry_info.sigma;
13042               if ((flags & SigmaValue) == 0)
13043                 affine.ty=affine.tx;
13044               break;
13045             }
13046           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13047             attribute);
13048           break;
13049         }
13050         case 'w':
13051         case 'W':
13052         {
13053           if (LocaleCompare(attribute,"weight") == 0)
13054             {
13055               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13056               draw_info->weight=(size_t) geometry_info.rho;
13057               break;
13058             }
13059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13060             attribute);
13061           break;
13062         }
13063         case 'x':
13064         case 'X':
13065         {
13066           if (LocaleCompare(attribute,"x") == 0)
13067             {
13068               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13069               x=geometry_info.rho;
13070               break;
13071             }
13072           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13073             attribute);
13074           break;
13075         }
13076         case 'y':
13077         case 'Y':
13078         {
13079           if (LocaleCompare(attribute,"y") == 0)
13080             {
13081               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13082               y=geometry_info.rho;
13083               break;
13084             }
13085           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13086             attribute);
13087           break;
13088         }
13089         default:
13090         {
13091           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13092             attribute);
13093           break;
13094         }
13095       }
13096     }
13097     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13098     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13099     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13100     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13101     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13102     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13103     if (draw_info->geometry == (char *) NULL)
13104       {
13105         draw_info->geometry=AcquireString((char *) NULL);
13106         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
13107           "%.15g,%.15g",x,y);
13108       }
13109     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13110     (void) CatchException(exception);
13111     if (status == MagickFalse)
13112       PUSHs(&sv_undef);
13113     else
13114       {
13115         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13116         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13117         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13118         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13119         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13120         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13121         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13122         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13123         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13124         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13125         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13126         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13127         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13128       }
13129     draw_info=DestroyDrawInfo(draw_info);
13130
13131   PerlException:
13132     if (package_info != (struct PackageInfo *) NULL)
13133       DestroyPackageInfo(package_info);
13134     InheritPerlException(exception,perl_exception);
13135     exception=DestroyExceptionInfo(exception);
13136     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13137   }
13138 \f
13139 #
13140 ###############################################################################
13141 #                                                                             #
13142 #                                                                             #
13143 #                                                                             #
13144 #   Q u e r y F o r m a t                                                     #
13145 #                                                                             #
13146 #                                                                             #
13147 #                                                                             #
13148 ###############################################################################
13149 #
13150 #
13151 void
13152 QueryFormat(ref,...)
13153   Image::Magick ref=NO_INIT
13154   ALIAS:
13155     queryformat = 1
13156   PPCODE:
13157   {
13158     char
13159       *name;
13160
13161     ExceptionInfo
13162       *exception;
13163
13164     register ssize_t
13165       i;
13166
13167     SV
13168       *perl_exception;
13169
13170     volatile const MagickInfo
13171       *magick_info;
13172
13173     PERL_UNUSED_VAR(ref);
13174     PERL_UNUSED_VAR(ix);
13175     exception=AcquireExceptionInfo();
13176     perl_exception=newSVpv("",0);
13177     if (items == 1)
13178       {
13179         char
13180           format[MaxTextExtent];
13181
13182         const MagickInfo
13183           **format_list;
13184
13185         size_t
13186           types;
13187
13188         format_list=GetMagickInfoList("*",&types,exception);
13189         EXTEND(sp,types);
13190         for (i=0; i < (ssize_t) types; i++)
13191         {
13192           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
13193           LocaleLower(format);
13194           PUSHs(sv_2mortal(newSVpv(format,0)));
13195         }
13196         format_list=(const MagickInfo **)
13197           RelinquishMagickMemory((MagickInfo *) format_list);
13198         goto PerlException;
13199       }
13200     EXTEND(sp,8*items);
13201     for (i=1; i < items; i++)
13202     {
13203       name=(char *) SvPV(ST(i),na);
13204       magick_info=GetMagickInfo(name,exception);
13205       if (magick_info == (const MagickInfo *) NULL)
13206         {
13207           PUSHs(&sv_undef);
13208           continue;
13209         }
13210       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
13211       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
13212       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
13213       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
13214       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
13215       if (magick_info->description == (char *) NULL)
13216         PUSHs(&sv_undef);
13217       else
13218         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13219       if (magick_info->module == (char *) NULL)
13220         PUSHs(&sv_undef);
13221       else
13222         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13223     }
13224
13225   PerlException:
13226     InheritPerlException(exception,perl_exception);
13227     exception=DestroyExceptionInfo(exception);
13228     SvREFCNT_dec(perl_exception);
13229   }
13230 \f
13231 #
13232 ###############################################################################
13233 #                                                                             #
13234 #                                                                             #
13235 #                                                                             #
13236 #   Q u e r y O p t i o n                                                     #
13237 #                                                                             #
13238 #                                                                             #
13239 #                                                                             #
13240 ###############################################################################
13241 #
13242 #
13243 void
13244 QueryOption(ref,...)
13245   Image::Magick ref=NO_INIT
13246   ALIAS:
13247     queryoption = 1
13248   PPCODE:
13249   {
13250     char
13251       **options;
13252
13253     ExceptionInfo
13254       *exception;
13255
13256     register ssize_t
13257       i;
13258
13259     ssize_t
13260       j,
13261       option;
13262
13263     SV
13264       *perl_exception;
13265
13266     PERL_UNUSED_VAR(ref);
13267     PERL_UNUSED_VAR(ix);
13268     exception=AcquireExceptionInfo();
13269     perl_exception=newSVpv("",0);
13270     EXTEND(sp,8*items);
13271     for (i=1; i < items; i++)
13272     {
13273       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13274         SvPV(ST(i),na));
13275       options=GetCommandOptions((CommandOption) option);
13276       if (options == (char **) NULL)
13277         PUSHs(&sv_undef);
13278       else
13279         {
13280           for (j=0; options[j] != (char *) NULL; j++)
13281             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13282           options=DestroyStringList(options);
13283         }
13284     }
13285
13286     InheritPerlException(exception,perl_exception);
13287     exception=DestroyExceptionInfo(exception);
13288     SvREFCNT_dec(perl_exception);
13289   }
13290 \f
13291 #
13292 ###############################################################################
13293 #                                                                             #
13294 #                                                                             #
13295 #                                                                             #
13296 #   R e a d                                                                   #
13297 #                                                                             #
13298 #                                                                             #
13299 #                                                                             #
13300 ###############################################################################
13301 #
13302 #
13303 void
13304 Read(ref,...)
13305   Image::Magick ref=NO_INIT
13306   ALIAS:
13307     ReadImage  = 1
13308     read       = 2
13309     readimage  = 3
13310   PPCODE:
13311   {
13312     AV
13313       *av;
13314
13315     char
13316       **keep,
13317       **list;
13318
13319     ExceptionInfo
13320       *exception;
13321
13322     HV
13323       *hv;
13324
13325     Image
13326       *image;
13327
13328     int
13329       n;
13330
13331     MagickBooleanType
13332       status;
13333
13334     register char
13335       **p;
13336
13337     register ssize_t
13338       i;
13339
13340     ssize_t
13341       ac,
13342       number_images;
13343
13344     STRLEN
13345       *length;
13346
13347     struct PackageInfo
13348       *info,
13349       *package_info;
13350
13351     SV
13352       *perl_exception,  /* Perl variable for storing messages */
13353       *reference,
13354       *rv,
13355       *sv;
13356
13357     PERL_UNUSED_VAR(ref);
13358     PERL_UNUSED_VAR(ix);
13359     exception=AcquireExceptionInfo();
13360     perl_exception=newSVpv("",0);
13361     sv=NULL;
13362     package_info=(struct PackageInfo *) NULL;
13363     number_images=0;
13364     ac=(items < 2) ? 1 : items-1;
13365     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13366     keep=list;
13367     length=(STRLEN *) NULL;
13368     if (list == (char **) NULL)
13369       {
13370         ThrowPerlException(exception,ResourceLimitError,
13371           "MemoryAllocationFailed",PackageName);
13372         goto PerlException;
13373       }
13374     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13375     if (length == (STRLEN *) NULL)
13376       {
13377         ThrowPerlException(exception,ResourceLimitError,
13378           "MemoryAllocationFailed",PackageName);
13379         goto PerlException;
13380       }
13381     if (sv_isobject(ST(0)) == 0)
13382       {
13383         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13384           PackageName);
13385         goto PerlException;
13386       }
13387     reference=SvRV(ST(0));
13388     hv=SvSTASH(reference);
13389     if (SvTYPE(reference) != SVt_PVAV)
13390       {
13391         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13392           PackageName);
13393         goto PerlException;
13394       }
13395     av=(AV *) reference;
13396     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13397       exception);
13398     package_info=ClonePackageInfo(info,exception);
13399     n=1;
13400     if (items <= 1)
13401       *list=(char *) (*package_info->image_info->filename ?
13402         package_info->image_info->filename : "XC:black");
13403     else
13404       for (n=0, i=0; i < ac; i++)
13405       {
13406         list[n]=(char *) SvPV(ST(i+1),length[n]);
13407         if ((items >= 3) && strEQcase(list[n],"blob"))
13408           {
13409             void
13410               *blob;
13411
13412             i++;
13413             blob=(void *) (SvPV(ST(i+1),length[n]));
13414             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13415           }
13416         if ((items >= 3) && strEQcase(list[n],"filename"))
13417           continue;
13418         if ((items >= 3) && strEQcase(list[n],"file"))
13419           {
13420             FILE
13421               *file;
13422
13423             PerlIO
13424               *io_info;
13425
13426             i++;
13427             io_info=IoIFP(sv_2io(ST(i+1)));
13428             if (io_info == (PerlIO *) NULL)
13429               {
13430                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13431                   PackageName);
13432                 continue;
13433               }
13434             file=PerlIO_findFILE(io_info);
13435             if (file == (FILE *) NULL)
13436               {
13437                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13438                   PackageName);
13439                 continue;
13440               }
13441             SetImageInfoFile(package_info->image_info,file);
13442           }
13443         if ((items >= 3) && strEQcase(list[n],"magick"))
13444           continue;
13445         n++;
13446       }
13447     list[n]=(char *) NULL;
13448     keep=list;
13449     status=ExpandFilenames(&n,&list);
13450     if (status == MagickFalse)
13451       {
13452         ThrowPerlException(exception,ResourceLimitError,
13453           "MemoryAllocationFailed",PackageName);
13454         goto PerlException;
13455       }
13456     number_images=0;
13457     for (i=0; i < n; i++)
13458     {
13459       if ((package_info->image_info->file == (FILE *) NULL) &&
13460           (package_info->image_info->blob == (void *) NULL))
13461         image=ReadImages(package_info->image_info,list[i],exception);
13462       else
13463         {
13464           image=ReadImages(package_info->image_info,
13465             package_info->image_info->filename,exception);
13466           if (image != (Image *) NULL)
13467             DisassociateImageStream(image);
13468         }
13469       if (image == (Image *) NULL)
13470         break;
13471       for ( ; image; image=image->next)
13472       {
13473         AddImageToRegistry(sv,image);
13474         rv=newRV(sv);
13475         av_push(av,sv_bless(rv,hv));
13476         SvREFCNT_dec(sv);
13477         number_images++;
13478       }
13479     }
13480     /*
13481       Free resources.
13482     */
13483     for (i=0; i < n; i++)
13484       if (list[i] != (char *) NULL)
13485         for (p=keep; list[i] != *p++; )
13486           if (*p == (char *) NULL)
13487             {
13488               list[i]=(char *) RelinquishMagickMemory(list[i]);
13489               break;
13490             }
13491
13492   PerlException:
13493     if (package_info != (struct PackageInfo *) NULL)
13494       DestroyPackageInfo(package_info);
13495     if (list && (list != keep))
13496       list=(char **) RelinquishMagickMemory(list);
13497     if (keep)
13498       keep=(char **) RelinquishMagickMemory(keep);
13499     if (length)
13500       length=(STRLEN *) RelinquishMagickMemory(length);
13501     InheritPerlException(exception,perl_exception);
13502     exception=DestroyExceptionInfo(exception);
13503     sv_setiv(perl_exception,(IV) number_images);
13504     SvPOK_on(perl_exception);
13505     ST(0)=sv_2mortal(perl_exception);
13506     XSRETURN(1);
13507   }
13508 \f
13509 #
13510 ###############################################################################
13511 #                                                                             #
13512 #                                                                             #
13513 #                                                                             #
13514 #   R e m o t e                                                               #
13515 #                                                                             #
13516 #                                                                             #
13517 #                                                                             #
13518 ###############################################################################
13519 #
13520 #
13521 void
13522 Remote(ref,...)
13523   Image::Magick ref=NO_INIT
13524   ALIAS:
13525     RemoteCommand  = 1
13526     remote         = 2
13527     remoteCommand  = 3
13528   PPCODE:
13529   {
13530     AV
13531       *av;
13532
13533     ExceptionInfo
13534       *exception;
13535
13536     register ssize_t
13537       i;
13538
13539     SV
13540       *perl_exception,
13541       *reference;
13542
13543     struct PackageInfo
13544       *info;
13545
13546     PERL_UNUSED_VAR(ref);
13547     PERL_UNUSED_VAR(ix);
13548     exception=AcquireExceptionInfo();
13549     perl_exception=newSVpv("",0);
13550     reference=SvRV(ST(0));
13551     av=(AV *) reference;
13552     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13553       exception);
13554     for (i=1; i < items; i++)
13555       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13556         SvPV(ST(i),na),exception);
13557     InheritPerlException(exception,perl_exception);
13558     exception=DestroyExceptionInfo(exception);
13559     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13560   }
13561 \f
13562 #
13563 ###############################################################################
13564 #                                                                             #
13565 #                                                                             #
13566 #                                                                             #
13567 #   S e t                                                                     #
13568 #                                                                             #
13569 #                                                                             #
13570 #                                                                             #
13571 ###############################################################################
13572 #
13573 #
13574 void
13575 Set(ref,...)
13576   Image::Magick ref=NO_INIT
13577   ALIAS:
13578     SetAttributes  = 1
13579     SetAttribute   = 2
13580     set            = 3
13581     setattributes  = 4
13582     setattribute   = 5
13583   PPCODE:
13584   {
13585     ExceptionInfo
13586       *exception;
13587
13588     Image
13589       *image;
13590
13591     register ssize_t
13592       i;
13593
13594     struct PackageInfo
13595       *info;
13596
13597     SV
13598       *perl_exception,
13599       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13600
13601     PERL_UNUSED_VAR(ref);
13602     PERL_UNUSED_VAR(ix);
13603     exception=AcquireExceptionInfo();
13604     perl_exception=newSVpv("",0);
13605     if (sv_isobject(ST(0)) == 0)
13606       {
13607         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13608           PackageName);
13609         goto PerlException;
13610       }
13611     reference=SvRV(ST(0));
13612     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13613     if (items == 2)
13614       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13615     else
13616       for (i=2; i < items; i+=2)
13617         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13618
13619   PerlException:
13620     InheritPerlException(exception,perl_exception);
13621     exception=DestroyExceptionInfo(exception);
13622     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13623     SvPOK_on(perl_exception);
13624     ST(0)=sv_2mortal(perl_exception);
13625     XSRETURN(1);
13626   }
13627 \f
13628 #
13629 ###############################################################################
13630 #                                                                             #
13631 #                                                                             #
13632 #                                                                             #
13633 #   S e t P i x e l                                                           #
13634 #                                                                             #
13635 #                                                                             #
13636 #                                                                             #
13637 ###############################################################################
13638 #
13639 #
13640 void
13641 SetPixel(ref,...)
13642   Image::Magick ref=NO_INIT
13643   ALIAS:
13644     setpixel = 1
13645     setPixel = 2
13646   PPCODE:
13647   {
13648     AV
13649       *av;
13650
13651     char
13652       *attribute;
13653
13654     ChannelType
13655       channel,
13656       channel_mask;
13657
13658     ExceptionInfo
13659       *exception;
13660
13661     Image
13662       *image;
13663
13664     MagickBooleanType
13665       normalize;
13666
13667     RectangleInfo
13668       region;
13669
13670     register ssize_t
13671       i;
13672
13673     register Quantum
13674       *q;
13675
13676     ssize_t
13677       option;
13678
13679     struct PackageInfo
13680       *info;
13681
13682     SV
13683       *perl_exception,
13684       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13685
13686     PERL_UNUSED_VAR(ref);
13687     PERL_UNUSED_VAR(ix);
13688     exception=AcquireExceptionInfo();
13689     perl_exception=newSVpv("",0);
13690     reference=SvRV(ST(0));
13691     av=(AV *) reference;
13692     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13693       exception);
13694     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13695     if (image == (Image *) NULL)
13696       {
13697         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13698           PackageName);
13699         goto PerlException;
13700       }
13701     av=(AV *) NULL;
13702     normalize=MagickTrue;
13703     region.x=0;
13704     region.y=0;
13705     region.width=image->columns;
13706     region.height=1;
13707     if (items == 1)
13708       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13709     channel=DefaultChannels;
13710     for (i=2; i < items; i+=2)
13711     {
13712       attribute=(char *) SvPV(ST(i-1),na);
13713       switch (*attribute)
13714       {
13715         case 'C':
13716         case 'c':
13717         {
13718           if (LocaleCompare(attribute,"channel") == 0)
13719             {
13720               ssize_t
13721                 option;
13722
13723               option=ParseChannelOption(SvPV(ST(i),na));
13724               if (option < 0)
13725                 {
13726                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13727                     SvPV(ST(i),na));
13728                   return;
13729                 }
13730               channel=(ChannelType) option;
13731               break;
13732             }
13733           if (LocaleCompare(attribute,"color") == 0)
13734             {
13735               if (SvTYPE(ST(i)) != SVt_RV)
13736                 {
13737                   char
13738                     message[MaxTextExtent];
13739
13740                   (void) FormatLocaleString(message,MaxTextExtent,
13741                     "invalid %.60s value",attribute);
13742                   ThrowPerlException(exception,OptionError,message,
13743                     SvPV(ST(i),na));
13744                 }
13745               av=(AV *) SvRV(ST(i));
13746               break;
13747             }
13748           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13749             attribute);
13750           break;
13751         }
13752         case 'g':
13753         case 'G':
13754         {
13755           if (LocaleCompare(attribute,"geometry") == 0)
13756             {
13757               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13758               break;
13759             }
13760           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13761             attribute);
13762           break;
13763         }
13764         case 'N':
13765         case 'n':
13766         {
13767           if (LocaleCompare(attribute,"normalize") == 0)
13768             {
13769               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13770                 SvPV(ST(i),na));
13771               if (option < 0)
13772                 {
13773                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13774                     SvPV(ST(i),na));
13775                   break;
13776                 }
13777              normalize=option != 0 ? MagickTrue : MagickFalse;
13778              break;
13779             }
13780           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13781             attribute);
13782           break;
13783         }
13784         case 'x':
13785         case 'X':
13786         {
13787           if (LocaleCompare(attribute,"x") == 0)
13788             {
13789               region.x=SvIV(ST(i));
13790               break;
13791             }
13792           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13793             attribute);
13794           break;
13795         }
13796         case 'y':
13797         case 'Y':
13798         {
13799           if (LocaleCompare(attribute,"y") == 0)
13800             {
13801               region.y=SvIV(ST(i));
13802               break;
13803             }
13804           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13805             attribute);
13806           break;
13807         }
13808         default:
13809         {
13810           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13811             attribute);
13812           break;
13813         }
13814       }
13815     }
13816     (void) SetImageStorageClass(image,DirectClass,exception);
13817     channel_mask=SetImageChannelMask(image,channel);
13818     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13819     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13820         (SvTYPE(av) != SVt_PVAV))
13821       PUSHs(&sv_undef);
13822     else
13823       {
13824         double
13825           scale;
13826
13827         register ssize_t
13828           i;
13829
13830         i=0;
13831         scale=1.0;
13832         if (normalize != MagickFalse)
13833           scale=QuantumRange;
13834         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13835             (i <= av_len(av)))
13836           {
13837             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13838               av_fetch(av,i,0)))),q);
13839             i++;
13840           }
13841         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13842             (i <= av_len(av)))
13843           {
13844             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13845               av_fetch(av,i,0)))),q);
13846             i++;
13847           }
13848         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13849             (i <= av_len(av)))
13850           {
13851             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13852               av_fetch(av,i,0)))),q);
13853             i++;
13854           }
13855         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13856             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13857           {
13858             SetPixelBlack(image,ClampToQuantum(scale*
13859               SvNV(*(av_fetch(av,i,0)))),q);
13860             i++;
13861           }
13862         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13863             (i <= av_len(av)))
13864           {
13865             SetPixelAlpha(image,ClampToQuantum(scale*
13866               SvNV(*(av_fetch(av,i,0)))),q);
13867             i++;
13868           }
13869         (void) SyncAuthenticPixels(image,exception);
13870       }
13871     (void) SetImageChannelMask(image,channel_mask);
13872
13873   PerlException:
13874     InheritPerlException(exception,perl_exception);
13875     exception=DestroyExceptionInfo(exception);
13876     SvREFCNT_dec(perl_exception);
13877   }
13878 \f
13879 #
13880 ###############################################################################
13881 #                                                                             #
13882 #                                                                             #
13883 #                                                                             #
13884 #   S m u s h                                                                 #
13885 #                                                                             #
13886 #                                                                             #
13887 #                                                                             #
13888 ###############################################################################
13889 #
13890 #
13891 void
13892 Smush(ref,...)
13893   Image::Magick ref=NO_INIT
13894   ALIAS:
13895     SmushImage  = 1
13896     smush       = 2
13897     smushimage  = 3
13898   PPCODE:
13899   {
13900     AV
13901       *av;
13902
13903     char
13904       *attribute;
13905
13906     ExceptionInfo
13907       *exception;
13908
13909     HV
13910       *hv;
13911
13912     Image
13913       *image;
13914
13915     register ssize_t
13916       i;
13917
13918     ssize_t
13919       offset,
13920       stack;
13921
13922     struct PackageInfo
13923       *info;
13924
13925     SV
13926       *av_reference,
13927       *perl_exception,
13928       *reference,
13929       *rv,
13930       *sv;
13931
13932     PERL_UNUSED_VAR(ref);
13933     PERL_UNUSED_VAR(ix);
13934     exception=AcquireExceptionInfo();
13935     perl_exception=newSVpv("",0);
13936     sv=NULL;
13937     attribute=NULL;
13938     av=NULL;
13939     if (sv_isobject(ST(0)) == 0)
13940       {
13941         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13942           PackageName);
13943         goto PerlException;
13944       }
13945     reference=SvRV(ST(0));
13946     hv=SvSTASH(reference);
13947     av=newAV();
13948     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13949     SvREFCNT_dec(av);
13950     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13951     if (image == (Image *) NULL)
13952       {
13953         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13954           PackageName);
13955         goto PerlException;
13956       }
13957     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13958     /*
13959       Get options.
13960     */
13961     offset=0;
13962     stack=MagickTrue;
13963     for (i=2; i < items; i+=2)
13964     {
13965       attribute=(char *) SvPV(ST(i-1),na);
13966       switch (*attribute)
13967       {
13968         case 'O':
13969         case 'o':
13970         {
13971           if (LocaleCompare(attribute,"offset") == 0)
13972             {
13973               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13974               break;
13975             }
13976           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13977             attribute);
13978           break;
13979         }
13980         case 'S':
13981         case 's':
13982         {
13983           if (LocaleCompare(attribute,"stack") == 0)
13984             {
13985               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13986                 SvPV(ST(i),na));
13987               if (stack < 0)
13988                 {
13989                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13990                     SvPV(ST(i),na));
13991                   return;
13992                 }
13993               break;
13994             }
13995           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13996             attribute);
13997           break;
13998         }
13999         default:
14000         {
14001           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14002             attribute);
14003           break;
14004         }
14005       }
14006     }
14007     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14008       exception);
14009     if (image == (Image *) NULL)
14010       goto PerlException;
14011     for ( ; image; image=image->next)
14012     {
14013       AddImageToRegistry(sv,image);
14014       rv=newRV(sv);
14015       av_push(av,sv_bless(rv,hv));
14016       SvREFCNT_dec(sv);
14017     }
14018     exception=DestroyExceptionInfo(exception);
14019     ST(0)=av_reference;
14020     SvREFCNT_dec(perl_exception);
14021     XSRETURN(1);
14022
14023   PerlException:
14024     InheritPerlException(exception,perl_exception);
14025     exception=DestroyExceptionInfo(exception);
14026     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14027     SvPOK_on(perl_exception);
14028     ST(0)=sv_2mortal(perl_exception);
14029     XSRETURN(1);
14030   }
14031 \f
14032 #
14033 ###############################################################################
14034 #                                                                             #
14035 #                                                                             #
14036 #                                                                             #
14037 #   S t a t i s t i c s                                                       #
14038 #                                                                             #
14039 #                                                                             #
14040 #                                                                             #
14041 ###############################################################################
14042 #
14043 #
14044 void
14045 Statistics(ref,...)
14046   Image::Magick ref=NO_INIT
14047   ALIAS:
14048     StatisticsImage = 1
14049     statistics      = 2
14050     statisticsimage = 3
14051   PPCODE:
14052   {
14053 #define ChannelStatistics(channel) \
14054 { \
14055   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
14056     (double) channel_statistics[channel].depth); \
14057   PUSHs(sv_2mortal(newSVpv(message,0))); \
14058   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14059     channel_statistics[channel].minima/scale); \
14060   PUSHs(sv_2mortal(newSVpv(message,0))); \
14061   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14062     channel_statistics[channel].maxima/scale); \
14063   PUSHs(sv_2mortal(newSVpv(message,0))); \
14064   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14065     channel_statistics[channel].mean/scale); \
14066   PUSHs(sv_2mortal(newSVpv(message,0))); \
14067   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14068     channel_statistics[channel].standard_deviation/scale); \
14069   PUSHs(sv_2mortal(newSVpv(message,0))); \
14070   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14071     channel_statistics[channel].kurtosis); \
14072   PUSHs(sv_2mortal(newSVpv(message,0))); \
14073   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
14074     channel_statistics[channel].skewness); \
14075   PUSHs(sv_2mortal(newSVpv(message,0))); \
14076 }
14077
14078     AV
14079       *av;
14080
14081     char
14082       message[MaxTextExtent];
14083
14084     ChannelStatistics
14085       *channel_statistics;
14086
14087     double
14088       scale;
14089
14090     ExceptionInfo
14091       *exception;
14092
14093     Image
14094       *image;
14095
14096     ssize_t
14097       count;
14098
14099     struct PackageInfo
14100       *info;
14101
14102     SV
14103       *perl_exception,
14104       *reference;
14105
14106     PERL_UNUSED_VAR(ref);
14107     PERL_UNUSED_VAR(ix);
14108     exception=AcquireExceptionInfo();
14109     perl_exception=newSVpv("",0);
14110     av=NULL;
14111     if (sv_isobject(ST(0)) == 0)
14112       {
14113         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14114           PackageName);
14115         goto PerlException;
14116       }
14117     reference=SvRV(ST(0));
14118     av=newAV();
14119     SvREFCNT_dec(av);
14120     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14121     if (image == (Image *) NULL)
14122       {
14123         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14124           PackageName);
14125         goto PerlException;
14126       }
14127     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14128     count=0;
14129     for ( ; image; image=image->next)
14130     {
14131       channel_statistics=GetImageStatistics(image,exception);
14132       if (channel_statistics == (ChannelStatistics *) NULL)
14133         continue;
14134       count++;
14135       EXTEND(sp,35*count);
14136       scale=(double) QuantumRange;
14137       ChannelStatistics(RedChannel);
14138       ChannelStatistics(GreenChannel);
14139       ChannelStatistics(BlueChannel);
14140       if (image->colorspace == CMYKColorspace)
14141         ChannelStatistics(BlackChannel);
14142       if (image->alpha_trait == BlendPixelTrait)
14143         ChannelStatistics(AlphaChannel);
14144       channel_statistics=(ChannelStatistics *)
14145         RelinquishMagickMemory(channel_statistics);
14146     }
14147
14148   PerlException:
14149     InheritPerlException(exception,perl_exception);
14150     exception=DestroyExceptionInfo(exception);
14151     SvREFCNT_dec(perl_exception);
14152   }
14153 \f
14154 #
14155 ###############################################################################
14156 #                                                                             #
14157 #                                                                             #
14158 #                                                                             #
14159 #   S y n c A u t h e n t i c P i x e l s                                     #
14160 #                                                                             #
14161 #                                                                             #
14162 #                                                                             #
14163 ###############################################################################
14164 #
14165 #
14166 void
14167 SyncAuthenticPixels(ref,...)
14168   Image::Magick ref = NO_INIT
14169   ALIAS:
14170     Syncauthenticpixels = 1
14171     SyncImagePixels = 2
14172     syncimagepixels = 3
14173   CODE:
14174   {
14175     ExceptionInfo
14176       *exception;
14177
14178     Image
14179       *image;
14180
14181     MagickBooleanType
14182       status;
14183
14184     struct PackageInfo
14185       *info;
14186
14187     SV
14188       *perl_exception,
14189       *reference;
14190
14191     PERL_UNUSED_VAR(ref);
14192     PERL_UNUSED_VAR(ix);
14193     exception=AcquireExceptionInfo();
14194     perl_exception=newSVpv("",0);
14195     if (sv_isobject(ST(0)) == 0)
14196       {
14197         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14198           PackageName);
14199         goto PerlException;
14200       }
14201
14202     reference=SvRV(ST(0));
14203     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14204     if (image == (Image *) NULL)
14205       {
14206         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14207           PackageName);
14208         goto PerlException;
14209       }
14210
14211     status=SyncAuthenticPixels(image,exception);
14212     if (status != MagickFalse)
14213       return;
14214
14215   PerlException:
14216     InheritPerlException(exception,perl_exception);
14217     exception=DestroyExceptionInfo(exception);
14218     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14219   }
14220 \f
14221 #
14222 ###############################################################################
14223 #                                                                             #
14224 #                                                                             #
14225 #                                                                             #
14226 #   T r a n s f o r m                                                         #
14227 #                                                                             #
14228 #                                                                             #
14229 #                                                                             #
14230 ###############################################################################
14231 #
14232 #
14233 void
14234 Transform(ref,...)
14235   Image::Magick ref=NO_INIT
14236   ALIAS:
14237     TransformImage = 1
14238     transform      = 2
14239     transformimage = 3
14240   PPCODE:
14241   {
14242     AV
14243       *av;
14244
14245     char
14246       *attribute,
14247       *crop_geometry,
14248       *geometry;
14249
14250     ExceptionInfo
14251       *exception;
14252
14253     HV
14254       *hv;
14255
14256     Image
14257       *clone,
14258       *image;
14259
14260     register ssize_t
14261       i;
14262
14263     struct PackageInfo
14264       *info;
14265
14266     SV
14267       *av_reference,
14268       *perl_exception,
14269       *reference,
14270       *rv,
14271       *sv;
14272
14273     PERL_UNUSED_VAR(ref);
14274     PERL_UNUSED_VAR(ix);
14275     exception=AcquireExceptionInfo();
14276     perl_exception=newSVpv("",0);
14277     sv=NULL;
14278     av=NULL;
14279     attribute=NULL;
14280     if (sv_isobject(ST(0)) == 0)
14281       {
14282         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14283           PackageName);
14284         goto PerlException;
14285       }
14286     reference=SvRV(ST(0));
14287     hv=SvSTASH(reference);
14288     av=newAV();
14289     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14290     SvREFCNT_dec(av);
14291     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14292     if (image == (Image *) NULL)
14293       {
14294         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14295           PackageName);
14296         goto PerlException;
14297       }
14298     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14299     /*
14300       Get attribute.
14301     */
14302     crop_geometry=(char *) NULL;
14303     geometry=(char *) NULL;
14304     for (i=2; i < items; i+=2)
14305     {
14306       attribute=(char *) SvPV(ST(i-1),na);
14307       switch (*attribute)
14308       {
14309         case 'c':
14310         case 'C':
14311         {
14312           if (LocaleCompare(attribute,"crop") == 0)
14313             {
14314               crop_geometry=SvPV(ST(i),na);
14315               break;
14316             }
14317           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14318             attribute);
14319           break;
14320         }
14321         case 'g':
14322         case 'G':
14323         {
14324           if (LocaleCompare(attribute,"geometry") == 0)
14325             {
14326               geometry=SvPV(ST(i),na);
14327               break;
14328             }
14329           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14330             attribute);
14331           break;
14332         }
14333         default:
14334         {
14335           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14336             attribute);
14337           break;
14338         }
14339       }
14340     }
14341     for ( ; image; image=image->next)
14342     {
14343       clone=CloneImage(image,0,0,MagickTrue,exception);
14344       if (clone == (Image *) NULL)
14345         goto PerlException;
14346       TransformImage(&clone,crop_geometry,geometry,exception);
14347       for ( ; clone; clone=clone->next)
14348       {
14349         AddImageToRegistry(sv,clone);
14350         rv=newRV(sv);
14351         av_push(av,sv_bless(rv,hv));
14352         SvREFCNT_dec(sv);
14353       }
14354     }
14355     exception=DestroyExceptionInfo(exception);
14356     ST(0)=av_reference;
14357     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14358     XSRETURN(1);
14359
14360   PerlException:
14361     InheritPerlException(exception,perl_exception);
14362     exception=DestroyExceptionInfo(exception);
14363     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14364     SvPOK_on(perl_exception);
14365     ST(0)=sv_2mortal(perl_exception);
14366     XSRETURN(1);
14367   }
14368 \f
14369 #
14370 ###############################################################################
14371 #                                                                             #
14372 #                                                                             #
14373 #                                                                             #
14374 #   W r i t e                                                                 #
14375 #                                                                             #
14376 #                                                                             #
14377 #                                                                             #
14378 ###############################################################################
14379 #
14380 #
14381 void
14382 Write(ref,...)
14383   Image::Magick ref=NO_INIT
14384   ALIAS:
14385     WriteImage    = 1
14386     write         = 2
14387     writeimage    = 3
14388   PPCODE:
14389   {
14390     char
14391       filename[MaxTextExtent];
14392
14393     ExceptionInfo
14394       *exception;
14395
14396     Image
14397       *image,
14398       *next;
14399
14400     register ssize_t
14401       i;
14402
14403     ssize_t
14404       number_images,
14405       scene;
14406
14407     struct PackageInfo
14408       *info,
14409       *package_info;
14410
14411     SV
14412       *perl_exception,
14413       *reference;
14414
14415     PERL_UNUSED_VAR(ref);
14416     PERL_UNUSED_VAR(ix);
14417     exception=AcquireExceptionInfo();
14418     perl_exception=newSVpv("",0);
14419     number_images=0;
14420     package_info=(struct PackageInfo *) NULL;
14421     if (sv_isobject(ST(0)) == 0)
14422       {
14423         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14424           PackageName);
14425         goto PerlException;
14426       }
14427     reference=SvRV(ST(0));
14428     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14429     if (image == (Image *) NULL)
14430       {
14431         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14432           PackageName);
14433         goto PerlException;
14434       }
14435     package_info=ClonePackageInfo(info,exception);
14436     if (items == 2)
14437       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14438     else
14439       if (items > 2)
14440         for (i=2; i < items; i+=2)
14441           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14442             exception);
14443     (void) CopyMagickString(filename,package_info->image_info->filename,
14444       MaxTextExtent);
14445     scene=0;
14446     for (next=image; next; next=next->next)
14447     {
14448       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
14449       next->scene=scene++;
14450     }
14451     SetImageInfo(package_info->image_info,(unsigned int)
14452       GetImageListLength(image),exception);
14453     for (next=image; next; next=next->next)
14454     {
14455       (void) WriteImage(package_info->image_info,next,exception);
14456       number_images++;
14457       if (package_info->image_info->adjoin)
14458         break;
14459     }
14460
14461   PerlException:
14462     if (package_info != (struct PackageInfo *) NULL)
14463       DestroyPackageInfo(package_info);
14464     InheritPerlException(exception,perl_exception);
14465     exception=DestroyExceptionInfo(exception);
14466     sv_setiv(perl_exception,(IV) number_images);
14467     SvPOK_on(perl_exception);
14468     ST(0)=sv_2mortal(perl_exception);
14469     XSRETURN(1);
14470   }