]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                                 Cristy                                      %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include <MagickCore/MagickCore.h>
57 #include "EXTERN.h"
58 #include "perl.h"
59 #include "XSUB.h"
60 #include <math.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "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     { "CannyEdge", { {"geometry", StringReference},
548       {"radius", RealReference}, {"sigma", RealReference},
549       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
550     { "HoughLine", { {"geometry", StringReference},
551       {"width", IntegerReference}, {"height", IntegerReference},
552       {"threshold", IntegerReference} } },
553     { "MeanShift", { {"geometry", StringReference},
554       {"width", IntegerReference}, {"height", IntegerReference},
555       {"distance", RealReference} } },
556     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
557       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
558     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
559     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
560       {"width", IntegerReference}, {"height", IntegerReference},
561       {"x", IntegerReference}, {"y", IntegerReference},
562       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
563       {"dx", IntegerReference}, {"dy", IntegerReference} } },
564   };
565
566 static SplayTreeInfo
567   *magick_registry = (SplayTreeInfo *) NULL;
568 \f
569 /*
570   Forward declarations.
571 */
572 static Image
573   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
574
575 static ssize_t
576   strEQcase(const char *,const char *);
577 \f
578 /*
579 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580 %                                                                             %
581 %                                                                             %
582 %                                                                             %
583 %   C l o n e P a c k a g e I n f o                                           %
584 %                                                                             %
585 %                                                                             %
586 %                                                                             %
587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
588 %
589 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
590 %  a new one.
591 %
592 %  The format of the ClonePackageInfo routine is:
593 %
594 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
595 %        exception)
596 %
597 %  A description of each parameter follows:
598 %
599 %    o info: a structure of type info.
600 %
601 %    o exception: Return any errors or warnings in this structure.
602 %
603 */
604 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
605   ExceptionInfo *exception)
606 {
607   struct PackageInfo
608     *clone_info;
609
610   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
611   if (clone_info == (struct PackageInfo *) NULL)
612     {
613       ThrowPerlException(exception,ResourceLimitError,
614         "UnableToClonePackageInfo",PackageName);
615       return((struct PackageInfo *) NULL);
616     }
617   if (info == (struct PackageInfo *) NULL)
618     {
619       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
620       return(clone_info);
621     }
622   *clone_info=(*info);
623   clone_info->image_info=CloneImageInfo(info->image_info);
624   return(clone_info);
625 }
626 \f
627 /*
628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
629 %                                                                             %
630 %                                                                             %
631 %                                                                             %
632 %   c o n s t a n t                                                           %
633 %                                                                             %
634 %                                                                             %
635 %                                                                             %
636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637 %
638 %  constant() returns a double value for the specified name.
639 %
640 %  The format of the constant routine is:
641 %
642 %      double constant(char *name,ssize_t sans)
643 %
644 %  A description of each parameter follows:
645 %
646 %    o value: Method constant returns a double value for the specified name.
647 %
648 %    o name: The name of the constant.
649 %
650 %    o sans: This integer value is not used.
651 %
652 */
653 static double constant(char *name,ssize_t sans)
654 {
655   (void) sans;
656   errno=0;
657   switch (*name)
658   {
659     case 'B':
660     {
661       if (strEQ(name,"BlobError"))
662         return(BlobError);
663       if (strEQ(name,"BlobWarning"))
664         return(BlobWarning);
665       break;
666     }
667     case 'C':
668     {
669       if (strEQ(name,"CacheError"))
670         return(CacheError);
671       if (strEQ(name,"CacheWarning"))
672         return(CacheWarning);
673       if (strEQ(name,"CoderError"))
674         return(CoderError);
675       if (strEQ(name,"CoderWarning"))
676         return(CoderWarning);
677       if (strEQ(name,"ConfigureError"))
678         return(ConfigureError);
679       if (strEQ(name,"ConfigureWarning"))
680         return(ConfigureWarning);
681       if (strEQ(name,"CorruptImageError"))
682         return(CorruptImageError);
683       if (strEQ(name,"CorruptImageWarning"))
684         return(CorruptImageWarning);
685       break;
686     }
687     case 'D':
688     {
689       if (strEQ(name,"DelegateError"))
690         return(DelegateError);
691       if (strEQ(name,"DelegateWarning"))
692         return(DelegateWarning);
693       if (strEQ(name,"DrawError"))
694         return(DrawError);
695       if (strEQ(name,"DrawWarning"))
696         return(DrawWarning);
697       break;
698     }
699     case 'E':
700     {
701       if (strEQ(name,"ErrorException"))
702         return(ErrorException);
703       if (strEQ(name,"ExceptionError"))
704         return(CoderError);
705       if (strEQ(name,"ExceptionWarning"))
706         return(CoderWarning);
707       break;
708     }
709     case 'F':
710     {
711       if (strEQ(name,"FatalErrorException"))
712         return(FatalErrorException);
713       if (strEQ(name,"FileOpenError"))
714         return(FileOpenError);
715       if (strEQ(name,"FileOpenWarning"))
716         return(FileOpenWarning);
717       break;
718     }
719     case 'I':
720     {
721       if (strEQ(name,"ImageError"))
722         return(ImageError);
723       if (strEQ(name,"ImageWarning"))
724         return(ImageWarning);
725       break;
726     }
727     case 'M':
728     {
729       if (strEQ(name,"MaxRGB"))
730         return(QuantumRange);
731       if (strEQ(name,"MissingDelegateError"))
732         return(MissingDelegateError);
733       if (strEQ(name,"MissingDelegateWarning"))
734         return(MissingDelegateWarning);
735       if (strEQ(name,"ModuleError"))
736         return(ModuleError);
737       if (strEQ(name,"ModuleWarning"))
738         return(ModuleWarning);
739       break;
740     }
741     case 'O':
742     {
743       if (strEQ(name,"Opaque"))
744         return(OpaqueAlpha);
745       if (strEQ(name,"OptionError"))
746         return(OptionError);
747       if (strEQ(name,"OptionWarning"))
748         return(OptionWarning);
749       break;
750     }
751     case 'Q':
752     {
753       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
754         return(MAGICKCORE_QUANTUM_DEPTH);
755       if (strEQ(name,"QuantumDepth"))
756         return(MAGICKCORE_QUANTUM_DEPTH);
757       if (strEQ(name,"QuantumRange"))
758         return(QuantumRange);
759       break;
760     }
761     case 'R':
762     {
763       if (strEQ(name,"ResourceLimitError"))
764         return(ResourceLimitError);
765       if (strEQ(name,"ResourceLimitWarning"))
766         return(ResourceLimitWarning);
767       if (strEQ(name,"RegistryError"))
768         return(RegistryError);
769       if (strEQ(name,"RegistryWarning"))
770         return(RegistryWarning);
771       break;
772     }
773     case 'S':
774     {
775       if (strEQ(name,"StreamError"))
776         return(StreamError);
777       if (strEQ(name,"StreamWarning"))
778         return(StreamWarning);
779       if (strEQ(name,"Success"))
780         return(0);
781       break;
782     }
783     case 'T':
784     {
785       if (strEQ(name,"Transparent"))
786         return(TransparentAlpha);
787       if (strEQ(name,"TypeError"))
788         return(TypeError);
789       if (strEQ(name,"TypeWarning"))
790         return(TypeWarning);
791       break;
792     }
793     case 'W':
794     {
795       if (strEQ(name,"WarningException"))
796         return(WarningException);
797       break;
798     }
799     case 'X':
800     {
801       if (strEQ(name,"XServerError"))
802         return(XServerError);
803       if (strEQ(name,"XServerWarning"))
804         return(XServerWarning);
805       break;
806     }
807   }
808   errno=EINVAL;
809   return(0);
810 }
811 \f
812 /*
813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
814 %                                                                             %
815 %                                                                             %
816 %                                                                             %
817 %   D e s t r o y P a c k a g e I n f o                                       %
818 %                                                                             %
819 %                                                                             %
820 %                                                                             %
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %
823 %  Method DestroyPackageInfo frees a previously created info structure.
824 %
825 %  The format of the DestroyPackageInfo routine is:
826 %
827 %      DestroyPackageInfo(struct PackageInfo *info)
828 %
829 %  A description of each parameter follows:
830 %
831 %    o info: a structure of type info.
832 %
833 */
834 static void DestroyPackageInfo(struct PackageInfo *info)
835 {
836   info->image_info=DestroyImageInfo(info->image_info);
837   info=(struct PackageInfo *) RelinquishMagickMemory(info);
838 }
839 \f
840 /*
841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842 %                                                                             %
843 %                                                                             %
844 %                                                                             %
845 %   G e t L i s t                                                             %
846 %                                                                             %
847 %                                                                             %
848 %                                                                             %
849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850 %
851 %  Method GetList is recursively called by SetupList to traverse the
852 %  Image__Magick reference.  If building an reference_vector (see SetupList),
853 %  *current is the current position in *reference_vector and *last is the final
854 %  entry in *reference_vector.
855 %
856 %  The format of the GetList routine is:
857 %
858 %      GetList(info)
859 %
860 %  A description of each parameter follows:
861 %
862 %    o info: a structure of type info.
863 %
864 */
865 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
866   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
867 {
868   Image
869     *image;
870
871   if (reference == (SV *) NULL)
872     return(NULL);
873   switch (SvTYPE(reference))
874   {
875     case SVt_PVAV:
876     {
877       AV
878         *av;
879
880       Image
881         *head,
882         *previous;
883
884       register ssize_t
885         i;
886
887       ssize_t
888         n;
889
890       /*
891         Array of images.
892       */
893       previous=(Image *) NULL;
894       head=(Image *) NULL;
895       av=(AV *) reference;
896       n=av_len(av);
897       for (i=0; i <= n; i++)
898       {
899         SV
900           **rv;
901
902         rv=av_fetch(av,i,0);
903         if (rv && *rv && sv_isobject(*rv))
904           {
905             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
906               exception);
907             if (image == (Image *) NULL)
908               continue;
909             if (image == previous)
910               {
911                 image=CloneImage(image,0,0,MagickTrue,exception);
912                 if (image == (Image *) NULL)
913                   return(NULL);
914               }
915             image->previous=previous;
916             *(previous ? &previous->next : &head)=image;
917             for (previous=image; previous->next; previous=previous->next) ;
918           }
919       }
920       return(head);
921     }
922     case SVt_PVMG:
923     {
924       /*
925         Blessed scalar, one image.
926       */
927       image=INT2PTR(Image *,SvIV(reference));
928       if (image == (Image *) NULL)
929         return(NULL);
930       image->previous=(Image *) NULL;
931       image->next=(Image *) NULL;
932       if (reference_vector)
933         {
934           if (*current == *last)
935             {
936               *last+=256;
937               if (*reference_vector == (SV **) NULL)
938                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
939                   sizeof(*reference_vector));
940               else
941                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
942                   *last,sizeof(*reference_vector));
943             }
944           if (*reference_vector == (SV **) NULL)
945             {
946               ThrowPerlException(exception,ResourceLimitError,
947                 "MemoryAllocationFailed",PackageName);
948               return((Image *) NULL);
949             }
950           (*reference_vector)[*current]=reference;
951           (*reference_vector)[++(*current)]=NULL;
952         }
953       return(image);
954     }
955     default:
956       break;
957   }
958   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
959     (double) SvTYPE(reference));
960   return((Image *) NULL);
961 }
962 \f
963 /*
964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
965 %                                                                             %
966 %                                                                             %
967 %                                                                             %
968 %   G e t P a c k a g e I n f o                                               %
969 %                                                                             %
970 %                                                                             %
971 %                                                                             %
972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
973 %
974 %  Method GetPackageInfo looks up or creates an info structure for the given
975 %  Image__Magick reference.  If it does create a new one, the information in
976 %  package_info is used to initialize it.
977 %
978 %  The format of the GetPackageInfo routine is:
979 %
980 %      struct PackageInfo *GetPackageInfo(void *reference,
981 %        struct PackageInfo *package_info,ExceptionInfo *exception)
982 %
983 %  A description of each parameter follows:
984 %
985 %    o info: a structure of type info.
986 %
987 %    o exception: Return any errors or warnings in this structure.
988 %
989 */
990 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
991   struct PackageInfo *package_info,ExceptionInfo *exception)
992 {
993   char
994     message[MagickPathExtent];
995
996   struct PackageInfo
997     *clone_info;
998
999   SV
1000     *sv;
1001
1002   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1003     PackageName,XS_VERSION,reference);
1004   sv=perl_get_sv(message,(TRUE | 0x02));
1005   if (sv == (SV *) NULL)
1006     {
1007       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1008         message);
1009       return(package_info);
1010     }
1011   if (SvREFCNT(sv) == 0)
1012     (void) SvREFCNT_inc(sv);
1013   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1014     return(clone_info);
1015   clone_info=ClonePackageInfo(package_info,exception);
1016   sv_setiv(sv,PTR2IV(clone_info));
1017   return(clone_info);
1018 }
1019 \f
1020 /*
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 %                                                                             %
1023 %                                                                             %
1024 %                                                                             %
1025 %   S e t A t t r i b u t e                                                   %
1026 %                                                                             %
1027 %                                                                             %
1028 %                                                                             %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %
1031 %  SetAttribute() sets the attribute to the value in sval.  This can change
1032 %  either or both of image or info.
1033 %
1034 %  The format of the SetAttribute routine is:
1035 %
1036 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1037 %        SV *sval,ExceptionInfo *exception)
1038 %
1039 %  A description of each parameter follows:
1040 %
1041 %    o list: a list of strings.
1042 %
1043 %    o string: a character string.
1044 %
1045 */
1046
1047 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1048 {
1049   char
1050     *q;
1051
1052   double
1053     value;
1054
1055   value=InterpretSiPrefixValue(string,&q);
1056   if (*q == '%')
1057     value*=interval/100.0;
1058   return(value);
1059 }
1060
1061 static inline double StringToDouble(const char *string,char **sentinal)
1062 {
1063   return(InterpretLocaleValue(string,sentinal));
1064 }
1065
1066 static double StringToDoubleInterval(const char *string,const double interval)
1067 {
1068   char
1069     *q;
1070
1071   double
1072     value;
1073
1074   value=InterpretLocaleValue(string,&q);
1075   if (*q == '%')
1076     value*=interval/100.0;
1077   return(value);
1078 }
1079
1080 static inline ssize_t StringToLong(const char *value)
1081 {
1082   return(strtol(value,(char **) NULL,10));
1083 }
1084
1085 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1086   const char *attribute,SV *sval,ExceptionInfo *exception)
1087 {
1088   GeometryInfo
1089     geometry_info;
1090
1091   long
1092     x,
1093     y;
1094
1095   PixelInfo
1096     pixel;
1097
1098   MagickStatusType
1099     flags;
1100
1101   PixelInfo
1102     *color,
1103     target_color;
1104
1105   ssize_t
1106     sp;
1107
1108   switch (*attribute)
1109   {
1110     case 'A':
1111     case 'a':
1112     {
1113       if (LocaleCompare(attribute,"adjoin") == 0)
1114         {
1115           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1116             SvPV(sval,na)) : SvIV(sval);
1117           if (sp < 0)
1118             {
1119               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1120                 SvPV(sval,na));
1121               break;
1122             }
1123           if (info)
1124             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1125           break;
1126         }
1127       if (LocaleCompare(attribute,"alpha") == 0)
1128         {
1129           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1130             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1131           if (sp < 0)
1132             {
1133               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1134                 SvPV(sval,na));
1135               break;
1136             }
1137           for ( ; image; image=image->next)
1138             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1139               exception);
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"antialias") == 0)
1143         {
1144           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1145             SvPV(sval,na)) : SvIV(sval);
1146           if (sp < 0)
1147             {
1148               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1149                 SvPV(sval,na));
1150               break;
1151             }
1152           if (info)
1153             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1154           break;
1155         }
1156       if (LocaleCompare(attribute,"area-limit") == 0)
1157         {
1158           MagickSizeType
1159             limit;
1160
1161           limit=MagickResourceInfinity;
1162           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1163             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1164               100.0);
1165           (void) SetMagickResourceLimit(AreaResource,limit);
1166           break;
1167         }
1168       if (LocaleCompare(attribute,"attenuate") == 0)
1169         {
1170           if (info)
1171             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1172           break;
1173         }
1174       if (LocaleCompare(attribute,"authenticate") == 0)
1175         {
1176           if (info)
1177             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1178           break;
1179         }
1180       if (info)
1181         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1182       for ( ; image; image=image->next)
1183         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1184       break;
1185     }
1186     case 'B':
1187     case 'b':
1188     {
1189       if (LocaleCompare(attribute,"background") == 0)
1190         {
1191           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1192             exception);
1193           if (info)
1194             info->image_info->background_color=target_color;
1195           for ( ; image; image=image->next)
1196             image->background_color=target_color;
1197           break;
1198         }
1199       if (LocaleCompare(attribute,"blue-primary") == 0)
1200         {
1201           for ( ; image; image=image->next)
1202           {
1203             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1204             image->chromaticity.blue_primary.x=geometry_info.rho;
1205             image->chromaticity.blue_primary.y=geometry_info.sigma;
1206             if ((flags & SigmaValue) == 0)
1207               image->chromaticity.blue_primary.y=
1208                 image->chromaticity.blue_primary.x;
1209           }
1210           break;
1211         }
1212       if (LocaleCompare(attribute,"bordercolor") == 0)
1213         {
1214           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1215             exception);
1216           if (info)
1217             info->image_info->border_color=target_color;
1218           for ( ; image; image=image->next)
1219             image->border_color=target_color;
1220           break;
1221         }
1222       if (info)
1223         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1224       for ( ; image; image=image->next)
1225         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1226       break;
1227     }
1228     case 'C':
1229     case 'c':
1230     {
1231       if (LocaleCompare(attribute,"cache-threshold") == 0)
1232         {
1233           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1234             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1235           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1236             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1237           break;
1238         }
1239       if (LocaleCompare(attribute,"clip-mask") == 0)
1240         {
1241           Image
1242             *clip_mask;
1243
1244           clip_mask=(Image *) NULL;
1245           if (SvPOK(sval))
1246             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1247           for ( ; image; image=image->next)
1248             SetImageMask(image,clip_mask,exception);
1249           break;
1250         }
1251       if (LocaleNCompare(attribute,"colormap",8) == 0)
1252         {
1253           for ( ; image; image=image->next)
1254           {
1255             int
1256               items;
1257
1258             long
1259               i;
1260
1261             if (image->storage_class == DirectClass)
1262               continue;
1263             i=0;
1264             items=sscanf(attribute,"%*[^[][%ld",&i);
1265             (void) items;
1266             if (i > (ssize_t) image->colors)
1267               i%=image->colors;
1268             if ((strchr(SvPV(sval,na),',') == 0) ||
1269                 (strchr(SvPV(sval,na),')') != 0))
1270               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1271                 image->colormap+i,exception);
1272             else
1273               {
1274                 color=image->colormap+i;
1275                 pixel.red=color->red;
1276                 pixel.green=color->green;
1277                 pixel.blue=color->blue;
1278                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1279                 pixel.red=geometry_info.rho;
1280                 pixel.green=geometry_info.sigma;
1281                 pixel.blue=geometry_info.xi;
1282                 color->red=ClampToQuantum(pixel.red);
1283                 color->green=ClampToQuantum(pixel.green);
1284                 color->blue=ClampToQuantum(pixel.blue);
1285               }
1286           }
1287           break;
1288         }
1289       if (LocaleCompare(attribute,"colorspace") == 0)
1290         {
1291           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1292             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1293           if (sp < 0)
1294             {
1295               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1296                 SvPV(sval,na));
1297               break;
1298             }
1299           for ( ; image; image=image->next)
1300             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1301               exception);
1302           break;
1303         }
1304       if (LocaleCompare(attribute,"comment") == 0)
1305         {
1306           for ( ; image; image=image->next)
1307             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1308               info ? info->image_info : (ImageInfo *) NULL,image,
1309               SvPV(sval,na),exception),exception);
1310           break;
1311         }
1312       if (LocaleCompare(attribute,"compression") == 0)
1313         {
1314           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1315             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1316           if (sp < 0)
1317             {
1318               ThrowPerlException(exception,OptionError,
1319                 "UnrecognizedImageCompression",SvPV(sval,na));
1320               break;
1321             }
1322           if (info)
1323             info->image_info->compression=(CompressionType) sp;
1324           for ( ; image; image=image->next)
1325             image->compression=(CompressionType) sp;
1326           break;
1327         }
1328       if (info)
1329         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1330       for ( ; image; image=image->next)
1331         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1332       break;
1333     }
1334     case 'D':
1335     case 'd':
1336     {
1337       if (LocaleCompare(attribute,"debug") == 0)
1338         {
1339           SetLogEventMask(SvPV(sval,na));
1340           break;
1341         }
1342       if (LocaleCompare(attribute,"delay") == 0)
1343         {
1344           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1345           for ( ; image; image=image->next)
1346           {
1347             image->delay=(size_t) floor(geometry_info.rho+0.5);
1348             if ((flags & SigmaValue) != 0)
1349               image->ticks_per_second=(ssize_t)
1350                 floor(geometry_info.sigma+0.5);
1351           }
1352           break;
1353         }
1354       if (LocaleCompare(attribute,"disk-limit") == 0)
1355         {
1356           MagickSizeType
1357             limit;
1358
1359           limit=MagickResourceInfinity;
1360           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1361             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1362               100.0);
1363           (void) SetMagickResourceLimit(DiskResource,limit);
1364           break;
1365         }
1366       if (LocaleCompare(attribute,"density") == 0)
1367         {
1368           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1369             {
1370               ThrowPerlException(exception,OptionError,"MissingGeometry",
1371                 SvPV(sval,na));
1372               break;
1373             }
1374           if (info)
1375             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1376           for ( ; image; image=image->next)
1377           {
1378             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1379             image->resolution.x=geometry_info.rho;
1380             image->resolution.y=geometry_info.sigma;
1381             if ((flags & SigmaValue) == 0)
1382               image->resolution.y=image->resolution.x;
1383           }
1384           break;
1385         }
1386       if (LocaleCompare(attribute,"depth") == 0)
1387         {
1388           if (info)
1389             info->image_info->depth=SvIV(sval);
1390           for ( ; image; image=image->next)
1391             (void) SetImageDepth(image,SvIV(sval),exception);
1392           break;
1393         }
1394       if (LocaleCompare(attribute,"dispose") == 0)
1395         {
1396           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1397             SvPV(sval,na)) : SvIV(sval);
1398           if (sp < 0)
1399             {
1400               ThrowPerlException(exception,OptionError,
1401                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1402               break;
1403             }
1404           for ( ; image; image=image->next)
1405             image->dispose=(DisposeType) sp;
1406           break;
1407         }
1408       if (LocaleCompare(attribute,"dither") == 0)
1409         {
1410           if (info)
1411             {
1412               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1413                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1414               if (sp < 0)
1415                 {
1416                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1417                     SvPV(sval,na));
1418                   break;
1419                 }
1420               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1421             }
1422           break;
1423         }
1424       if (LocaleCompare(attribute,"display") == 0)
1425         {
1426           display:
1427           if (info)
1428             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1429           break;
1430         }
1431       if (info)
1432         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1433       for ( ; image; image=image->next)
1434         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1435       break;
1436     }
1437     case 'E':
1438     case 'e':
1439     {
1440       if (LocaleCompare(attribute,"endian") == 0)
1441         {
1442           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1443             SvPV(sval,na)) : SvIV(sval);
1444           if (sp < 0)
1445             {
1446               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1447                 SvPV(sval,na));
1448               break;
1449             }
1450           if (info)
1451             info->image_info->endian=(EndianType) sp;
1452           for ( ; image; image=image->next)
1453             image->endian=(EndianType) sp;
1454           break;
1455         }
1456       if (LocaleCompare(attribute,"extract") == 0)
1457         {
1458           /*
1459             Set image extract geometry.
1460           */
1461           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1462           break;
1463         }
1464       if (info)
1465         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1466       for ( ; image; image=image->next)
1467         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1468       break;
1469     }
1470     case 'F':
1471     case 'f':
1472     {
1473       if (LocaleCompare(attribute,"filename") == 0)
1474         {
1475           if (info)
1476             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1477               MagickPathExtent);
1478           for ( ; image; image=image->next)
1479             (void) CopyMagickString(image->filename,SvPV(sval,na),
1480               MagickPathExtent);
1481           break;
1482         }
1483       if (LocaleCompare(attribute,"file") == 0)
1484         {
1485           FILE
1486             *file;
1487
1488           PerlIO
1489             *io_info;
1490
1491           if (info == (struct PackageInfo *) NULL)
1492             break;
1493           io_info=IoIFP(sv_2io(sval));
1494           if (io_info == (PerlIO *) NULL)
1495             {
1496               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1497                 PackageName);
1498               break;
1499             }
1500           file=PerlIO_findFILE(io_info);
1501           if (file == (FILE *) NULL)
1502             {
1503               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1504                 PackageName);
1505               break;
1506             }
1507           SetImageInfoFile(info->image_info,file);
1508           break;
1509         }
1510       if (LocaleCompare(attribute,"fill") == 0)
1511         {
1512           if (info)
1513             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1514           break;
1515         }
1516       if (LocaleCompare(attribute,"font") == 0)
1517         {
1518           if (info)
1519             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1520           break;
1521         }
1522       if (LocaleCompare(attribute,"foreground") == 0)
1523         break;
1524       if (LocaleCompare(attribute,"fuzz") == 0)
1525         {
1526           if (info)
1527             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1528               QuantumRange+1.0);
1529           for ( ; image; image=image->next)
1530             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1531               QuantumRange+1.0);
1532           break;
1533         }
1534       if (info)
1535         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1536       for ( ; image; image=image->next)
1537         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1538       break;
1539     }
1540     case 'G':
1541     case 'g':
1542     {
1543       if (LocaleCompare(attribute,"gamma") == 0)
1544         {
1545           for ( ; image; image=image->next)
1546             image->gamma=SvNV(sval);
1547           break;
1548         }
1549       if (LocaleCompare(attribute,"gravity") == 0)
1550         {
1551           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1552             SvPV(sval,na)) : SvIV(sval);
1553           if (sp < 0)
1554             {
1555               ThrowPerlException(exception,OptionError,
1556                 "UnrecognizedGravityType",SvPV(sval,na));
1557               break;
1558             }
1559           if (info)
1560             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1561           for ( ; image; image=image->next)
1562             image->gravity=(GravityType) sp;
1563           break;
1564         }
1565       if (LocaleCompare(attribute,"green-primary") == 0)
1566         {
1567           for ( ; image; image=image->next)
1568           {
1569             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1570             image->chromaticity.green_primary.x=geometry_info.rho;
1571             image->chromaticity.green_primary.y=geometry_info.sigma;
1572             if ((flags & SigmaValue) == 0)
1573               image->chromaticity.green_primary.y=
1574                 image->chromaticity.green_primary.x;
1575           }
1576           break;
1577         }
1578       if (info)
1579         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1580       for ( ; image; image=image->next)
1581         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1582       break;
1583     }
1584     case 'I':
1585     case 'i':
1586     {
1587       if (LocaleNCompare(attribute,"index",5) == 0)
1588         {
1589           int
1590             items;
1591
1592           long
1593             index;
1594
1595           register Quantum
1596             *q;
1597
1598           CacheView
1599             *image_view;
1600
1601           for ( ; image; image=image->next)
1602           {
1603             if (image->storage_class != PseudoClass)
1604               continue;
1605             x=0;
1606             y=0;
1607             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1608             (void) items;
1609             image_view=AcquireAuthenticCacheView(image,exception);
1610             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1611             if (q != (Quantum *) NULL)
1612               {
1613                 items=sscanf(SvPV(sval,na),"%ld",&index);
1614                 if ((index >= 0) && (index < (ssize_t) image->colors))
1615                   SetPixelIndex(image,index,q);
1616                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1617               }
1618             image_view=DestroyCacheView(image_view);
1619           }
1620           break;
1621         }
1622       if (LocaleCompare(attribute,"iterations") == 0)
1623         {
1624   iterations:
1625           for ( ; image; image=image->next)
1626             image->iterations=SvIV(sval);
1627           break;
1628         }
1629       if (LocaleCompare(attribute,"interlace") == 0)
1630         {
1631           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1632             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1633           if (sp < 0)
1634             {
1635               ThrowPerlException(exception,OptionError,
1636                 "UnrecognizedInterlaceType",SvPV(sval,na));
1637               break;
1638             }
1639           if (info)
1640             info->image_info->interlace=(InterlaceType) sp;
1641           for ( ; image; image=image->next)
1642             image->interlace=(InterlaceType) sp;
1643           break;
1644         }
1645       if (info)
1646         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1647       for ( ; image; image=image->next)
1648         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1649       break;
1650     }
1651     case 'L':
1652     case 'l':
1653     {
1654       if (LocaleCompare(attribute,"label") == 0)
1655         {
1656           for ( ; image; image=image->next)
1657             (void) SetImageProperty(image,"label",InterpretImageProperties(
1658               info ? info->image_info : (ImageInfo *) NULL,image,
1659               SvPV(sval,na),exception),exception);
1660           break;
1661         }
1662       if (LocaleCompare(attribute,"loop") == 0)
1663         goto iterations;
1664       if (info)
1665         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1666       for ( ; image; image=image->next)
1667         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1668       break;
1669     }
1670     case 'M':
1671     case 'm':
1672     {
1673       if (LocaleCompare(attribute,"magick") == 0)
1674         {
1675           if (info)
1676             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1677               "%s:",SvPV(sval,na));
1678           for ( ; image; image=image->next)
1679             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1680           break;
1681         }
1682       if (LocaleCompare(attribute,"map-limit") == 0)
1683         {
1684           MagickSizeType
1685             limit;
1686
1687           limit=MagickResourceInfinity;
1688           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1689             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1690               100.0);
1691           (void) SetMagickResourceLimit(MapResource,limit);
1692           break;
1693         }
1694       if (LocaleCompare(attribute,"mask") == 0)
1695         {
1696           Image
1697             *mask;
1698
1699           mask=(Image *) NULL;
1700           if (SvPOK(sval))
1701             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1702           for ( ; image; image=image->next)
1703             SetImageMask(image,mask,exception);
1704           break;
1705         }
1706       if (LocaleCompare(attribute,"mattecolor") == 0)
1707         {
1708           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1709             exception);
1710           if (info)
1711             info->image_info->matte_color=target_color;
1712           for ( ; image; image=image->next)
1713             image->matte_color=target_color;
1714           break;
1715         }
1716       if (LocaleCompare(attribute,"matte") == 0)
1717         {
1718           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1719             SvPV(sval,na)) : SvIV(sval);
1720           if (sp < 0)
1721             {
1722               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1723                 SvPV(sval,na));
1724               break;
1725             }
1726           for ( ; image; image=image->next)
1727             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1728           break;
1729         }
1730       if (LocaleCompare(attribute,"memory-limit") == 0)
1731         {
1732           MagickSizeType
1733             limit;
1734
1735           limit=MagickResourceInfinity;
1736           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1737             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1738               100.0);
1739           (void) SetMagickResourceLimit(MemoryResource,limit);
1740           break;
1741         }
1742       if (LocaleCompare(attribute,"monochrome") == 0)
1743         {
1744           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1745             SvPV(sval,na)) : SvIV(sval);
1746           if (sp < 0)
1747             {
1748               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1749                 SvPV(sval,na));
1750               break;
1751             }
1752           if (info)
1753             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1754           for ( ; image; image=image->next)
1755             (void) SetImageType(image,BilevelType,exception);
1756           break;
1757         }
1758       if (info)
1759         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1760       for ( ; image; image=image->next)
1761         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1762       break;
1763     }
1764     case 'O':
1765     case 'o':
1766     {
1767       if (LocaleCompare(attribute,"option") == 0)
1768         {
1769           if (info)
1770             DefineImageOption(info->image_info,SvPV(sval,na));
1771           break;
1772         }
1773       if (LocaleCompare(attribute,"orientation") == 0)
1774         {
1775           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1776             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1777           if (sp < 0)
1778             {
1779               ThrowPerlException(exception,OptionError,
1780                 "UnrecognizedOrientationType",SvPV(sval,na));
1781               break;
1782             }
1783           if (info)
1784             info->image_info->orientation=(OrientationType) sp;
1785           for ( ; image; image=image->next)
1786             image->orientation=(OrientationType) sp;
1787           break;
1788         }
1789       if (info)
1790         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1791       for ( ; image; image=image->next)
1792         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1793       break;
1794     }
1795     case 'P':
1796     case 'p':
1797     {
1798       if (LocaleCompare(attribute,"page") == 0)
1799         {
1800           char
1801             *geometry;
1802
1803           geometry=GetPageGeometry(SvPV(sval,na));
1804           if (info)
1805             (void) CloneString(&info->image_info->page,geometry);
1806           for ( ; image; image=image->next)
1807             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1808           geometry=(char *) RelinquishMagickMemory(geometry);
1809           break;
1810         }
1811       if (LocaleNCompare(attribute,"pixel",5) == 0)
1812         {
1813           int
1814             items;
1815
1816           PixelInfo
1817             pixel;
1818
1819           register Quantum
1820             *q;
1821
1822           CacheView
1823             *image_view;
1824
1825           for ( ; image; image=image->next)
1826           {
1827             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1828               break;
1829             x=0;
1830             y=0;
1831             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1832             (void) items;
1833             image_view=AcquireVirtualCacheView(image,exception);
1834             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1835             if (q != (Quantum *) NULL)
1836               {
1837                 if ((strchr(SvPV(sval,na),',') == 0) ||
1838                     (strchr(SvPV(sval,na),')') != 0))
1839                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1840                     &pixel,exception);
1841                 else
1842                   {
1843                     GetPixelInfo(image,&pixel);
1844                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1845                     pixel.red=geometry_info.rho;
1846                     if ((flags & SigmaValue) != 0)
1847                       pixel.green=geometry_info.sigma;
1848                     if ((flags & XiValue) != 0)
1849                       pixel.blue=geometry_info.xi;
1850                     if ((flags & PsiValue) != 0)
1851                       pixel.alpha=geometry_info.psi;
1852                     if ((flags & ChiValue) != 0)
1853                       pixel.black=geometry_info.chi;
1854                   }
1855                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1856                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1857                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1858                 if (image->colorspace == CMYKColorspace)
1859                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1860                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1861                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1862               }
1863             image_view=DestroyCacheView(image_view);
1864           }
1865           break;
1866         }
1867       if (LocaleCompare(attribute,"pointsize") == 0)
1868         {
1869           if (info)
1870             {
1871               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1872               info->image_info->pointsize=geometry_info.rho;
1873             }
1874           break;
1875         }
1876       if (LocaleCompare(attribute,"preview") == 0)
1877         {
1878           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1879             SvPV(sval,na)) : SvIV(sval);
1880           if (sp < 0)
1881             {
1882               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1883                 SvPV(sval,na));
1884               break;
1885             }
1886           if (info)
1887             info->image_info->preview_type=(PreviewType) sp;
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 'Q':
1897     case 'q':
1898     {
1899       if (LocaleCompare(attribute,"quality") == 0)
1900         {
1901           if (info)
1902             info->image_info->quality=SvIV(sval);
1903           for ( ; image; image=image->next)
1904             image->quality=SvIV(sval);
1905           break;
1906         }
1907       if (info)
1908         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1909       for ( ; image; image=image->next)
1910         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1911       break;
1912     }
1913     case 'R':
1914     case 'r':
1915     {
1916       if (LocaleCompare(attribute,"red-primary") == 0)
1917         {
1918           for ( ; image; image=image->next)
1919           {
1920             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1921             image->chromaticity.red_primary.x=geometry_info.rho;
1922             image->chromaticity.red_primary.y=geometry_info.sigma;
1923             if ((flags & SigmaValue) == 0)
1924               image->chromaticity.red_primary.y=
1925                 image->chromaticity.red_primary.x;
1926           }
1927           break;
1928         }
1929       if (LocaleCompare(attribute,"render") == 0)
1930         {
1931           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1932             SvPV(sval,na)) : SvIV(sval);
1933           if (sp < 0)
1934             {
1935               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1936                 SvPV(sval,na));
1937               break;
1938             }
1939          for ( ; image; image=image->next)
1940            image->rendering_intent=(RenderingIntent) sp;
1941          break;
1942        }
1943       if (LocaleCompare(attribute,"repage") == 0)
1944         {
1945           RectangleInfo
1946             geometry;
1947
1948           for ( ; image; image=image->next)
1949           {
1950             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1951             if ((flags & WidthValue) != 0)
1952               {
1953                 if ((flags & HeightValue) == 0)
1954                   geometry.height=geometry.width;
1955                 image->page.width=geometry.width;
1956                 image->page.height=geometry.height;
1957               }
1958             if ((flags & AspectValue) != 0)
1959               {
1960                 if ((flags & XValue) != 0)
1961                   image->page.x+=geometry.x;
1962                 if ((flags & YValue) != 0)
1963                   image->page.y+=geometry.y;
1964               }
1965             else
1966               {
1967                 if ((flags & XValue) != 0)
1968                   {
1969                     image->page.x=geometry.x;
1970                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1971                       image->page.width=image->columns+geometry.x;
1972                   }
1973                 if ((flags & YValue) != 0)
1974                   {
1975                     image->page.y=geometry.y;
1976                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1977                       image->page.height=image->rows+geometry.y;
1978                   }
1979               }
1980           }
1981           break;
1982         }
1983       if (info)
1984         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1985       for ( ; image; image=image->next)
1986         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1987       break;
1988     }
1989     case 'S':
1990     case 's':
1991     {
1992       if (LocaleCompare(attribute,"sampling-factor") == 0)
1993         {
1994           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1995             {
1996               ThrowPerlException(exception,OptionError,"MissingGeometry",
1997                 SvPV(sval,na));
1998               break;
1999             }
2000           if (info)
2001             (void) CloneString(&info->image_info->sampling_factor,
2002               SvPV(sval,na));
2003           break;
2004         }
2005       if (LocaleCompare(attribute,"scene") == 0)
2006         {
2007           for ( ; image; image=image->next)
2008             image->scene=SvIV(sval);
2009           break;
2010         }
2011       if (LocaleCompare(attribute,"server") == 0)
2012         goto display;
2013       if (LocaleCompare(attribute,"size") == 0)
2014         {
2015           if (info)
2016             {
2017               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2018                 {
2019                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2020                     SvPV(sval,na));
2021                   break;
2022                 }
2023               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2024             }
2025           break;
2026         }
2027       if (LocaleCompare(attribute,"stroke") == 0)
2028         {
2029           if (info)
2030             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2031           break;
2032         }
2033       if (info)
2034         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2035       for ( ; image; image=image->next)
2036         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2037       break;
2038     }
2039     case 'T':
2040     case 't':
2041     {
2042       if (LocaleCompare(attribute,"texture") == 0)
2043         {
2044           if (info)
2045             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2046           break;
2047         }
2048       if (LocaleCompare(attribute,"thread-limit") == 0)
2049         {
2050           MagickSizeType
2051             limit;
2052
2053           limit=MagickResourceInfinity;
2054           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2055             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2056               100.0);
2057           (void) SetMagickResourceLimit(ThreadResource,limit);
2058           break;
2059         }
2060       if (LocaleCompare(attribute,"tile-offset") == 0)
2061         {
2062           char
2063             *geometry;
2064
2065           geometry=GetPageGeometry(SvPV(sval,na));
2066           if (info)
2067             (void) CloneString(&info->image_info->page,geometry);
2068           for ( ; image; image=image->next)
2069             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2070               exception);
2071           geometry=(char *) RelinquishMagickMemory(geometry);
2072           break;
2073         }
2074       if (LocaleCompare(attribute,"time-limit") == 0)
2075         {
2076           MagickSizeType
2077             limit;
2078
2079           limit=MagickResourceInfinity;
2080           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2081             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2082               100.0);
2083           (void) SetMagickResourceLimit(TimeResource,limit);
2084           break;
2085         }
2086       if (LocaleCompare(attribute,"transparent-color") == 0)
2087         {
2088           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2089             exception);
2090           if (info)
2091             info->image_info->transparent_color=target_color;
2092           for ( ; image; image=image->next)
2093             image->transparent_color=target_color;
2094           break;
2095         }
2096       if (LocaleCompare(attribute,"type") == 0)
2097         {
2098           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2099             SvPV(sval,na)) : SvIV(sval);
2100           if (sp < 0)
2101             {
2102               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2103                 SvPV(sval,na));
2104               break;
2105             }
2106           if (info)
2107             info->image_info->type=(ImageType) sp;
2108           for ( ; image; image=image->next)
2109             SetImageType(image,(ImageType) sp,exception);
2110           break;
2111         }
2112       if (info)
2113         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2114       for ( ; image; image=image->next)
2115         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2116       break;
2117     }
2118     case 'U':
2119     case 'u':
2120     {
2121       if (LocaleCompare(attribute,"units") == 0)
2122         {
2123           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2124             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2125           if (sp < 0)
2126             {
2127               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2128                 SvPV(sval,na));
2129               break;
2130             }
2131           if (info)
2132             info->image_info->units=(ResolutionType) sp;
2133           for ( ; image; image=image->next)
2134           {
2135             ResolutionType
2136               units;
2137
2138             units=(ResolutionType) sp;
2139             if (image->units != units)
2140               switch (image->units)
2141               {
2142                 case UndefinedResolution:
2143                 case PixelsPerInchResolution:
2144                 {
2145                   if (units == PixelsPerCentimeterResolution)
2146                     {
2147                       image->resolution.x*=2.54;
2148                       image->resolution.y*=2.54;
2149                     }
2150                   break;
2151                 }
2152                 case PixelsPerCentimeterResolution:
2153                 {
2154                   if (units == PixelsPerInchResolution)
2155                     {
2156                       image->resolution.x/=2.54;
2157                       image->resolution.y/=2.54;
2158                     }
2159                   break;
2160                 }
2161               }
2162             image->units=units;
2163           }
2164           break;
2165         }
2166       if (info)
2167         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2168       for ( ; image; image=image->next)
2169         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2170       break;
2171     }
2172     case 'V':
2173     case 'v':
2174     {
2175       if (LocaleCompare(attribute,"verbose") == 0)
2176         {
2177           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2178             SvPV(sval,na)) : SvIV(sval);
2179           if (sp < 0)
2180             {
2181               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2182                 SvPV(sval,na));
2183               break;
2184             }
2185           if (info)
2186             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2187           break;
2188         }
2189       if (LocaleCompare(attribute,"view") == 0)
2190         {
2191           if (info)
2192             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2193           break;
2194         }
2195       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2196         {
2197           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2198             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2199           if (sp < 0)
2200             {
2201               ThrowPerlException(exception,OptionError,
2202                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2203               break;
2204             }
2205           for ( ; image; image=image->next)
2206             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2207           break;
2208         }
2209       if (info)
2210         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2211       for ( ; image; image=image->next)
2212         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2213       break;
2214     }
2215     case 'W':
2216     case 'w':
2217     {
2218       if (LocaleCompare(attribute,"white-point") == 0)
2219         {
2220           for ( ; image; image=image->next)
2221           {
2222             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2223             image->chromaticity.white_point.x=geometry_info.rho;
2224             image->chromaticity.white_point.y=geometry_info.sigma;
2225             if ((flags & SigmaValue) == 0)
2226               image->chromaticity.white_point.y=
2227                 image->chromaticity.white_point.x;
2228           }
2229           break;
2230         }
2231       if (info)
2232         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2233       for ( ; image; image=image->next)
2234         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2235       break;
2236     }
2237     default:
2238     {
2239       if (info)
2240         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2241       for ( ; image; image=image->next)
2242         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2243       break;
2244     }
2245   }
2246 }
2247 \f
2248 /*
2249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2250 %                                                                             %
2251 %                                                                             %
2252 %                                                                             %
2253 %   S e t u p L i s t                                                         %
2254 %                                                                             %
2255 %                                                                             %
2256 %                                                                             %
2257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2258 %
2259 %  Method SetupList returns the list of all the images linked by their
2260 %  image->next and image->previous link lists for use with ImageMagick.  If
2261 %  info is non-NULL, an info structure is returned in *info.  If
2262 %  reference_vector is non-NULL,an array of SV* are returned in
2263 %  *reference_vector.  Reference_vector is used when the images are going to be
2264 %  replaced with new Image*'s.
2265 %
2266 %  The format of the SetupList routine is:
2267 %
2268 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2269 %        SV ***reference_vector,ExceptionInfo *exception)
2270 %
2271 %  A description of each parameter follows:
2272 %
2273 %    o list: a list of strings.
2274 %
2275 %    o string: a character string.
2276 %
2277 %    o exception: Return any errors or warnings in this structure.
2278 %
2279 */
2280 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2281   SV ***reference_vector,ExceptionInfo *exception)
2282 {
2283   Image
2284     *image;
2285
2286   ssize_t
2287     current,
2288     last;
2289
2290   if (reference_vector)
2291     *reference_vector=NULL;
2292   if (info)
2293     *info=NULL;
2294   current=0;
2295   last=0;
2296   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2297   if (info && (SvTYPE(reference) == SVt_PVAV))
2298     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2299       exception);
2300   return(image);
2301 }
2302 \f
2303 /*
2304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2305 %                                                                             %
2306 %                                                                             %
2307 %                                                                             %
2308 %   s t r E Q c a s e                                                         %
2309 %                                                                             %
2310 %                                                                             %
2311 %                                                                             %
2312 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2313 %
2314 %  strEQcase() compares two strings and returns 0 if they are the
2315 %  same or if the second string runs out first.  The comparison is case
2316 %  insensitive.
2317 %
2318 %  The format of the strEQcase routine is:
2319 %
2320 %      ssize_t strEQcase(const char *p,const char *q)
2321 %
2322 %  A description of each parameter follows:
2323 %
2324 %    o p: a character string.
2325 %
2326 %    o q: a character string.
2327 %
2328 %
2329 */
2330 static ssize_t strEQcase(const char *p,const char *q)
2331 {
2332   char
2333     c;
2334
2335   register ssize_t
2336     i;
2337
2338   for (i=0 ; (c=(*q)) != 0; i++)
2339   {
2340     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2341         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2342       return(0);
2343     p++;
2344     q++;
2345   }
2346   return(((*q == 0) && (*p == 0)) ? i : 0);
2347 }
2348 \f
2349 /*
2350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2351 %                                                                             %
2352 %                                                                             %
2353 %                                                                             %
2354 %   I m a g e : : M a g i c k                                                 %
2355 %                                                                             %
2356 %                                                                             %
2357 %                                                                             %
2358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2359 %
2360 %
2361 */
2362 MODULE = Image::Magick PACKAGE = Image::Magick
2363
2364 PROTOTYPES: ENABLE
2365
2366 BOOT:
2367   MagickCoreGenesis("PerlMagick",MagickFalse);
2368   SetWarningHandler(NULL);
2369   SetErrorHandler(NULL);
2370   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2371     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2372
2373 void
2374 UNLOAD()
2375   PPCODE:
2376   {
2377     if (magick_registry != (SplayTreeInfo *) NULL)
2378       magick_registry=DestroySplayTree(magick_registry);
2379     MagickCoreTerminus();
2380   }
2381
2382 double
2383 constant(name,argument)
2384   char *name
2385   ssize_t argument
2386 \f
2387 #
2388 ###############################################################################
2389 #                                                                             #
2390 #                                                                             #
2391 #                                                                             #
2392 #   A n i m a t e                                                             #
2393 #                                                                             #
2394 #                                                                             #
2395 #                                                                             #
2396 ###############################################################################
2397 #
2398 #
2399 void
2400 Animate(ref,...)
2401   Image::Magick ref=NO_INIT
2402   ALIAS:
2403     AnimateImage  = 1
2404     animate       = 2
2405     animateimage  = 3
2406   PPCODE:
2407   {
2408     ExceptionInfo
2409       *exception;
2410
2411     Image
2412       *image;
2413
2414     register ssize_t
2415       i;
2416
2417     struct PackageInfo
2418       *info,
2419       *package_info;
2420
2421     SV
2422       *perl_exception,
2423       *reference;
2424
2425     PERL_UNUSED_VAR(ref);
2426     PERL_UNUSED_VAR(ix);
2427     exception=AcquireExceptionInfo();
2428     perl_exception=newSVpv("",0);
2429     package_info=(struct PackageInfo *) NULL;
2430     if (sv_isobject(ST(0)) == 0)
2431       {
2432         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2433           PackageName);
2434         goto PerlException;
2435       }
2436     reference=SvRV(ST(0));
2437     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2438     if (image == (Image *) NULL)
2439       {
2440         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2441           PackageName);
2442         goto PerlException;
2443       }
2444     package_info=ClonePackageInfo(info,exception);
2445     if (items == 2)
2446       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2447     else
2448       if (items > 2)
2449         for (i=2; i < items; i+=2)
2450           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2451             exception);
2452     (void) AnimateImages(package_info->image_info,image,exception);
2453     (void) CatchImageException(image);
2454
2455   PerlException:
2456     if (package_info != (struct PackageInfo *) NULL)
2457       DestroyPackageInfo(package_info);
2458     InheritPerlException(exception,perl_exception);
2459     exception=DestroyExceptionInfo(exception);
2460     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2461     SvPOK_on(perl_exception);
2462     ST(0)=sv_2mortal(perl_exception);
2463     XSRETURN(1);
2464   }
2465 \f
2466 #
2467 ###############################################################################
2468 #                                                                             #
2469 #                                                                             #
2470 #                                                                             #
2471 #   A p p e n d                                                               #
2472 #                                                                             #
2473 #                                                                             #
2474 #                                                                             #
2475 ###############################################################################
2476 #
2477 #
2478 void
2479 Append(ref,...)
2480   Image::Magick ref=NO_INIT
2481   ALIAS:
2482     AppendImage  = 1
2483     append       = 2
2484     appendimage  = 3
2485   PPCODE:
2486   {
2487     AV
2488       *av;
2489
2490     char
2491       *attribute;
2492
2493     ExceptionInfo
2494       *exception;
2495
2496     HV
2497       *hv;
2498
2499     Image
2500       *image;
2501
2502     register ssize_t
2503       i;
2504
2505     ssize_t
2506       stack;
2507
2508     struct PackageInfo
2509       *info;
2510
2511     SV
2512       *av_reference,
2513       *perl_exception,
2514       *reference,
2515       *rv,
2516       *sv;
2517
2518     PERL_UNUSED_VAR(ref);
2519     PERL_UNUSED_VAR(ix);
2520     exception=AcquireExceptionInfo();
2521     perl_exception=newSVpv("",0);
2522     sv=NULL;
2523     attribute=NULL;
2524     av=NULL;
2525     if (sv_isobject(ST(0)) == 0)
2526       {
2527         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2528           PackageName);
2529         goto PerlException;
2530       }
2531     reference=SvRV(ST(0));
2532     hv=SvSTASH(reference);
2533     av=newAV();
2534     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2535     SvREFCNT_dec(av);
2536     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2537     if (image == (Image *) NULL)
2538       {
2539         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2540           PackageName);
2541         goto PerlException;
2542       }
2543     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2544     /*
2545       Get options.
2546     */
2547     stack=MagickTrue;
2548     for (i=2; i < items; i+=2)
2549     {
2550       attribute=(char *) SvPV(ST(i-1),na);
2551       switch (*attribute)
2552       {
2553         case 'S':
2554         case 's':
2555         {
2556           if (LocaleCompare(attribute,"stack") == 0)
2557             {
2558               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2559                 SvPV(ST(i),na));
2560               if (stack < 0)
2561                 {
2562                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2563                     SvPV(ST(i),na));
2564                   return;
2565                 }
2566               break;
2567             }
2568           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2569             attribute);
2570           break;
2571         }
2572         default:
2573         {
2574           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2575             attribute);
2576           break;
2577         }
2578       }
2579     }
2580     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2581     if (image == (Image *) NULL)
2582       goto PerlException;
2583     for ( ; image; image=image->next)
2584     {
2585       AddImageToRegistry(sv,image);
2586       rv=newRV(sv);
2587       av_push(av,sv_bless(rv,hv));
2588       SvREFCNT_dec(sv);
2589     }
2590     exception=DestroyExceptionInfo(exception);
2591     ST(0)=av_reference;
2592     SvREFCNT_dec(perl_exception);
2593     XSRETURN(1);
2594
2595   PerlException:
2596     InheritPerlException(exception,perl_exception);
2597     exception=DestroyExceptionInfo(exception);
2598     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2599     SvPOK_on(perl_exception);
2600     ST(0)=sv_2mortal(perl_exception);
2601     XSRETURN(1);
2602   }
2603 \f
2604 #
2605 ###############################################################################
2606 #                                                                             #
2607 #                                                                             #
2608 #                                                                             #
2609 #   A v e r a g e                                                             #
2610 #                                                                             #
2611 #                                                                             #
2612 #                                                                             #
2613 ###############################################################################
2614 #
2615 #
2616 void
2617 Average(ref)
2618   Image::Magick ref=NO_INIT
2619   ALIAS:
2620     AverageImage   = 1
2621     average        = 2
2622     averageimage   = 3
2623   PPCODE:
2624   {
2625     AV
2626       *av;
2627
2628     char
2629       *p;
2630
2631     ExceptionInfo
2632       *exception;
2633
2634     HV
2635       *hv;
2636
2637     Image
2638       *image;
2639
2640     struct PackageInfo
2641       *info;
2642
2643     SV
2644       *perl_exception,
2645       *reference,
2646       *rv,
2647       *sv;
2648
2649     PERL_UNUSED_VAR(ref);
2650     PERL_UNUSED_VAR(ix);
2651     exception=AcquireExceptionInfo();
2652     perl_exception=newSVpv("",0);
2653     sv=NULL;
2654     if (sv_isobject(ST(0)) == 0)
2655       {
2656         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2657           PackageName);
2658         goto PerlException;
2659       }
2660     reference=SvRV(ST(0));
2661     hv=SvSTASH(reference);
2662     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2663     if (image == (Image *) NULL)
2664       {
2665         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2666           PackageName);
2667         goto PerlException;
2668       }
2669     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2670     if (image == (Image *) NULL)
2671       goto PerlException;
2672     /*
2673       Create blessed Perl array for the returned image.
2674     */
2675     av=newAV();
2676     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2677     SvREFCNT_dec(av);
2678     AddImageToRegistry(sv,image);
2679     rv=newRV(sv);
2680     av_push(av,sv_bless(rv,hv));
2681     SvREFCNT_dec(sv);
2682     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2683     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2684       "average-%.*s",(int) (MagickPathExtent-9),
2685       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2686     (void) CopyMagickString(image->filename,info->image_info->filename,
2687       MagickPathExtent);
2688     SetImageInfo(info->image_info,0,exception);
2689     exception=DestroyExceptionInfo(exception);
2690     SvREFCNT_dec(perl_exception);
2691     XSRETURN(1);
2692
2693   PerlException:
2694     InheritPerlException(exception,perl_exception);
2695     exception=DestroyExceptionInfo(exception);
2696     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2697     SvPOK_on(perl_exception);
2698     ST(0)=sv_2mortal(perl_exception);
2699     XSRETURN(1);
2700   }
2701 \f
2702 #
2703 ###############################################################################
2704 #                                                                             #
2705 #                                                                             #
2706 #                                                                             #
2707 #   B l o b T o I m a g e                                                     #
2708 #                                                                             #
2709 #                                                                             #
2710 #                                                                             #
2711 ###############################################################################
2712 #
2713 #
2714 void
2715 BlobToImage(ref,...)
2716   Image::Magick ref=NO_INIT
2717   ALIAS:
2718     BlobToImage  = 1
2719     blobtoimage  = 2
2720     blobto       = 3
2721   PPCODE:
2722   {
2723     AV
2724       *av;
2725
2726     char
2727       **keep,
2728       **list;
2729
2730     ExceptionInfo
2731       *exception;
2732
2733     HV
2734       *hv;
2735
2736     Image
2737       *image;
2738
2739     register char
2740       **p;
2741
2742     register ssize_t
2743       i;
2744
2745     ssize_t
2746       ac,
2747       n,
2748       number_images;
2749
2750     STRLEN
2751       *length;
2752
2753     struct PackageInfo
2754       *info;
2755
2756     SV
2757       *perl_exception,
2758       *reference,
2759       *rv,
2760       *sv;
2761
2762     PERL_UNUSED_VAR(ref);
2763     PERL_UNUSED_VAR(ix);
2764     exception=AcquireExceptionInfo();
2765     perl_exception=newSVpv("",0);
2766     sv=NULL;
2767     number_images=0;
2768     ac=(items < 2) ? 1 : items-1;
2769     length=(STRLEN *) NULL;
2770     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2771     if (list == (char **) NULL)
2772       {
2773         ThrowPerlException(exception,ResourceLimitError,
2774           "MemoryAllocationFailed",PackageName);
2775         goto PerlException;
2776       }
2777     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2778     if (length == (STRLEN *) NULL)
2779       {
2780         ThrowPerlException(exception,ResourceLimitError,
2781           "MemoryAllocationFailed",PackageName);
2782         goto PerlException;
2783       }
2784     if (sv_isobject(ST(0)) == 0)
2785       {
2786         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2787           PackageName);
2788         goto PerlException;
2789       }
2790     reference=SvRV(ST(0));
2791     hv=SvSTASH(reference);
2792     if (SvTYPE(reference) != SVt_PVAV)
2793       {
2794         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2795           PackageName);
2796         goto PerlException;
2797       }
2798     av=(AV *) reference;
2799     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2800       exception);
2801     n=1;
2802     if (items <= 1)
2803       {
2804         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2805         goto PerlException;
2806       }
2807     for (n=0, i=0; i < ac; i++)
2808     {
2809       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2810       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2811         {
2812           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2813           continue;
2814         }
2815       n++;
2816     }
2817     list[n]=(char *) NULL;
2818     keep=list;
2819     for (i=number_images=0; i < n; i++)
2820     {
2821       image=BlobToImage(info->image_info,list[i],length[i],exception);
2822       if (image == (Image *) NULL)
2823         break;
2824       for ( ; image; image=image->next)
2825       {
2826         AddImageToRegistry(sv,image);
2827         rv=newRV(sv);
2828         av_push(av,sv_bless(rv,hv));
2829         SvREFCNT_dec(sv);
2830         number_images++;
2831       }
2832     }
2833     /*
2834       Free resources.
2835     */
2836     for (i=0; i < n; i++)
2837       if (list[i] != (char *) NULL)
2838         for (p=keep; list[i] != *p++; )
2839           if (*p == (char *) NULL)
2840             {
2841               list[i]=(char *) RelinquishMagickMemory(list[i]);
2842               break;
2843             }
2844
2845   PerlException:
2846     if (list)
2847       list=(char **) RelinquishMagickMemory(list);
2848     if (length)
2849       length=(STRLEN *) RelinquishMagickMemory(length);
2850     InheritPerlException(exception,perl_exception);
2851     exception=DestroyExceptionInfo(exception);
2852     sv_setiv(perl_exception,(IV) number_images);
2853     SvPOK_on(perl_exception);
2854     ST(0)=sv_2mortal(perl_exception);
2855     XSRETURN(1);
2856   }
2857 \f
2858 #
2859 ###############################################################################
2860 #                                                                             #
2861 #                                                                             #
2862 #                                                                             #
2863 #   C h a n n e l F x                                                         #
2864 #                                                                             #
2865 #                                                                             #
2866 #                                                                             #
2867 ###############################################################################
2868 #
2869 #
2870 void
2871 ChannelFx(ref,...)
2872   Image::Magick ref=NO_INIT
2873   ALIAS:
2874     ChannelFxImage  = 1
2875     channelfx       = 2
2876     channelfximage  = 3
2877   PPCODE:
2878   {
2879     AV
2880       *av;
2881
2882     char
2883       *attribute,
2884       expression[MagickPathExtent];
2885
2886     ChannelType
2887       channel,
2888       channel_mask;
2889
2890     ExceptionInfo
2891       *exception;
2892
2893     HV
2894       *hv;
2895
2896     Image
2897       *image;
2898
2899     register ssize_t
2900       i;
2901
2902     struct PackageInfo
2903       *info;
2904
2905     SV
2906       *av_reference,
2907       *perl_exception,
2908       *reference,
2909       *rv,
2910       *sv;
2911
2912     PERL_UNUSED_VAR(ref);
2913     PERL_UNUSED_VAR(ix);
2914     exception=AcquireExceptionInfo();
2915     perl_exception=newSVpv("",0);
2916     sv=NULL;
2917     attribute=NULL;
2918     av=NULL;
2919     if (sv_isobject(ST(0)) == 0)
2920       {
2921         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2922           PackageName);
2923         goto PerlException;
2924       }
2925     reference=SvRV(ST(0));
2926     hv=SvSTASH(reference);
2927     av=newAV();
2928     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2929     SvREFCNT_dec(av);
2930     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2931     if (image == (Image *) NULL)
2932       {
2933         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2934           PackageName);
2935         goto PerlException;
2936       }
2937     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2938     /*
2939       Get options.
2940     */
2941     channel=DefaultChannels;
2942     (void) CopyMagickString(expression,"u",MagickPathExtent);
2943     if (items == 2)
2944       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2945     else
2946       for (i=2; i < items; i+=2)
2947       {
2948         attribute=(char *) SvPV(ST(i-1),na);
2949         switch (*attribute)
2950         {
2951           case 'C':
2952           case 'c':
2953           {
2954             if (LocaleCompare(attribute,"channel") == 0)
2955               {
2956                 ssize_t
2957                   option;
2958
2959                 option=ParseChannelOption(SvPV(ST(i),na));
2960                 if (option < 0)
2961                   {
2962                     ThrowPerlException(exception,OptionError,
2963                       "UnrecognizedType",SvPV(ST(i),na));
2964                     return;
2965                   }
2966                 channel=(ChannelType) option;
2967                 break;
2968               }
2969             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2970               attribute);
2971             break;
2972           }
2973           case 'E':
2974           case 'e':
2975           {
2976             if (LocaleCompare(attribute,"expression") == 0)
2977               {
2978                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2979                   MagickPathExtent);
2980                 break;
2981               }
2982             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2983               attribute);
2984             break;
2985           }
2986           default:
2987           {
2988             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2989               attribute);
2990             break;
2991           }
2992         }
2993       }
2994     channel_mask=SetImageChannelMask(image,channel);
2995     image=ChannelFxImage(image,expression,exception);
2996     if (image != (Image *) NULL)
2997       (void) SetImageChannelMask(image,channel_mask);
2998     if (image == (Image *) NULL)
2999       goto PerlException;
3000     for ( ; image; image=image->next)
3001     {
3002       AddImageToRegistry(sv,image);
3003       rv=newRV(sv);
3004       av_push(av,sv_bless(rv,hv));
3005       SvREFCNT_dec(sv);
3006     }
3007     exception=DestroyExceptionInfo(exception);
3008     ST(0)=av_reference;
3009     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3010     XSRETURN(1);
3011
3012   PerlException:
3013     InheritPerlException(exception,perl_exception);
3014     exception=DestroyExceptionInfo(exception);
3015     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3016     SvPOK_on(perl_exception);
3017     ST(0)=sv_2mortal(perl_exception);
3018     XSRETURN(1);
3019   }
3020 \f
3021 #
3022 ###############################################################################
3023 #                                                                             #
3024 #                                                                             #
3025 #                                                                             #
3026 #   C l o n e                                                                 #
3027 #                                                                             #
3028 #                                                                             #
3029 #                                                                             #
3030 ###############################################################################
3031 #
3032 #
3033 void
3034 Clone(ref)
3035   Image::Magick ref=NO_INIT
3036   ALIAS:
3037     CopyImage   = 1
3038     copy        = 2
3039     copyimage   = 3
3040     CloneImage  = 4
3041     clone       = 5
3042     cloneimage  = 6
3043     Clone       = 7
3044   PPCODE:
3045   {
3046     AV
3047       *av;
3048
3049     ExceptionInfo
3050       *exception;
3051
3052     HV
3053       *hv;
3054
3055     Image
3056       *clone,
3057       *image;
3058
3059     struct PackageInfo
3060       *info;
3061
3062     SV
3063       *perl_exception,
3064       *reference,
3065       *rv,
3066       *sv;
3067
3068     PERL_UNUSED_VAR(ref);
3069     PERL_UNUSED_VAR(ix);
3070     exception=AcquireExceptionInfo();
3071     perl_exception=newSVpv("",0);
3072     sv=NULL;
3073     if (sv_isobject(ST(0)) == 0)
3074       {
3075         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3076           PackageName);
3077         goto PerlException;
3078       }
3079     reference=SvRV(ST(0));
3080     hv=SvSTASH(reference);
3081     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3082     if (image == (Image *) NULL)
3083       {
3084         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3085           PackageName);
3086         goto PerlException;
3087       }
3088     /*
3089       Create blessed Perl array for the returned image.
3090     */
3091     av=newAV();
3092     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3093     SvREFCNT_dec(av);
3094     for ( ; image; image=image->next)
3095     {
3096       clone=CloneImage(image,0,0,MagickTrue,exception);
3097       if (clone == (Image *) NULL)
3098         break;
3099       AddImageToRegistry(sv,clone);
3100       rv=newRV(sv);
3101       av_push(av,sv_bless(rv,hv));
3102       SvREFCNT_dec(sv);
3103     }
3104     exception=DestroyExceptionInfo(exception);
3105     SvREFCNT_dec(perl_exception);
3106     XSRETURN(1);
3107
3108   PerlException:
3109     InheritPerlException(exception,perl_exception);
3110     exception=DestroyExceptionInfo(exception);
3111     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3112     SvPOK_on(perl_exception);
3113     ST(0)=sv_2mortal(perl_exception);
3114     XSRETURN(1);
3115   }
3116 \f
3117 #
3118 ###############################################################################
3119 #                                                                             #
3120 #                                                                             #
3121 #                                                                             #
3122 #   C L O N E                                                                 #
3123 #                                                                             #
3124 #                                                                             #
3125 #                                                                             #
3126 ###############################################################################
3127 #
3128 #
3129 void
3130 CLONE(ref,...)
3131   SV *ref;
3132   CODE:
3133   {
3134     PERL_UNUSED_VAR(ref);
3135     if (magick_registry != (SplayTreeInfo *) NULL)
3136       {
3137         register Image
3138           *p;
3139
3140         ResetSplayTreeIterator(magick_registry);
3141         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3142         while (p != (Image *) NULL)
3143         {
3144           ReferenceImage(p);
3145           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3146         }
3147       }
3148   }
3149 \f
3150 #
3151 ###############################################################################
3152 #                                                                             #
3153 #                                                                             #
3154 #                                                                             #
3155 #   C o a l e s c e                                                           #
3156 #                                                                             #
3157 #                                                                             #
3158 #                                                                             #
3159 ###############################################################################
3160 #
3161 #
3162 void
3163 Coalesce(ref)
3164   Image::Magick ref=NO_INIT
3165   ALIAS:
3166     CoalesceImage   = 1
3167     coalesce        = 2
3168     coalesceimage   = 3
3169   PPCODE:
3170   {
3171     AV
3172       *av;
3173
3174     ExceptionInfo
3175       *exception;
3176
3177     HV
3178       *hv;
3179
3180     Image
3181       *image;
3182
3183     struct PackageInfo
3184       *info;
3185
3186     SV
3187       *av_reference,
3188       *perl_exception,
3189       *reference,
3190       *rv,
3191       *sv;
3192
3193     PERL_UNUSED_VAR(ref);
3194     PERL_UNUSED_VAR(ix);
3195     exception=AcquireExceptionInfo();
3196     perl_exception=newSVpv("",0);
3197     sv=NULL;
3198     if (sv_isobject(ST(0)) == 0)
3199       {
3200         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3201           PackageName);
3202         goto PerlException;
3203       }
3204     reference=SvRV(ST(0));
3205     hv=SvSTASH(reference);
3206     av=newAV();
3207     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3208     SvREFCNT_dec(av);
3209     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3210     if (image == (Image *) NULL)
3211       {
3212         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3213           PackageName);
3214         goto PerlException;
3215       }
3216     image=CoalesceImages(image,exception);
3217     if (image == (Image *) NULL)
3218       goto PerlException;
3219     for ( ; image; image=image->next)
3220     {
3221       AddImageToRegistry(sv,image);
3222       rv=newRV(sv);
3223       av_push(av,sv_bless(rv,hv));
3224       SvREFCNT_dec(sv);
3225     }
3226     exception=DestroyExceptionInfo(exception);
3227     ST(0)=av_reference;
3228     SvREFCNT_dec(perl_exception);
3229     XSRETURN(1);
3230
3231   PerlException:
3232     InheritPerlException(exception,perl_exception);
3233     exception=DestroyExceptionInfo(exception);
3234     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3235     SvPOK_on(perl_exception);
3236     ST(0)=sv_2mortal(perl_exception);
3237     XSRETURN(1);
3238   }
3239 \f
3240 #
3241 ###############################################################################
3242 #                                                                             #
3243 #                                                                             #
3244 #                                                                             #
3245 #   C o m p a r e                                                             #
3246 #                                                                             #
3247 #                                                                             #
3248 #                                                                             #
3249 ###############################################################################
3250 #
3251 #
3252 void
3253 Compare(ref,...)
3254   Image::Magick ref=NO_INIT
3255   ALIAS:
3256     CompareImages = 1
3257     compare      = 2
3258     compareimage = 3
3259   PPCODE:
3260   {
3261     AV
3262       *av;
3263
3264     char
3265       *attribute;
3266
3267     double
3268       distortion;
3269
3270     ExceptionInfo
3271       *exception;
3272
3273     HV
3274       *hv;
3275
3276     Image
3277       *difference_image,
3278       *image,
3279       *reconstruct_image;
3280
3281     MetricType
3282       metric;
3283
3284     register ssize_t
3285       i;
3286
3287     ssize_t
3288       option;
3289
3290     struct PackageInfo
3291       *info;
3292
3293     SV
3294       *av_reference,
3295       *perl_exception,
3296       *reference,
3297       *rv,
3298       *sv;
3299
3300     PERL_UNUSED_VAR(ref);
3301     PERL_UNUSED_VAR(ix);
3302     exception=AcquireExceptionInfo();
3303     perl_exception=newSVpv("",0);
3304     sv=NULL;
3305     av=NULL;
3306     attribute=NULL;
3307     if (sv_isobject(ST(0)) == 0)
3308       {
3309         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3310           PackageName);
3311         goto PerlException;
3312       }
3313     reference=SvRV(ST(0));
3314     hv=SvSTASH(reference);
3315     av=newAV();
3316     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3317     SvREFCNT_dec(av);
3318     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3319     if (image == (Image *) NULL)
3320       {
3321         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3322           PackageName);
3323         goto PerlException;
3324       }
3325     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3326     /*
3327       Get attribute.
3328     */
3329     reconstruct_image=image;
3330     metric=RootMeanSquaredErrorMetric;
3331     for (i=2; i < items; i+=2)
3332     {
3333       attribute=(char *) SvPV(ST(i-1),na);
3334       switch (*attribute)
3335       {
3336         case 'C':
3337         case 'c':
3338         {
3339           if (LocaleCompare(attribute,"channel") == 0)
3340             {
3341               ssize_t
3342                 option;
3343
3344               option=ParseChannelOption(SvPV(ST(i),na));
3345               if (option < 0)
3346                 {
3347                   ThrowPerlException(exception,OptionError,
3348                     "UnrecognizedType",SvPV(ST(i),na));
3349                   return;
3350                 }
3351               (void) SetPixelChannelMask(image,(ChannelType) option);
3352               break;
3353             }
3354           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3355             attribute);
3356           break;
3357         }
3358         case 'F':
3359         case 'f':
3360         {
3361           if (LocaleCompare(attribute,"fuzz") == 0)
3362             {
3363               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3364               break;
3365             }
3366           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3367             attribute);
3368           break;
3369         }
3370         case 'I':
3371         case 'i':
3372         {
3373           if (LocaleCompare(attribute,"image") == 0)
3374             {
3375               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3376                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3377               break;
3378             }
3379           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3380             attribute);
3381           break;
3382         }
3383         case 'M':
3384         case 'm':
3385         {
3386           if (LocaleCompare(attribute,"metric") == 0)
3387             {
3388               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3389                 SvPV(ST(i),na));
3390               if (option < 0)
3391                 {
3392                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3393                     SvPV(ST(i),na));
3394                   break;
3395                 }
3396               metric=(MetricType) option;
3397               break;
3398             }
3399           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3400             attribute);
3401           break;
3402         }
3403         default:
3404         {
3405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3406             attribute);
3407           break;
3408         }
3409       }
3410     }
3411     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3412       exception);
3413     if (difference_image != (Image *) NULL)
3414       {
3415         difference_image->error.mean_error_per_pixel=distortion;
3416         AddImageToRegistry(sv,difference_image);
3417         rv=newRV(sv);
3418         av_push(av,sv_bless(rv,hv));
3419         SvREFCNT_dec(sv);
3420       }
3421     exception=DestroyExceptionInfo(exception);
3422     ST(0)=av_reference;
3423     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3424     XSRETURN(1);
3425
3426   PerlException:
3427     InheritPerlException(exception,perl_exception);
3428     exception=DestroyExceptionInfo(exception);
3429     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3430     SvPOK_on(perl_exception);
3431     ST(0)=sv_2mortal(perl_exception);
3432     XSRETURN(1);
3433   }
3434 \f
3435 #
3436 ###############################################################################
3437 #                                                                             #
3438 #                                                                             #
3439 #                                                                             #
3440 #   C o m p l e x I m a g e s                                                 #
3441 #                                                                             #
3442 #                                                                             #
3443 #                                                                             #
3444 ###############################################################################
3445 #
3446 #
3447 void
3448 ComplexImages(ref)
3449   Image::Magick ref=NO_INIT
3450   ALIAS:
3451     ComplexImages   = 1
3452     compleximages   = 2
3453   PPCODE:
3454   {
3455     AV
3456       *av;
3457
3458     char
3459       *attribute,
3460       *p;
3461
3462     ComplexOperator
3463       op;
3464
3465     ExceptionInfo
3466       *exception;
3467
3468     HV
3469       *hv;
3470
3471     Image
3472       *image;
3473
3474     register ssize_t
3475       i;
3476
3477     struct PackageInfo
3478       *info;
3479
3480     SV
3481       *perl_exception,
3482       *reference,
3483       *rv,
3484       *sv;
3485
3486     PERL_UNUSED_VAR(ref);
3487     PERL_UNUSED_VAR(ix);
3488     exception=AcquireExceptionInfo();
3489     perl_exception=newSVpv("",0);
3490     sv=NULL;
3491     if (sv_isobject(ST(0)) == 0)
3492       {
3493         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3494           PackageName);
3495         goto PerlException;
3496       }
3497     reference=SvRV(ST(0));
3498     hv=SvSTASH(reference);
3499     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3500     if (image == (Image *) NULL)
3501       {
3502         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3503           PackageName);
3504         goto PerlException;
3505       }
3506     op=UndefinedComplexOperator;
3507     if (items == 2)
3508       {
3509         ssize_t
3510           in;
3511
3512         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3513           SvPV(ST(1),na));
3514         if (in < 0)
3515           {
3516             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3517               SvPV(ST(1),na));
3518             return;
3519           }
3520         op=(ComplexOperator) in;
3521       }
3522     else
3523       for (i=2; i < items; i+=2)
3524       {
3525         attribute=(char *) SvPV(ST(i-1),na);
3526         switch (*attribute)
3527         {
3528           case 'O':
3529           case 'o':
3530           {
3531             if (LocaleCompare(attribute,"operator") == 0)
3532               {
3533                 ssize_t
3534                   in;
3535
3536                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3537                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3538                 if (in < 0)
3539                   {
3540                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3541                       SvPV(ST(i),na));
3542                     return;
3543                   }
3544                 op=(ComplexOperator) in;
3545                 break;
3546               }
3547             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3548               attribute);
3549             break;
3550           }
3551           default:
3552           {
3553             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3554               attribute);
3555             break;
3556           }
3557         }
3558       }
3559     image=ComplexImages(image,op,exception);
3560     if (image == (Image *) NULL)
3561       goto PerlException;
3562     /*
3563       Create blessed Perl array for the returned image.
3564     */
3565     av=newAV();
3566     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3567     SvREFCNT_dec(av);
3568     AddImageToRegistry(sv,image);
3569     rv=newRV(sv);
3570     av_push(av,sv_bless(rv,hv));
3571     SvREFCNT_dec(sv);
3572     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3573     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3574       "complex-%.*s",(int) (MagickPathExtent-9),
3575       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3576     (void) CopyMagickString(image->filename,info->image_info->filename,
3577       MagickPathExtent);
3578     SetImageInfo(info->image_info,0,exception);
3579     exception=DestroyExceptionInfo(exception);
3580     SvREFCNT_dec(perl_exception);
3581     XSRETURN(1);
3582
3583   PerlException:
3584     InheritPerlException(exception,perl_exception);
3585     exception=DestroyExceptionInfo(exception);
3586     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3587     SvPOK_on(perl_exception);
3588     ST(0)=sv_2mortal(perl_exception);
3589     XSRETURN(1);
3590   }
3591 \f
3592 #
3593 ###############################################################################
3594 #                                                                             #
3595 #                                                                             #
3596 #                                                                             #
3597 #   C o m p a r e L a y e r s                                                 #
3598 #                                                                             #
3599 #                                                                             #
3600 #                                                                             #
3601 ###############################################################################
3602 #
3603 #
3604 void
3605 CompareLayers(ref)
3606   Image::Magick ref=NO_INIT
3607   ALIAS:
3608     CompareImagesLayers   = 1
3609     comparelayers        = 2
3610     compareimagelayers   = 3
3611   PPCODE:
3612   {
3613     AV
3614       *av;
3615
3616     char
3617       *attribute;
3618
3619     ExceptionInfo
3620       *exception;
3621
3622     HV
3623       *hv;
3624
3625     Image
3626       *image;
3627
3628     LayerMethod
3629       method;
3630
3631     register ssize_t
3632       i;
3633
3634     ssize_t
3635       option;
3636
3637     struct PackageInfo
3638       *info;
3639
3640     SV
3641       *av_reference,
3642       *perl_exception,
3643       *reference,
3644       *rv,
3645       *sv;
3646
3647     PERL_UNUSED_VAR(ref);
3648     PERL_UNUSED_VAR(ix);
3649     exception=AcquireExceptionInfo();
3650     perl_exception=newSVpv("",0);
3651     sv=NULL;
3652     if (sv_isobject(ST(0)) == 0)
3653       {
3654         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3655           PackageName);
3656         goto PerlException;
3657       }
3658     reference=SvRV(ST(0));
3659     hv=SvSTASH(reference);
3660     av=newAV();
3661     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3662     SvREFCNT_dec(av);
3663     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3664     if (image == (Image *) NULL)
3665       {
3666         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3667           PackageName);
3668         goto PerlException;
3669       }
3670     method=CompareAnyLayer;
3671     for (i=2; i < items; i+=2)
3672     {
3673       attribute=(char *) SvPV(ST(i-1),na);
3674       switch (*attribute)
3675       {
3676         case 'M':
3677         case 'm':
3678         {
3679           if (LocaleCompare(attribute,"method") == 0)
3680             {
3681               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3682                 SvPV(ST(i),na));
3683               if (option < 0)
3684                 {
3685                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3686                     SvPV(ST(i),na));
3687                   break;
3688                 }
3689                method=(LayerMethod) option;
3690               break;
3691             }
3692           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3693             attribute);
3694           break;
3695         }
3696         default:
3697         {
3698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3699             attribute);
3700           break;
3701         }
3702       }
3703     }
3704     image=CompareImagesLayers(image,method,exception);
3705     if (image == (Image *) NULL)
3706       goto PerlException;
3707     for ( ; image; image=image->next)
3708     {
3709       AddImageToRegistry(sv,image);
3710       rv=newRV(sv);
3711       av_push(av,sv_bless(rv,hv));
3712       SvREFCNT_dec(sv);
3713     }
3714     exception=DestroyExceptionInfo(exception);
3715     ST(0)=av_reference;
3716     SvREFCNT_dec(perl_exception);
3717     XSRETURN(1);
3718
3719   PerlException:
3720     InheritPerlException(exception,perl_exception);
3721     exception=DestroyExceptionInfo(exception);
3722     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3723     SvPOK_on(perl_exception);
3724     ST(0)=sv_2mortal(perl_exception);
3725     XSRETURN(1);
3726   }
3727 \f
3728 #
3729 ###############################################################################
3730 #                                                                             #
3731 #                                                                             #
3732 #                                                                             #
3733 #   D e s t r o y                                                             #
3734 #                                                                             #
3735 #                                                                             #
3736 #                                                                             #
3737 ###############################################################################
3738 #
3739 #
3740 void
3741 DESTROY(ref)
3742   Image::Magick ref=NO_INIT
3743   PPCODE:
3744   {
3745     SV
3746       *reference;
3747
3748     PERL_UNUSED_VAR(ref);
3749     if (sv_isobject(ST(0)) == 0)
3750       croak("ReferenceIsNotMyType");
3751     reference=SvRV(ST(0));
3752     switch (SvTYPE(reference))
3753     {
3754       case SVt_PVAV:
3755       {
3756         char
3757           message[MagickPathExtent];
3758
3759         const SV
3760           *key;
3761
3762         HV
3763           *hv;
3764
3765         GV
3766           **gvp;
3767
3768         struct PackageInfo
3769           *info;
3770
3771         SV
3772           *sv;
3773
3774         /*
3775           Array (AV *) reference
3776         */
3777         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3778           XS_VERSION,reference);
3779         hv=gv_stashpv(PackageName, FALSE);
3780         if (!hv)
3781           break;
3782         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3783         if (!gvp)
3784           break;
3785         sv=GvSV(*gvp);
3786         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3787           {
3788             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3789             DestroyPackageInfo(info);
3790           }
3791         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3792         (void) key;
3793         break;
3794       }
3795       case SVt_PVMG:
3796       {
3797         Image
3798           *image;
3799
3800         /*
3801           Blessed scalar = (Image *) SvIV(reference)
3802         */
3803         image=INT2PTR(Image *,SvIV(reference));
3804         if (image != (Image *) NULL)
3805           DeleteImageFromRegistry(reference,image);
3806         break;
3807       }
3808       default:
3809         break;
3810     }
3811   }
3812 \f
3813 #
3814 ###############################################################################
3815 #                                                                             #
3816 #                                                                             #
3817 #                                                                             #
3818 #   D i s p l a y                                                             #
3819 #                                                                             #
3820 #                                                                             #
3821 #                                                                             #
3822 ###############################################################################
3823 #
3824 #
3825 void
3826 Display(ref,...)
3827   Image::Magick ref=NO_INIT
3828   ALIAS:
3829     DisplayImage  = 1
3830     display       = 2
3831     displayimage  = 3
3832   PPCODE:
3833   {
3834     ExceptionInfo
3835       *exception;
3836
3837     Image
3838       *image;
3839
3840     register ssize_t
3841       i;
3842
3843     struct PackageInfo
3844       *info,
3845       *package_info;
3846
3847     SV
3848       *perl_exception,
3849       *reference;
3850
3851     PERL_UNUSED_VAR(ref);
3852     PERL_UNUSED_VAR(ix);
3853     exception=AcquireExceptionInfo();
3854     perl_exception=newSVpv("",0);
3855     package_info=(struct PackageInfo *) NULL;
3856     if (sv_isobject(ST(0)) == 0)
3857       {
3858         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3859           PackageName);
3860         goto PerlException;
3861       }
3862     reference=SvRV(ST(0));
3863     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3864     if (image == (Image *) NULL)
3865       {
3866         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3867           PackageName);
3868         goto PerlException;
3869       }
3870     package_info=ClonePackageInfo(info,exception);
3871     if (items == 2)
3872       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3873     else
3874       if (items > 2)
3875         for (i=2; i < items; i+=2)
3876           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3877             exception);
3878     (void) DisplayImages(package_info->image_info,image,exception);
3879     (void) CatchImageException(image);
3880
3881   PerlException:
3882     if (package_info != (struct PackageInfo *) NULL)
3883       DestroyPackageInfo(package_info);
3884     InheritPerlException(exception,perl_exception);
3885     exception=DestroyExceptionInfo(exception);
3886     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3887     SvPOK_on(perl_exception);
3888     ST(0)=sv_2mortal(perl_exception);
3889     XSRETURN(1);
3890   }
3891 \f
3892 #
3893 ###############################################################################
3894 #                                                                             #
3895 #                                                                             #
3896 #                                                                             #
3897 #   E v a l u a t e I m a g e s                                               #
3898 #                                                                             #
3899 #                                                                             #
3900 #                                                                             #
3901 ###############################################################################
3902 #
3903 #
3904 void
3905 EvaluateImages(ref)
3906   Image::Magick ref=NO_INIT
3907   ALIAS:
3908     EvaluateImages   = 1
3909     evaluateimages   = 2
3910   PPCODE:
3911   {
3912     AV
3913       *av;
3914
3915     char
3916       *attribute,
3917       *p;
3918
3919     ExceptionInfo
3920       *exception;
3921
3922     HV
3923       *hv;
3924
3925     Image
3926       *image;
3927
3928     MagickEvaluateOperator
3929       op;
3930
3931     register ssize_t
3932       i;
3933
3934     struct PackageInfo
3935       *info;
3936
3937     SV
3938       *perl_exception,
3939       *reference,
3940       *rv,
3941       *sv;
3942
3943     PERL_UNUSED_VAR(ref);
3944     PERL_UNUSED_VAR(ix);
3945     exception=AcquireExceptionInfo();
3946     perl_exception=newSVpv("",0);
3947     sv=NULL;
3948     if (sv_isobject(ST(0)) == 0)
3949       {
3950         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3951           PackageName);
3952         goto PerlException;
3953       }
3954     reference=SvRV(ST(0));
3955     hv=SvSTASH(reference);
3956     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3957     if (image == (Image *) NULL)
3958       {
3959         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3960           PackageName);
3961         goto PerlException;
3962       }
3963     op=MeanEvaluateOperator;
3964     if (items == 2)
3965       {
3966         ssize_t
3967           in;
3968
3969         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3970           SvPV(ST(1),na));
3971         if (in < 0)
3972           {
3973             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3974               SvPV(ST(1),na));
3975             return;
3976           }
3977         op=(MagickEvaluateOperator) in;
3978       }
3979     else
3980       for (i=2; i < items; i+=2)
3981       {
3982         attribute=(char *) SvPV(ST(i-1),na);
3983         switch (*attribute)
3984         {
3985           case 'O':
3986           case 'o':
3987           {
3988             if (LocaleCompare(attribute,"operator") == 0)
3989               {
3990                 ssize_t
3991                   in;
3992
3993                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3994                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3995                 if (in < 0)
3996                   {
3997                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3998                       SvPV(ST(i),na));
3999                     return;
4000                   }
4001                 op=(MagickEvaluateOperator) in;
4002                 break;
4003               }
4004             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4005               attribute);
4006             break;
4007           }
4008           default:
4009           {
4010             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4011               attribute);
4012             break;
4013           }
4014         }
4015       }
4016     image=EvaluateImages(image,op,exception);
4017     if (image == (Image *) NULL)
4018       goto PerlException;
4019     /*
4020       Create blessed Perl array for the returned image.
4021     */
4022     av=newAV();
4023     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4024     SvREFCNT_dec(av);
4025     AddImageToRegistry(sv,image);
4026     rv=newRV(sv);
4027     av_push(av,sv_bless(rv,hv));
4028     SvREFCNT_dec(sv);
4029     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4030     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4031       "evaluate-%.*s",(int) (MagickPathExtent-9),
4032       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4033     (void) CopyMagickString(image->filename,info->image_info->filename,
4034       MagickPathExtent);
4035     SetImageInfo(info->image_info,0,exception);
4036     exception=DestroyExceptionInfo(exception);
4037     SvREFCNT_dec(perl_exception);
4038     XSRETURN(1);
4039
4040   PerlException:
4041     InheritPerlException(exception,perl_exception);
4042     exception=DestroyExceptionInfo(exception);
4043     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4044     SvPOK_on(perl_exception);
4045     ST(0)=sv_2mortal(perl_exception);
4046     XSRETURN(1);
4047   }
4048 \f
4049 #
4050 ###############################################################################
4051 #                                                                             #
4052 #                                                                             #
4053 #                                                                             #
4054 #   F e a t u r e s                                                           #
4055 #                                                                             #
4056 #                                                                             #
4057 #                                                                             #
4058 ###############################################################################
4059 #
4060 #
4061 void
4062 Features(ref,...)
4063   Image::Magick ref=NO_INIT
4064   ALIAS:
4065     FeaturesImage = 1
4066     features      = 2
4067     featuresimage = 3
4068   PPCODE:
4069   {
4070 #define ChannelFeatures(channel,direction) \
4071 { \
4072   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4073     channel_features[channel].angular_second_moment[direction]); \
4074   PUSHs(sv_2mortal(newSVpv(message,0))); \
4075   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4076     channel_features[channel].contrast[direction]); \
4077   PUSHs(sv_2mortal(newSVpv(message,0))); \
4078   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4079     channel_features[channel].contrast[direction]); \
4080   PUSHs(sv_2mortal(newSVpv(message,0))); \
4081   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4082     channel_features[channel].variance_sum_of_squares[direction]); \
4083   PUSHs(sv_2mortal(newSVpv(message,0))); \
4084   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4085     channel_features[channel].inverse_difference_moment[direction]); \
4086   PUSHs(sv_2mortal(newSVpv(message,0))); \
4087   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4088     channel_features[channel].sum_average[direction]); \
4089   PUSHs(sv_2mortal(newSVpv(message,0))); \
4090   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4091     channel_features[channel].sum_variance[direction]); \
4092   PUSHs(sv_2mortal(newSVpv(message,0))); \
4093   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4094     channel_features[channel].sum_entropy[direction]); \
4095   PUSHs(sv_2mortal(newSVpv(message,0))); \
4096   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4097     channel_features[channel].entropy[direction]); \
4098   PUSHs(sv_2mortal(newSVpv(message,0))); \
4099   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4100     channel_features[channel].difference_variance[direction]); \
4101   PUSHs(sv_2mortal(newSVpv(message,0))); \
4102   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4103     channel_features[channel].difference_entropy[direction]); \
4104   PUSHs(sv_2mortal(newSVpv(message,0))); \
4105   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4106     channel_features[channel].measure_of_correlation_1[direction]); \
4107   PUSHs(sv_2mortal(newSVpv(message,0))); \
4108   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4109     channel_features[channel].measure_of_correlation_2[direction]); \
4110   PUSHs(sv_2mortal(newSVpv(message,0))); \
4111   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4112     channel_features[channel].maximum_correlation_coefficient[direction]); \
4113   PUSHs(sv_2mortal(newSVpv(message,0))); \
4114 }
4115
4116     AV
4117       *av;
4118
4119     char
4120       *attribute,
4121       message[MagickPathExtent];
4122
4123     ChannelFeatures
4124       *channel_features;
4125
4126     double
4127       distance;
4128
4129     ExceptionInfo
4130       *exception;
4131
4132     Image
4133       *image;
4134
4135     register ssize_t
4136       i;
4137
4138     ssize_t
4139       count;
4140
4141     struct PackageInfo
4142       *info;
4143
4144     SV
4145       *perl_exception,
4146       *reference;
4147
4148     PERL_UNUSED_VAR(ref);
4149     PERL_UNUSED_VAR(ix);
4150     exception=AcquireExceptionInfo();
4151     perl_exception=newSVpv("",0);
4152     av=NULL;
4153     if (sv_isobject(ST(0)) == 0)
4154       {
4155         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4156           PackageName);
4157         goto PerlException;
4158       }
4159     reference=SvRV(ST(0));
4160     av=newAV();
4161     SvREFCNT_dec(av);
4162     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4163     if (image == (Image *) NULL)
4164       {
4165         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4166           PackageName);
4167         goto PerlException;
4168       }
4169     distance=1.0;
4170     for (i=2; i < items; i+=2)
4171     {
4172       attribute=(char *) SvPV(ST(i-1),na);
4173       switch (*attribute)
4174       {
4175         case 'D':
4176         case 'd':
4177         {
4178           if (LocaleCompare(attribute,"distance") == 0)
4179             {
4180               distance=StringToLong((char *) SvPV(ST(1),na));
4181               break;
4182             }
4183           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4184             attribute);
4185           break;
4186         }
4187         default:
4188         {
4189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4190             attribute);
4191           break;
4192         }
4193       }
4194     }
4195     count=0;
4196     for ( ; image; image=image->next)
4197     {
4198       channel_features=GetImageFeatures(image,distance,exception);
4199       if (channel_features == (ChannelFeatures *) NULL)
4200         continue;
4201       count++;
4202       EXTEND(sp,280*count);
4203       for (i=0; i < 4; i++)
4204       {
4205         ChannelFeatures(RedChannel,i);
4206         ChannelFeatures(GreenChannel,i);
4207         ChannelFeatures(BlueChannel,i);
4208         if (image->colorspace == CMYKColorspace)
4209           ChannelFeatures(BlackChannel,i);
4210         if (image->alpha_trait != UndefinedPixelTrait)
4211           ChannelFeatures(AlphaChannel,i);
4212       }
4213       channel_features=(ChannelFeatures *)
4214         RelinquishMagickMemory(channel_features);
4215     }
4216
4217   PerlException:
4218     InheritPerlException(exception,perl_exception);
4219     exception=DestroyExceptionInfo(exception);
4220     SvREFCNT_dec(perl_exception);
4221   }
4222 \f
4223 #
4224 ###############################################################################
4225 #                                                                             #
4226 #                                                                             #
4227 #                                                                             #
4228 #   F l a t t e n                                                             #
4229 #                                                                             #
4230 #                                                                             #
4231 #                                                                             #
4232 ###############################################################################
4233 #
4234 #
4235 void
4236 Flatten(ref)
4237   Image::Magick ref=NO_INIT
4238   ALIAS:
4239     FlattenImage   = 1
4240     flatten        = 2
4241     flattenimage   = 3
4242   PPCODE:
4243   {
4244     AV
4245       *av;
4246
4247     char
4248       *attribute,
4249       *p;
4250
4251     ExceptionInfo
4252       *exception;
4253
4254     HV
4255       *hv;
4256
4257     Image
4258       *image;
4259
4260     PixelInfo
4261       background_color;
4262
4263     register ssize_t
4264       i;
4265
4266     struct PackageInfo
4267       *info;
4268
4269     SV
4270       *perl_exception,
4271       *reference,
4272       *rv,
4273       *sv;
4274
4275     PERL_UNUSED_VAR(ref);
4276     PERL_UNUSED_VAR(ix);
4277     exception=AcquireExceptionInfo();
4278     perl_exception=newSVpv("",0);
4279     sv=NULL;
4280     if (sv_isobject(ST(0)) == 0)
4281       {
4282         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4283           PackageName);
4284         goto PerlException;
4285       }
4286     reference=SvRV(ST(0));
4287     hv=SvSTASH(reference);
4288     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4289     if (image == (Image *) NULL)
4290       {
4291         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4292           PackageName);
4293         goto PerlException;
4294       }
4295     background_color=image->background_color;
4296     if (items == 2)
4297       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4298         &background_color,exception);
4299     else
4300       for (i=2; i < items; i+=2)
4301       {
4302         attribute=(char *) SvPV(ST(i-1),na);
4303         switch (*attribute)
4304         {
4305           case 'B':
4306           case 'b':
4307           {
4308             if (LocaleCompare(attribute,"background") == 0)
4309               {
4310                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4311                   AllCompliance,&background_color,exception);
4312                 break;
4313               }
4314             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4315               attribute);
4316             break;
4317           }
4318           default:
4319           {
4320             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4321               attribute);
4322             break;
4323           }
4324         }
4325       }
4326     image->background_color=background_color;
4327     image=MergeImageLayers(image,FlattenLayer,exception);
4328     if (image == (Image *) NULL)
4329       goto PerlException;
4330     /*
4331       Create blessed Perl array for the returned image.
4332     */
4333     av=newAV();
4334     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4335     SvREFCNT_dec(av);
4336     AddImageToRegistry(sv,image);
4337     rv=newRV(sv);
4338     av_push(av,sv_bless(rv,hv));
4339     SvREFCNT_dec(sv);
4340     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4341     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4342       "flatten-%.*s",(int) (MagickPathExtent-9),
4343       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4344     (void) CopyMagickString(image->filename,info->image_info->filename,
4345       MagickPathExtent);
4346     SetImageInfo(info->image_info,0,exception);
4347     exception=DestroyExceptionInfo(exception);
4348     SvREFCNT_dec(perl_exception);
4349     XSRETURN(1);
4350
4351   PerlException:
4352     InheritPerlException(exception,perl_exception);
4353     exception=DestroyExceptionInfo(exception);
4354     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4355     SvPOK_on(perl_exception);  /* return messages in string context */
4356     ST(0)=sv_2mortal(perl_exception);
4357     XSRETURN(1);
4358   }
4359 \f
4360 #
4361 ###############################################################################
4362 #                                                                             #
4363 #                                                                             #
4364 #                                                                             #
4365 #   F x                                                                       #
4366 #                                                                             #
4367 #                                                                             #
4368 #                                                                             #
4369 ###############################################################################
4370 #
4371 #
4372 void
4373 Fx(ref,...)
4374   Image::Magick ref=NO_INIT
4375   ALIAS:
4376     FxImage  = 1
4377     fx       = 2
4378     fximage  = 3
4379   PPCODE:
4380   {
4381     AV
4382       *av;
4383
4384     char
4385       *attribute,
4386       expression[MagickPathExtent];
4387
4388     ChannelType
4389       channel,
4390       channel_mask;
4391
4392     ExceptionInfo
4393       *exception;
4394
4395     HV
4396       *hv;
4397
4398     Image
4399       *image;
4400
4401     register ssize_t
4402       i;
4403
4404     struct PackageInfo
4405       *info;
4406
4407     SV
4408       *av_reference,
4409       *perl_exception,
4410       *reference,
4411       *rv,
4412       *sv;
4413
4414     PERL_UNUSED_VAR(ref);
4415     PERL_UNUSED_VAR(ix);
4416     exception=AcquireExceptionInfo();
4417     perl_exception=newSVpv("",0);
4418     sv=NULL;
4419     attribute=NULL;
4420     av=NULL;
4421     if (sv_isobject(ST(0)) == 0)
4422       {
4423         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4424           PackageName);
4425         goto PerlException;
4426       }
4427     reference=SvRV(ST(0));
4428     hv=SvSTASH(reference);
4429     av=newAV();
4430     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4431     SvREFCNT_dec(av);
4432     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4433     if (image == (Image *) NULL)
4434       {
4435         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4436           PackageName);
4437         goto PerlException;
4438       }
4439     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4440     /*
4441       Get options.
4442     */
4443     channel=DefaultChannels;
4444     (void) CopyMagickString(expression,"u",MagickPathExtent);
4445     if (items == 2)
4446       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4447     else
4448       for (i=2; i < items; i+=2)
4449       {
4450         attribute=(char *) SvPV(ST(i-1),na);
4451         switch (*attribute)
4452         {
4453           case 'C':
4454           case 'c':
4455           {
4456             if (LocaleCompare(attribute,"channel") == 0)
4457               {
4458                 ssize_t
4459                   option;
4460
4461                 option=ParseChannelOption(SvPV(ST(i),na));
4462                 if (option < 0)
4463                   {
4464                     ThrowPerlException(exception,OptionError,
4465                       "UnrecognizedType",SvPV(ST(i),na));
4466                     return;
4467                   }
4468                 channel=(ChannelType) option;
4469                 break;
4470               }
4471             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4472               attribute);
4473             break;
4474           }
4475           case 'E':
4476           case 'e':
4477           {
4478             if (LocaleCompare(attribute,"expression") == 0)
4479               {
4480                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4481                   MagickPathExtent);
4482                 break;
4483               }
4484             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4485               attribute);
4486             break;
4487           }
4488           default:
4489           {
4490             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4491               attribute);
4492             break;
4493           }
4494         }
4495       }
4496     channel_mask=SetImageChannelMask(image,channel);
4497     image=FxImage(image,expression,exception);
4498     if (image != (Image *) NULL)
4499       (void) SetImageChannelMask(image,channel_mask);
4500     if (image == (Image *) NULL)
4501       goto PerlException;
4502     for ( ; image; image=image->next)
4503     {
4504       AddImageToRegistry(sv,image);
4505       rv=newRV(sv);
4506       av_push(av,sv_bless(rv,hv));
4507       SvREFCNT_dec(sv);
4508     }
4509     exception=DestroyExceptionInfo(exception);
4510     ST(0)=av_reference;
4511     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4512     XSRETURN(1);
4513
4514   PerlException:
4515     InheritPerlException(exception,perl_exception);
4516     exception=DestroyExceptionInfo(exception);
4517     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4518     SvPOK_on(perl_exception);
4519     ST(0)=sv_2mortal(perl_exception);
4520     XSRETURN(1);
4521   }
4522 \f
4523 #
4524 ###############################################################################
4525 #                                                                             #
4526 #                                                                             #
4527 #                                                                             #
4528 #   G e t                                                                     #
4529 #                                                                             #
4530 #                                                                             #
4531 #                                                                             #
4532 ###############################################################################
4533 #
4534 #
4535 void
4536 Get(ref,...)
4537   Image::Magick ref=NO_INIT
4538   ALIAS:
4539     GetAttributes = 1
4540     GetAttribute  = 2
4541     get           = 3
4542     getattributes = 4
4543     getattribute  = 5
4544   PPCODE:
4545   {
4546     char
4547       *attribute,
4548       color[MagickPathExtent];
4549
4550     const char
4551       *value;
4552
4553     ExceptionInfo
4554       *exception;
4555
4556     Image
4557       *image;
4558
4559     long
4560       j;
4561
4562     register ssize_t
4563       i;
4564
4565     struct PackageInfo
4566       *info;
4567
4568     SV
4569       *perl_exception,
4570       *reference,
4571       *s;
4572
4573     PERL_UNUSED_VAR(ref);
4574     PERL_UNUSED_VAR(ix);
4575     exception=AcquireExceptionInfo();
4576     perl_exception=newSVpv("",0);
4577     if (sv_isobject(ST(0)) == 0)
4578       {
4579         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4580           PackageName);
4581         XSRETURN_EMPTY;
4582       }
4583     reference=SvRV(ST(0));
4584     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4585     if (image == (Image *) NULL && !info)
4586       XSRETURN_EMPTY;
4587     EXTEND(sp,items);
4588     for (i=1; i < items; i++)
4589     {
4590       attribute=(char *) SvPV(ST(i),na);
4591       s=NULL;
4592       switch (*attribute)
4593       {
4594         case 'A':
4595         case 'a':
4596         {
4597           if (LocaleCompare(attribute,"adjoin") == 0)
4598             {
4599               if (info)
4600                 s=newSViv((ssize_t) info->image_info->adjoin);
4601               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4602               continue;
4603             }
4604           if (LocaleCompare(attribute,"antialias") == 0)
4605             {
4606               if (info)
4607                 s=newSViv((ssize_t) info->image_info->antialias);
4608               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4609               continue;
4610             }
4611           if (LocaleCompare(attribute,"area") == 0)
4612             {
4613               s=newSViv(GetMagickResource(AreaResource));
4614               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4615               continue;
4616             }
4617           if (LocaleCompare(attribute,"attenuate") == 0)
4618             {
4619               const char
4620                 *value;
4621
4622               value=GetImageProperty(image,attribute,exception);
4623               if (value != (const char *) NULL)
4624                 s=newSVpv(value,0);
4625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4626               continue;
4627             }
4628           if (LocaleCompare(attribute,"authenticate") == 0)
4629             {
4630               if (info)
4631                 {
4632                   const char
4633                     *option;
4634
4635                   option=GetImageOption(info->image_info,attribute);
4636                   if (option != (const char *) NULL)
4637                     s=newSVpv(option,0);
4638                 }
4639               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4640               continue;
4641             }
4642           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4643             attribute);
4644           break;
4645         }
4646         case 'B':
4647         case 'b':
4648         {
4649           if (LocaleCompare(attribute,"background") == 0)
4650             {
4651               if (image == (Image *) NULL)
4652                 break;
4653               (void) FormatLocaleString(color,MagickPathExtent,
4654                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4655                 (double) image->background_color.green,
4656                 (double) image->background_color.blue,
4657                 (double) image->background_color.alpha);
4658               s=newSVpv(color,0);
4659               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4660               continue;
4661             }
4662           if (LocaleCompare(attribute,"base-columns") == 0)
4663             {
4664               if (image != (Image *) NULL)
4665                 s=newSViv((ssize_t) image->magick_columns);
4666               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4667               continue;
4668             }
4669           if (LocaleCompare(attribute,"base-filename") == 0)
4670             {
4671               if (image != (Image *) NULL)
4672                 s=newSVpv(image->magick_filename,0);
4673               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4674               continue;
4675             }
4676           if (LocaleCompare(attribute,"base-height") == 0)
4677             {
4678               if (image != (Image *) NULL)
4679                 s=newSViv((ssize_t) image->magick_rows);
4680               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4681               continue;
4682             }
4683           if (LocaleCompare(attribute,"base-rows") == 0)
4684             {
4685               if (image != (Image *) NULL)
4686                 s=newSViv((ssize_t) image->magick_rows);
4687               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4688               continue;
4689             }
4690           if (LocaleCompare(attribute,"base-width") == 0)
4691             {
4692               if (image != (Image *) NULL)
4693                 s=newSViv((ssize_t) image->magick_columns);
4694               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4695               continue;
4696             }
4697           if (LocaleCompare(attribute,"blue-primary") == 0)
4698             {
4699               if (image == (Image *) NULL)
4700                 break;
4701               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4702                 image->chromaticity.blue_primary.x,
4703                 image->chromaticity.blue_primary.y);
4704               s=newSVpv(color,0);
4705               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4706               continue;
4707             }
4708           if (LocaleCompare(attribute,"bordercolor") == 0)
4709             {
4710               if (image == (Image *) NULL)
4711                 break;
4712               (void) FormatLocaleString(color,MagickPathExtent,
4713                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4714                 (double) image->border_color.green,
4715                 (double) image->border_color.blue,
4716                 (double) image->border_color.alpha);
4717               s=newSVpv(color,0);
4718               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4719               continue;
4720             }
4721           if (LocaleCompare(attribute,"bounding-box") == 0)
4722             {
4723               char
4724                 geometry[MagickPathExtent];
4725
4726               RectangleInfo
4727                 page;
4728
4729               if (image == (Image *) NULL)
4730                 break;
4731               page=GetImageBoundingBox(image,exception);
4732               (void) FormatLocaleString(geometry,MagickPathExtent,
4733                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4734                 page.height,(double) page.x,(double) page.y);
4735               s=newSVpv(geometry,0);
4736               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4737               continue;
4738             }
4739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4740             attribute);
4741           break;
4742         }
4743         case 'C':
4744         case 'c':
4745         {
4746           if (LocaleCompare(attribute,"class") == 0)
4747             {
4748               if (image == (Image *) NULL)
4749                 break;
4750               s=newSViv(image->storage_class);
4751               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4752                 image->storage_class));
4753               SvIOK_on(s);
4754               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4755               continue;
4756             }
4757           if (LocaleCompare(attribute,"clip-mask") == 0)
4758             {
4759               if (image != (Image *) NULL)
4760                 {
4761                   Image
4762                     *mask_image;
4763
4764                   SV
4765                     *sv;
4766
4767                   sv=NULL;
4768                   if (image->read_mask == MagickFalse)
4769                     ClipImage(image,exception);
4770                   mask_image=GetImageMask(image,exception);
4771                   if (mask_image != (Image *) NULL)
4772                     {
4773                       AddImageToRegistry(sv,mask_image);
4774                       s=sv_bless(newRV(sv),SvSTASH(reference));
4775                     }
4776                 }
4777               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4778               continue;
4779             }
4780           if (LocaleCompare(attribute,"clip-path") == 0)
4781             {
4782               if (image != (Image *) NULL)
4783                 {
4784                   Image
4785                     *mask_image;
4786
4787                   SV
4788                     *sv;
4789
4790                   sv=NULL;
4791                   if (image->read_mask != MagickFalse)
4792                     ClipImage(image,exception);
4793                   mask_image=GetImageMask(image,exception);
4794                   if (mask_image != (Image *) NULL)
4795                     {
4796                       AddImageToRegistry(sv,mask_image);
4797                       s=sv_bless(newRV(sv),SvSTASH(reference));
4798                     }
4799                 }
4800               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4801               continue;
4802             }
4803           if (LocaleCompare(attribute,"compression") == 0)
4804             {
4805               j=info ? info->image_info->compression : image ?
4806                 image->compression : UndefinedCompression;
4807               if (info)
4808                 if (info->image_info->compression == UndefinedCompression)
4809                   j=image->compression;
4810               s=newSViv(j);
4811               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4812                 j));
4813               SvIOK_on(s);
4814               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4815               continue;
4816             }
4817           if (LocaleCompare(attribute,"colorspace") == 0)
4818             {
4819               j=image ? image->colorspace : RGBColorspace;
4820               s=newSViv(j);
4821               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4822                 j));
4823               SvIOK_on(s);
4824               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4825               continue;
4826             }
4827           if (LocaleCompare(attribute,"colors") == 0)
4828             {
4829               if (image != (Image *) NULL)
4830                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4831                   exception));
4832               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4833               continue;
4834             }
4835           if (LocaleNCompare(attribute,"colormap",8) == 0)
4836             {
4837               int
4838                 items;
4839
4840               if (image == (Image *) NULL || !image->colormap)
4841                 break;
4842               j=0;
4843               items=sscanf(attribute,"%*[^[][%ld",&j);
4844               (void) items;
4845               if (j > (ssize_t) image->colors)
4846                 j%=image->colors;
4847               (void) FormatLocaleString(color,MagickPathExtent,
4848                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4849                 (double) image->colormap[j].green,
4850                 (double) image->colormap[j].blue,
4851                 (double) image->colormap[j].alpha);
4852               s=newSVpv(color,0);
4853               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4854               continue;
4855             }
4856           if (LocaleCompare(attribute,"columns") == 0)
4857             {
4858               if (image != (Image *) NULL)
4859                 s=newSViv((ssize_t) image->columns);
4860               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4861               continue;
4862             }
4863           if (LocaleCompare(attribute,"comment") == 0)
4864             {
4865               const char
4866                 *value;
4867
4868               value=GetImageProperty(image,attribute,exception);
4869               if (value != (const char *) NULL)
4870                 s=newSVpv(value,0);
4871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4872               continue;
4873             }
4874           if (LocaleCompare(attribute,"copyright") == 0)
4875             {
4876               s=newSVpv(GetMagickCopyright(),0);
4877               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4878               continue;
4879             }
4880           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4881             attribute);
4882           break;
4883         }
4884         case 'D':
4885         case 'd':
4886         {
4887           if (LocaleCompare(attribute,"density") == 0)
4888             {
4889               char
4890                 geometry[MagickPathExtent];
4891
4892               if (image == (Image *) NULL)
4893                 break;
4894               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4895                 image->resolution.x,image->resolution.y);
4896               s=newSVpv(geometry,0);
4897               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4898               continue;
4899             }
4900           if (LocaleCompare(attribute,"delay") == 0)
4901             {
4902               if (image != (Image *) NULL)
4903                 s=newSViv((ssize_t) image->delay);
4904               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4905               continue;
4906             }
4907           if (LocaleCompare(attribute,"depth") == 0)
4908             {
4909               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4910               if (image != (Image *) NULL)
4911                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4912               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4913               continue;
4914             }
4915           if (LocaleCompare(attribute,"directory") == 0)
4916             {
4917               if (image && image->directory)
4918                 s=newSVpv(image->directory,0);
4919               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4920               continue;
4921             }
4922           if (LocaleCompare(attribute,"dispose") == 0)
4923             {
4924               if (image == (Image *) NULL)
4925                 break;
4926
4927               s=newSViv(image->dispose);
4928               (void) sv_setpv(s,
4929                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4930               SvIOK_on(s);
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           if (LocaleCompare(attribute,"disk") == 0)
4935             {
4936               s=newSViv(GetMagickResource(DiskResource));
4937               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4938               continue;
4939             }
4940           if (LocaleCompare(attribute,"dither") == 0)
4941             {
4942               if (info)
4943                 s=newSViv((ssize_t) info->image_info->dither);
4944               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945               continue;
4946             }
4947           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4948             {
4949               if (info && info->image_info->server_name)
4950                 s=newSVpv(info->image_info->server_name,0);
4951               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4952               continue;
4953             }
4954           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4955             attribute);
4956           break;
4957         }
4958         case 'E':
4959         case 'e':
4960         {
4961           if (LocaleCompare(attribute,"elapsed-time") == 0)
4962             {
4963               if (image != (Image *) NULL)
4964                 s=newSVnv(GetElapsedTime(&image->timer));
4965               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4966               continue;
4967             }
4968           if (LocaleCompare(attribute,"endian") == 0)
4969             {
4970               j=info ? info->image_info->endian : image ? image->endian :
4971                 UndefinedEndian;
4972               s=newSViv(j);
4973               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4974               SvIOK_on(s);
4975               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4976               continue;
4977             }
4978           if (LocaleCompare(attribute,"error") == 0)
4979             {
4980               if (image != (Image *) NULL)
4981                 s=newSVnv(image->error.mean_error_per_pixel);
4982               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4983               continue;
4984             }
4985           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4986             attribute);
4987           break;
4988         }
4989         case 'F':
4990         case 'f':
4991         {
4992           if (LocaleCompare(attribute,"filesize") == 0)
4993             {
4994               if (image != (Image *) NULL)
4995                 s=newSViv((ssize_t) GetBlobSize(image));
4996               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4997               continue;
4998             }
4999           if (LocaleCompare(attribute,"filename") == 0)
5000             {
5001               if (info && info->image_info->filename &&
5002                   *info->image_info->filename)
5003                 s=newSVpv(info->image_info->filename,0);
5004               if (image != (Image *) NULL)
5005                 s=newSVpv(image->filename,0);
5006               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5007               continue;
5008             }
5009           if (LocaleCompare(attribute,"filter") == 0)
5010             {
5011               s=image ? newSViv(image->filter) : newSViv(0);
5012               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5013                 image->filter));
5014               SvIOK_on(s);
5015               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5016               continue;
5017             }
5018           if (LocaleCompare(attribute,"font") == 0)
5019             {
5020               if (info && info->image_info->font)
5021                 s=newSVpv(info->image_info->font,0);
5022               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5023               continue;
5024             }
5025           if (LocaleCompare(attribute,"foreground") == 0)
5026             continue;
5027           if (LocaleCompare(attribute,"format") == 0)
5028             {
5029               const MagickInfo
5030                 *magick_info;
5031
5032               magick_info=(const MagickInfo *) NULL;
5033               if (info && (*info->image_info->magick != '\0'))
5034                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5035               if (image != (Image *) NULL)
5036                 magick_info=GetMagickInfo(image->magick,exception);
5037               if ((magick_info != (const MagickInfo *) NULL) &&
5038                   (*magick_info->description != '\0'))
5039                 s=newSVpv((char *) magick_info->description,0);
5040               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5041               continue;
5042             }
5043           if (LocaleCompare(attribute,"fuzz") == 0)
5044             {
5045               if (info)
5046                 s=newSVnv(info->image_info->fuzz);
5047               if (image != (Image *) NULL)
5048                 s=newSVnv(image->fuzz);
5049               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5050               continue;
5051             }
5052           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5053             attribute);
5054           break;
5055         }
5056         case 'G':
5057         case 'g':
5058         {
5059           if (LocaleCompare(attribute,"gamma") == 0)
5060             {
5061               if (image != (Image *) NULL)
5062                 s=newSVnv(image->gamma);
5063               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5064               continue;
5065             }
5066           if (LocaleCompare(attribute,"geometry") == 0)
5067             {
5068               if (image && image->geometry)
5069                 s=newSVpv(image->geometry,0);
5070               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5071               continue;
5072             }
5073           if (LocaleCompare(attribute,"gravity") == 0)
5074             {
5075               s=image ? newSViv(image->gravity) : newSViv(0);
5076               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5077                 image->gravity));
5078               SvIOK_on(s);
5079               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5080               continue;
5081             }
5082           if (LocaleCompare(attribute,"green-primary") == 0)
5083             {
5084               if (image == (Image *) NULL)
5085                 break;
5086               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5087                 image->chromaticity.green_primary.x,
5088                 image->chromaticity.green_primary.y);
5089               s=newSVpv(color,0);
5090               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5091               continue;
5092             }
5093           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5094             attribute);
5095           break;
5096         }
5097         case 'H':
5098         case 'h':
5099         {
5100           if (LocaleCompare(attribute,"height") == 0)
5101             {
5102               if (image != (Image *) NULL)
5103                 s=newSViv((ssize_t) image->rows);
5104               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5105               continue;
5106             }
5107           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5108             attribute);
5109           break;
5110         }
5111         case 'I':
5112         case 'i':
5113         {
5114           if (LocaleCompare(attribute,"icc") == 0)
5115             {
5116               if (image != (Image *) NULL)
5117                 {
5118                   const StringInfo
5119                     *profile;
5120
5121                   profile=GetImageProfile(image,"icc");
5122                   if (profile != (StringInfo *) NULL)
5123                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5124                       GetStringInfoLength(profile));
5125                 }
5126               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5127               continue;
5128             }
5129           if (LocaleCompare(attribute,"icm") == 0)
5130             {
5131               if (image != (Image *) NULL)
5132                 {
5133                   const StringInfo
5134                     *profile;
5135
5136                   profile=GetImageProfile(image,"icm");
5137                   if (profile != (const StringInfo *) NULL)
5138                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5139                       GetStringInfoLength(profile));
5140                 }
5141               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5142               continue;
5143             }
5144           if (LocaleCompare(attribute,"id") == 0)
5145             {
5146               if (image != (Image *) NULL)
5147                 {
5148                   char
5149                     key[MagickPathExtent];
5150
5151                   MagickBooleanType
5152                     status;
5153
5154                   static ssize_t
5155                     id = 0;
5156
5157                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5158                     id);
5159                   status=SetImageRegistry(ImageRegistryType,key,image,
5160                     exception);
5161                   (void) status;
5162                   s=newSViv(id++);
5163                 }
5164               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5165               continue;
5166             }
5167           if (LocaleNCompare(attribute,"index",5) == 0)
5168             {
5169               char
5170                 name[MagickPathExtent];
5171
5172               int
5173                 items;
5174
5175               long
5176                 x,
5177                 y;
5178
5179               register const Quantum
5180                 *p;
5181
5182               CacheView
5183                 *image_view;
5184
5185               if (image == (Image *) NULL)
5186                 break;
5187               if (image->storage_class != PseudoClass)
5188                 break;
5189               x=0;
5190               y=0;
5191               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5192               (void) items;
5193               image_view=AcquireVirtualCacheView(image,exception);
5194               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5195               if (p != (const Quantum *) NULL)
5196                 {
5197                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5198                     GetPixelIndex(image,p));
5199                   s=newSVpv(name,0);
5200                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5201                 }
5202               image_view=DestroyCacheView(image_view);
5203               continue;
5204             }
5205           if (LocaleCompare(attribute,"iptc") == 0)
5206             {
5207               if (image != (Image *) NULL)
5208                 {
5209                   const StringInfo
5210                     *profile;
5211
5212                   profile=GetImageProfile(image,"iptc");
5213                   if (profile != (const StringInfo *) NULL)
5214                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5215                       GetStringInfoLength(profile));
5216                 }
5217               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5218               continue;
5219             }
5220           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5221             {
5222               if (image != (Image *) NULL)
5223                 s=newSViv((ssize_t) image->iterations);
5224               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5225               continue;
5226             }
5227           if (LocaleCompare(attribute,"interlace") == 0)
5228             {
5229               j=info ? info->image_info->interlace : image ? image->interlace :
5230                 UndefinedInterlace;
5231               s=newSViv(j);
5232               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5233                 j));
5234               SvIOK_on(s);
5235               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5236               continue;
5237             }
5238           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5239             attribute);
5240           break;
5241         }
5242         case 'L':
5243         case 'l':
5244         {
5245           if (LocaleCompare(attribute,"label") == 0)
5246             {
5247               const char
5248                 *value;
5249
5250               if (image == (Image *) NULL)
5251                 break;
5252               value=GetImageProperty(image,"Label",exception);
5253               if (value != (const char *) NULL)
5254                 s=newSVpv(value,0);
5255               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5256               continue;
5257             }
5258           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5259             {
5260               if (image != (Image *) NULL)
5261                 s=newSViv((ssize_t) image->iterations);
5262               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5263               continue;
5264             }
5265           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5266             attribute);
5267           break;
5268         }
5269         case 'M':
5270         case 'm':
5271         {
5272           if (LocaleCompare(attribute,"magick") == 0)
5273             {
5274               if (info && *info->image_info->magick)
5275                 s=newSVpv(info->image_info->magick,0);
5276               if (image != (Image *) NULL)
5277                 s=newSVpv(image->magick,0);
5278               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5279               continue;
5280             }
5281           if (LocaleCompare(attribute,"map") == 0)
5282             {
5283               s=newSViv(GetMagickResource(MapResource));
5284               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5285               continue;
5286             }
5287           if (LocaleCompare(attribute,"maximum-error") == 0)
5288             {
5289               if (image != (Image *) NULL)
5290                 s=newSVnv(image->error.normalized_maximum_error);
5291               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5292               continue;
5293             }
5294           if (LocaleCompare(attribute,"memory") == 0)
5295             {
5296               s=newSViv(GetMagickResource(MemoryResource));
5297               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298               continue;
5299             }
5300           if (LocaleCompare(attribute,"mean-error") == 0)
5301             {
5302               if (image != (Image *) NULL)
5303                 s=newSVnv(image->error.normalized_mean_error);
5304               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5305               continue;
5306             }
5307           if (LocaleCompare(attribute,"mime") == 0)
5308             {
5309               if (info && *info->image_info->magick)
5310                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5311               if (image != (Image *) NULL)
5312                 s=newSVpv(MagickToMime(image->magick),0);
5313               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5314               continue;
5315             }
5316           if (LocaleCompare(attribute,"mattecolor") == 0)
5317             {
5318               if (image == (Image *) NULL)
5319                 break;
5320               (void) FormatLocaleString(color,MagickPathExtent,
5321                 "%.20g,%.20g,%.20g,%.20g",(double) image->matte_color.red,
5322                 (double) image->matte_color.green,
5323                 (double) image->matte_color.blue,
5324                 (double) image->matte_color.alpha);
5325               s=newSVpv(color,0);
5326               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5327               continue;
5328             }
5329           if (LocaleCompare(attribute,"matte") == 0)
5330             {
5331               if (image != (Image *) NULL)
5332                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5333                   1 : 0);
5334               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5335               continue;
5336             }
5337           if (LocaleCompare(attribute,"mime") == 0)
5338             {
5339               const char
5340                 *magick;
5341
5342               magick=NULL;
5343               if (info && *info->image_info->magick)
5344                 magick=info->image_info->magick;
5345               if (image != (Image *) NULL)
5346                 magick=image->magick;
5347               if (magick)
5348                 {
5349                   char
5350                     *mime;
5351
5352                   mime=MagickToMime(magick);
5353                   s=newSVpv(mime,0);
5354                   mime=(char *) RelinquishMagickMemory(mime);
5355                 }
5356               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5357               continue;
5358             }
5359           if (LocaleCompare(attribute,"monochrome") == 0)
5360             {
5361               if (image == (Image *) NULL)
5362                 continue;
5363               j=info ? info->image_info->monochrome :
5364                 SetImageMonochrome(image,exception);
5365               s=newSViv(j);
5366               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5367               continue;
5368             }
5369           if (LocaleCompare(attribute,"montage") == 0)
5370             {
5371               if (image && image->montage)
5372                 s=newSVpv(image->montage,0);
5373               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5374               continue;
5375             }
5376           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5377             attribute);
5378           break;
5379         }
5380         case 'O':
5381         case 'o':
5382         {
5383           if (LocaleCompare(attribute,"orientation") == 0)
5384             {
5385               j=info ? info->image_info->orientation : image ?
5386                 image->orientation : UndefinedOrientation;
5387               s=newSViv(j);
5388               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5389                 j));
5390               SvIOK_on(s);
5391               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5392               continue;
5393             }
5394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5395             attribute);
5396           break;
5397         }
5398         case 'P':
5399         case 'p':
5400         {
5401           if (LocaleCompare(attribute,"page") == 0)
5402             {
5403               if (info && info->image_info->page)
5404                 s=newSVpv(info->image_info->page,0);
5405               if (image != (Image *) NULL)
5406                 {
5407                   char
5408                     geometry[MagickPathExtent];
5409
5410                   (void) FormatLocaleString(geometry,MagickPathExtent,
5411                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5412                     (double) image->page.height,(double) image->page.x,(double)
5413                     image->page.y);
5414                   s=newSVpv(geometry,0);
5415                 }
5416               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5417               continue;
5418             }
5419           if (LocaleCompare(attribute,"page.x") == 0)
5420             {
5421               if (image != (Image *) NULL)
5422                 s=newSViv((ssize_t) image->page.x);
5423               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5424               continue;
5425             }
5426           if (LocaleCompare(attribute,"page.y") == 0)
5427             {
5428               if (image != (Image *) NULL)
5429                 s=newSViv((ssize_t) image->page.y);
5430               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5431               continue;
5432             }
5433           if (LocaleNCompare(attribute,"pixel",5) == 0)
5434             {
5435               char
5436                 tuple[MagickPathExtent];
5437
5438               int
5439                 items;
5440
5441               long
5442                 x,
5443                 y;
5444
5445               register const Quantum
5446                 *p;
5447
5448               if (image == (Image *) NULL)
5449                 break;
5450               x=0;
5451               y=0;
5452               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5453               (void) items;
5454               p=GetVirtualPixels(image,x,y,1,1,exception);
5455               if (image->colorspace != CMYKColorspace)
5456                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5457                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5458                   GetPixelRed(image,p),GetPixelGreen(image,p),
5459                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5460               else
5461                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5462                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5463                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5464                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5465                   GetPixelAlpha(image,p));
5466               s=newSVpv(tuple,0);
5467               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5468               continue;
5469             }
5470           if (LocaleCompare(attribute,"pointsize") == 0)
5471             {
5472               if (info)
5473                 s=newSViv((ssize_t) info->image_info->pointsize);
5474               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5475               continue;
5476             }
5477           if (LocaleCompare(attribute,"preview") == 0)
5478             {
5479               s=newSViv(info->image_info->preview_type);
5480               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5481                 info->image_info->preview_type));
5482               SvIOK_on(s);
5483               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5484               continue;
5485             }
5486           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5487             attribute);
5488           break;
5489         }
5490         case 'Q':
5491         case 'q':
5492         {
5493           if (LocaleCompare(attribute,"quality") == 0)
5494             {
5495               if (info)
5496                 s=newSViv((ssize_t) info->image_info->quality);
5497               if (image != (Image *) NULL)
5498                 s=newSViv((ssize_t) image->quality);
5499               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5500               continue;
5501             }
5502           if (LocaleCompare(attribute,"quantum") == 0)
5503             {
5504               if (info)
5505                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5506               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5507               continue;
5508             }
5509           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5510             attribute);
5511           break;
5512         }
5513         case 'R':
5514         case 'r':
5515         {
5516           if (LocaleCompare(attribute,"rendering-intent") == 0)
5517             {
5518               s=newSViv(image->rendering_intent);
5519               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5520                 image->rendering_intent));
5521               SvIOK_on(s);
5522               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5523               continue;
5524             }
5525           if (LocaleCompare(attribute,"red-primary") == 0)
5526             {
5527               if (image == (Image *) NULL)
5528                 break;
5529               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5530                 image->chromaticity.red_primary.x,
5531                 image->chromaticity.red_primary.y);
5532               s=newSVpv(color,0);
5533               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5534               continue;
5535             }
5536           if (LocaleCompare(attribute,"rows") == 0)
5537             {
5538               if (image != (Image *) NULL)
5539                 s=newSViv((ssize_t) image->rows);
5540               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5541               continue;
5542             }
5543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5544             attribute);
5545           break;
5546         }
5547         case 'S':
5548         case 's':
5549         {
5550           if (LocaleCompare(attribute,"sampling-factor") == 0)
5551             {
5552               if (info && info->image_info->sampling_factor)
5553                 s=newSVpv(info->image_info->sampling_factor,0);
5554               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5555               continue;
5556             }
5557           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5558             {
5559               if (info && info->image_info->server_name)
5560                 s=newSVpv(info->image_info->server_name,0);
5561               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5562               continue;
5563             }
5564           if (LocaleCompare(attribute,"size") == 0)
5565             {
5566               if (info && info->image_info->size)
5567                 s=newSVpv(info->image_info->size,0);
5568               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5569               continue;
5570             }
5571           if (LocaleCompare(attribute,"scene") == 0)
5572             {
5573               if (image != (Image *) NULL)
5574                 s=newSViv((ssize_t) image->scene);
5575               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5576               continue;
5577             }
5578           if (LocaleCompare(attribute,"scenes") == 0)
5579             {
5580               if (image != (Image *) NULL)
5581                 s=newSViv((ssize_t) info->image_info->number_scenes);
5582               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5583               continue;
5584             }
5585           if (LocaleCompare(attribute,"signature") == 0)
5586             {
5587               const char
5588                 *value;
5589
5590               if (image == (Image *) NULL)
5591                 break;
5592               (void) SignatureImage(image,exception);
5593               value=GetImageProperty(image,"Signature",exception);
5594               if (value != (const char *) NULL)
5595                 s=newSVpv(value,0);
5596               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5597               continue;
5598             }
5599           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5600             attribute);
5601           break;
5602         }
5603         case 'T':
5604         case 't':
5605         {
5606           if (LocaleCompare(attribute,"taint") == 0)
5607             {
5608               if (image != (Image *) NULL)
5609                 s=newSViv((ssize_t) IsTaintImage(image));
5610               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5611               continue;
5612             }
5613           if (LocaleCompare(attribute,"texture") == 0)
5614             {
5615               if (info && info->image_info->texture)
5616                 s=newSVpv(info->image_info->texture,0);
5617               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5618               continue;
5619             }
5620           if (LocaleCompare(attribute,"total-ink-density") == 0)
5621             {
5622               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5623               if (image != (Image *) NULL)
5624                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5625               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5626               continue;
5627             }
5628           if (LocaleCompare(attribute,"transparent-color") == 0)
5629             {
5630               if (image == (Image *) NULL)
5631                 break;
5632               (void) FormatLocaleString(color,MagickPathExtent,
5633                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5634                 (double) image->transparent_color.green,
5635                 (double) image->transparent_color.blue,
5636                 (double) image->transparent_color.alpha);
5637               s=newSVpv(color,0);
5638               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5639               continue;
5640             }
5641           if (LocaleCompare(attribute,"type") == 0)
5642             {
5643               if (image == (Image *) NULL)
5644                 break;
5645               j=(ssize_t) GetImageType(image,exception);
5646               s=newSViv(j);
5647               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5648               SvIOK_on(s);
5649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5650               continue;
5651             }
5652           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5653             attribute);
5654           break;
5655         }
5656         case 'U':
5657         case 'u':
5658         {
5659           if (LocaleCompare(attribute,"units") == 0)
5660             {
5661               j=info ? info->image_info->units : image ? image->units :
5662                 UndefinedResolution;
5663               if (info && (info->image_info->units == UndefinedResolution))
5664                 if (image)
5665                   j=image->units;
5666               if (j == UndefinedResolution)
5667                 s=newSVpv("undefined units",0);
5668               else
5669                 if (j == PixelsPerInchResolution)
5670                   s=newSVpv("pixels / inch",0);
5671                 else
5672                   s=newSVpv("pixels / centimeter",0);
5673               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5674               continue;
5675             }
5676           if (LocaleCompare(attribute,"user-time") == 0)
5677             {
5678               if (image != (Image *) NULL)
5679                 s=newSVnv(GetUserTime(&image->timer));
5680               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5681               continue;
5682             }
5683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5684             attribute);
5685           break;
5686         }
5687         case 'V':
5688         case 'v':
5689         {
5690           if (LocaleCompare(attribute,"verbose") == 0)
5691             {
5692               if (info)
5693                 s=newSViv((ssize_t) info->image_info->verbose);
5694               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5695               continue;
5696             }
5697           if (LocaleCompare(attribute,"version") == 0)
5698             {
5699               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5701               continue;
5702             }
5703           if (LocaleCompare(attribute,"view") == 0)
5704             {
5705               if (info && info->image_info->view)
5706                 s=newSVpv(info->image_info->view,0);
5707               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5708               continue;
5709             }
5710           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5711             {
5712               if (image == (Image *) NULL)
5713                 break;
5714               j=(ssize_t) GetImageVirtualPixelMethod(image);
5715               s=newSViv(j);
5716               (void) sv_setpv(s,CommandOptionToMnemonic(
5717                 MagickVirtualPixelOptions,j));
5718               SvIOK_on(s);
5719               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5720               continue;
5721             }
5722           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5723             attribute);
5724           break;
5725         }
5726         case 'W':
5727         case 'w':
5728         {
5729           if (LocaleCompare(attribute,"white-point") == 0)
5730             {
5731               if (image == (Image *) NULL)
5732                 break;
5733               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5734                 image->chromaticity.white_point.x,
5735                 image->chromaticity.white_point.y);
5736               s=newSVpv(color,0);
5737               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5738               continue;
5739             }
5740           if (LocaleCompare(attribute,"width") == 0)
5741             {
5742               if (image != (Image *) NULL)
5743                 s=newSViv((ssize_t) image->columns);
5744               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5745               continue;
5746             }
5747           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5748              attribute);
5749           break;
5750         }
5751         case 'X':
5752         case 'x':
5753         {
5754           if (LocaleCompare(attribute,"x-resolution") == 0)
5755             {
5756               if (image != (Image *) NULL)
5757                 s=newSVnv(image->resolution.x);
5758               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5759               continue;
5760             }
5761           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5762             attribute);
5763           break;
5764         }
5765         case 'Y':
5766         case 'y':
5767         {
5768           if (LocaleCompare(attribute,"y-resolution") == 0)
5769             {
5770               if (image != (Image *) NULL)
5771                 s=newSVnv(image->resolution.y);
5772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5773               continue;
5774             }
5775           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5776             attribute);
5777           break;
5778         }
5779         default:
5780           break;
5781       }
5782       if (image == (Image *) NULL)
5783         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5784           attribute)
5785       else
5786         {
5787           value=GetImageProperty(image,attribute,exception);
5788           if (value != (const char *) NULL)
5789             {
5790               s=newSVpv(value,0);
5791               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5792             }
5793           else
5794             if (*attribute != '%')
5795               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5796                 attribute)
5797             else
5798               {
5799                  char
5800                    *meta;
5801
5802                  meta=InterpretImageProperties(info ? info->image_info :
5803                    (ImageInfo *) NULL,image,attribute,exception);
5804                  s=newSVpv(meta,0);
5805                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5806                  meta=(char *) RelinquishMagickMemory(meta);
5807               }
5808         }
5809     }
5810     exception=DestroyExceptionInfo(exception);
5811     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5812   }
5813 \f
5814 #
5815 ###############################################################################
5816 #                                                                             #
5817 #                                                                             #
5818 #                                                                             #
5819 #   G e t A u t h e n t i c P i x e l s                                       #
5820 #                                                                             #
5821 #                                                                             #
5822 #                                                                             #
5823 ###############################################################################
5824 #
5825 #
5826 void *
5827 GetAuthenticPixels(ref,...)
5828   Image::Magick ref = NO_INIT
5829   ALIAS:
5830     getauthenticpixels = 1
5831     GetImagePixels = 2
5832     getimagepixels = 3
5833   CODE:
5834   {
5835     char
5836       *attribute;
5837
5838     ExceptionInfo
5839       *exception;
5840
5841     Image
5842       *image;
5843
5844     RectangleInfo
5845       region;
5846
5847     ssize_t
5848       i;
5849
5850     struct PackageInfo
5851       *info;
5852
5853     SV
5854       *perl_exception,
5855       *reference;
5856
5857     void
5858       *blob = NULL;
5859
5860     PERL_UNUSED_VAR(ref);
5861     PERL_UNUSED_VAR(ix);
5862     exception=AcquireExceptionInfo();
5863     perl_exception=newSVpv("",0);
5864     if (sv_isobject(ST(0)) == 0)
5865       {
5866         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5867           PackageName);
5868         goto PerlException;
5869       }
5870     reference=SvRV(ST(0));
5871
5872     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5873     if (image == (Image *) NULL)
5874       {
5875         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5876           PackageName);
5877         goto PerlException;
5878       }
5879
5880     region.x=0;
5881     region.y=0;
5882     region.width=image->columns;
5883     region.height=1;
5884     if (items == 1)
5885       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5886     for (i=2; i < items; i+=2)
5887     {
5888       attribute=(char *) SvPV(ST(i-1),na);
5889       switch (*attribute)
5890       {
5891         case 'g':
5892         case 'G':
5893         {
5894           if (LocaleCompare(attribute,"geometry") == 0)
5895             {
5896               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5897               break;
5898             }
5899           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5900             attribute);
5901           break;
5902         }
5903         case 'H':
5904         case 'h':
5905         {
5906           if (LocaleCompare(attribute,"height") == 0)
5907             {
5908               region.height=SvIV(ST(i));
5909               continue;
5910             }
5911           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5912             attribute);
5913           break;
5914         }
5915         case 'X':
5916         case 'x':
5917         {
5918           if (LocaleCompare(attribute,"x") == 0)
5919             {
5920               region.x=SvIV(ST(i));
5921               continue;
5922             }
5923           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5924             attribute);
5925           break;
5926         }
5927         case 'Y':
5928         case 'y':
5929         {
5930           if (LocaleCompare(attribute,"y") == 0)
5931             {
5932               region.y=SvIV(ST(i));
5933               continue;
5934             }
5935           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5936             attribute);
5937           break;
5938         }
5939         case 'W':
5940         case 'w':
5941         {
5942           if (LocaleCompare(attribute,"width") == 0)
5943             {
5944               region.width=SvIV(ST(i));
5945               continue;
5946             }
5947           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5948             attribute);
5949           break;
5950         }
5951       }
5952     }
5953     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5954       region.height,exception);
5955     if (blob != (void *) NULL)
5956       goto PerlEnd;
5957
5958   PerlException:
5959     InheritPerlException(exception,perl_exception);
5960     exception=DestroyExceptionInfo(exception);
5961     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5962
5963   PerlEnd:
5964     RETVAL = blob;
5965   }
5966   OUTPUT:
5967     RETVAL
5968 \f
5969 #
5970 ###############################################################################
5971 #                                                                             #
5972 #                                                                             #
5973 #                                                                             #
5974 #   G e t V i r t u a l P i x e l s                                           #
5975 #                                                                             #
5976 #                                                                             #
5977 #                                                                             #
5978 ###############################################################################
5979 #
5980 #
5981 void *
5982 GetVirtualPixels(ref,...)
5983   Image::Magick ref = NO_INIT
5984   ALIAS:
5985     getvirtualpixels = 1
5986     AcquireImagePixels = 2
5987     acquireimagepixels = 3
5988   CODE:
5989   {
5990     char
5991       *attribute;
5992
5993     const void
5994       *blob = NULL;
5995
5996     ExceptionInfo
5997       *exception;
5998
5999     Image
6000       *image;
6001
6002     RectangleInfo
6003       region;
6004
6005     ssize_t
6006       i;
6007
6008     struct PackageInfo
6009       *info;
6010
6011     SV
6012       *perl_exception,
6013       *reference;
6014
6015     PERL_UNUSED_VAR(ref);
6016     PERL_UNUSED_VAR(ix);
6017     exception=AcquireExceptionInfo();
6018     perl_exception=newSVpv("",0);
6019     if (sv_isobject(ST(0)) == 0)
6020       {
6021         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6022           PackageName);
6023         goto PerlException;
6024       }
6025     reference=SvRV(ST(0));
6026
6027     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6028     if (image == (Image *) NULL)
6029       {
6030         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6031           PackageName);
6032         goto PerlException;
6033       }
6034
6035     region.x=0;
6036     region.y=0;
6037     region.width=image->columns;
6038     region.height=1;
6039     if (items == 1)
6040       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6041     for (i=2; i < items; i+=2)
6042     {
6043       attribute=(char *) SvPV(ST(i-1),na);
6044       switch (*attribute)
6045       {
6046         case 'g':
6047         case 'G':
6048         {
6049           if (LocaleCompare(attribute,"geometry") == 0)
6050             {
6051               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6052               break;
6053             }
6054           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6055             attribute);
6056           break;
6057         }
6058         case 'H':
6059         case 'h':
6060         {
6061           if (LocaleCompare(attribute,"height") == 0)
6062             {
6063               region.height=SvIV(ST(i));
6064               continue;
6065             }
6066           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6067             attribute);
6068           break;
6069         }
6070         case 'X':
6071         case 'x':
6072         {
6073           if (LocaleCompare(attribute,"x") == 0)
6074             {
6075               region.x=SvIV(ST(i));
6076               continue;
6077             }
6078           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6079             attribute);
6080           break;
6081         }
6082         case 'Y':
6083         case 'y':
6084         {
6085           if (LocaleCompare(attribute,"y") == 0)
6086             {
6087               region.y=SvIV(ST(i));
6088               continue;
6089             }
6090           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6091             attribute);
6092           break;
6093         }
6094         case 'W':
6095         case 'w':
6096         {
6097           if (LocaleCompare(attribute,"width") == 0)
6098             {
6099               region.width=SvIV(ST(i));
6100               continue;
6101             }
6102           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6103             attribute);
6104           break;
6105         }
6106       }
6107     }
6108     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6109       region.height,exception);
6110     if (blob != (void *) NULL)
6111       goto PerlEnd;
6112
6113   PerlException:
6114     InheritPerlException(exception,perl_exception);
6115     exception=DestroyExceptionInfo(exception);
6116     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6117
6118   PerlEnd:
6119     RETVAL = (void *) blob;
6120   }
6121   OUTPUT:
6122     RETVAL
6123 \f
6124 #
6125 ###############################################################################
6126 #                                                                             #
6127 #                                                                             #
6128 #                                                                             #
6129 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6130 #                                                                             #
6131 #                                                                             #
6132 #                                                                             #
6133 ###############################################################################
6134 #
6135 #
6136 void *
6137 GetAuthenticMetacontent(ref,...)
6138   Image::Magick ref = NO_INIT
6139   ALIAS:
6140     getauthenticmetacontent = 1
6141     GetMetacontent = 2
6142     getmetacontent = 3
6143   CODE:
6144   {
6145     ExceptionInfo
6146       *exception;
6147
6148     Image
6149       *image;
6150
6151     struct PackageInfo
6152       *info;
6153
6154     SV
6155       *perl_exception,
6156       *reference;
6157
6158     void
6159       *blob = NULL;
6160
6161     PERL_UNUSED_VAR(ref);
6162     PERL_UNUSED_VAR(ix);
6163     exception=AcquireExceptionInfo();
6164     perl_exception=newSVpv("",0);
6165     if (sv_isobject(ST(0)) == 0)
6166       {
6167         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6168           PackageName);
6169         goto PerlException;
6170       }
6171     reference=SvRV(ST(0));
6172
6173     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6174     if (image == (Image *) NULL)
6175       {
6176         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6177           PackageName);
6178         goto PerlException;
6179       }
6180
6181     blob=(void *) GetAuthenticMetacontent(image);
6182     if (blob != (void *) NULL)
6183       goto PerlEnd;
6184
6185   PerlException:
6186     InheritPerlException(exception,perl_exception);
6187     exception=DestroyExceptionInfo(exception);
6188     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6189
6190   PerlEnd:
6191     RETVAL = blob;
6192   }
6193   OUTPUT:
6194     RETVAL
6195 \f
6196 #
6197 ###############################################################################
6198 #                                                                             #
6199 #                                                                             #
6200 #                                                                             #
6201 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6202 #                                                                             #
6203 #                                                                             #
6204 #                                                                             #
6205 ###############################################################################
6206 #
6207 #
6208 void *
6209 GetVirtualMetacontent(ref,...)
6210   Image::Magick ref = NO_INIT
6211   ALIAS:
6212     getvirtualmetacontent = 1
6213   CODE:
6214   {
6215     ExceptionInfo
6216       *exception;
6217
6218     Image
6219       *image;
6220
6221     struct PackageInfo
6222       *info;
6223
6224     SV
6225       *perl_exception,
6226       *reference;
6227
6228     void
6229       *blob = NULL;
6230
6231     PERL_UNUSED_VAR(ref);
6232     PERL_UNUSED_VAR(ix);
6233     exception=AcquireExceptionInfo();
6234     perl_exception=newSVpv("",0);
6235     if (sv_isobject(ST(0)) == 0)
6236       {
6237         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6238           PackageName);
6239         goto PerlException;
6240       }
6241     reference=SvRV(ST(0));
6242
6243     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6244     if (image == (Image *) NULL)
6245       {
6246         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6247           PackageName);
6248         goto PerlException;
6249       }
6250
6251     blob=(void *) GetVirtualMetacontent(image);
6252     if (blob != (void *) NULL)
6253       goto PerlEnd;
6254
6255   PerlException:
6256     InheritPerlException(exception,perl_exception);
6257     exception=DestroyExceptionInfo(exception);
6258     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6259
6260   PerlEnd:
6261     RETVAL = blob;
6262   }
6263   OUTPUT:
6264     RETVAL
6265 \f
6266 #
6267 ###############################################################################
6268 #                                                                             #
6269 #                                                                             #
6270 #                                                                             #
6271 #   H i s t o g r a m                                                         #
6272 #                                                                             #
6273 #                                                                             #
6274 #                                                                             #
6275 ###############################################################################
6276 #
6277 #
6278 void
6279 Histogram(ref,...)
6280   Image::Magick ref=NO_INIT
6281   ALIAS:
6282     HistogramImage = 1
6283     histogram      = 2
6284     histogramimage = 3
6285   PPCODE:
6286   {
6287     AV
6288       *av;
6289
6290     char
6291       message[MagickPathExtent];
6292
6293     PixelInfo
6294       *histogram;
6295
6296     ExceptionInfo
6297       *exception;
6298
6299     Image
6300       *image;
6301
6302     register ssize_t
6303       i;
6304
6305     ssize_t
6306       count;
6307
6308     struct PackageInfo
6309       *info;
6310
6311     SV
6312       *perl_exception,
6313       *reference;
6314
6315     size_t
6316       number_colors;
6317
6318     PERL_UNUSED_VAR(ref);
6319     PERL_UNUSED_VAR(ix);
6320     exception=AcquireExceptionInfo();
6321     perl_exception=newSVpv("",0);
6322     av=NULL;
6323     if (sv_isobject(ST(0)) == 0)
6324       {
6325         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6326           PackageName);
6327         goto PerlException;
6328       }
6329     reference=SvRV(ST(0));
6330     av=newAV();
6331     SvREFCNT_dec(av);
6332     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6333     if (image == (Image *) NULL)
6334       {
6335         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6336           PackageName);
6337         goto PerlException;
6338       }
6339     count=0;
6340     for ( ; image; image=image->next)
6341     {
6342       histogram=GetImageHistogram(image,&number_colors,exception);
6343       if (histogram == (PixelInfo *) NULL)
6344         continue;
6345       count+=(ssize_t) number_colors;
6346       EXTEND(sp,6*count);
6347       for (i=0; i < (ssize_t) number_colors; i++)
6348       {
6349         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6350           histogram[i].red);
6351         PUSHs(sv_2mortal(newSVpv(message,0)));
6352         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6353           histogram[i].green);
6354         PUSHs(sv_2mortal(newSVpv(message,0)));
6355         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6356           histogram[i].blue);
6357         PUSHs(sv_2mortal(newSVpv(message,0)));
6358         if (image->colorspace == CMYKColorspace)
6359           {
6360             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6361               histogram[i].black);
6362             PUSHs(sv_2mortal(newSVpv(message,0)));
6363           }
6364         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6365           histogram[i].alpha);
6366         PUSHs(sv_2mortal(newSVpv(message,0)));
6367         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6368           histogram[i].count);
6369         PUSHs(sv_2mortal(newSVpv(message,0)));
6370       }
6371       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6372     }
6373
6374   PerlException:
6375     InheritPerlException(exception,perl_exception);
6376     exception=DestroyExceptionInfo(exception);
6377     SvREFCNT_dec(perl_exception);
6378   }
6379 \f
6380 #
6381 ###############################################################################
6382 #                                                                             #
6383 #                                                                             #
6384 #                                                                             #
6385 #   G e t P i x e l                                                           #
6386 #                                                                             #
6387 #                                                                             #
6388 #                                                                             #
6389 ###############################################################################
6390 #
6391 #
6392 void
6393 GetPixel(ref,...)
6394   Image::Magick ref=NO_INIT
6395   ALIAS:
6396     getpixel = 1
6397     getPixel = 2
6398   PPCODE:
6399   {
6400     AV
6401       *av;
6402
6403     char
6404       *attribute;
6405
6406     ExceptionInfo
6407       *exception;
6408
6409     Image
6410       *image;
6411
6412     MagickBooleanType
6413       normalize;
6414
6415     RectangleInfo
6416       region;
6417
6418     register const Quantum
6419       *p;
6420
6421     register ssize_t
6422       i;
6423
6424     ssize_t
6425       option;
6426
6427     struct PackageInfo
6428       *info;
6429
6430     SV
6431       *perl_exception,
6432       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6433
6434     PERL_UNUSED_VAR(ref);
6435     PERL_UNUSED_VAR(ix);
6436     exception=AcquireExceptionInfo();
6437     perl_exception=newSVpv("",0);
6438     reference=SvRV(ST(0));
6439     av=(AV *) reference;
6440     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6441       exception);
6442     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6443     if (image == (Image *) NULL)
6444       {
6445         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6446           PackageName);
6447         goto PerlException;
6448       }
6449     normalize=MagickTrue;
6450     region.x=0;
6451     region.y=0;
6452     region.width=image->columns;
6453     region.height=1;
6454     if (items == 1)
6455       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6456     for (i=2; i < items; i+=2)
6457     {
6458       attribute=(char *) SvPV(ST(i-1),na);
6459       switch (*attribute)
6460       {
6461         case 'C':
6462         case 'c':
6463         {
6464           if (LocaleCompare(attribute,"channel") == 0)
6465             {
6466               ssize_t
6467                 option;
6468
6469               option=ParseChannelOption(SvPV(ST(i),na));
6470               if (option < 0)
6471                 {
6472                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6473                     SvPV(ST(i),na));
6474                   return;
6475                 }
6476               (void) SetPixelChannelMask(image,(ChannelType) option);
6477               break;
6478             }
6479           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6480             attribute);
6481           break;
6482         }
6483         case 'g':
6484         case 'G':
6485         {
6486           if (LocaleCompare(attribute,"geometry") == 0)
6487             {
6488               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6489               break;
6490             }
6491           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6492             attribute);
6493           break;
6494         }
6495         case 'N':
6496         case 'n':
6497         {
6498           if (LocaleCompare(attribute,"normalize") == 0)
6499             {
6500               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6501                 SvPV(ST(i),na));
6502               if (option < 0)
6503                 {
6504                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6505                     SvPV(ST(i),na));
6506                   break;
6507                 }
6508              normalize=option != 0 ? MagickTrue : MagickFalse;
6509              break;
6510             }
6511           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6512             attribute);
6513           break;
6514         }
6515         case 'x':
6516         case 'X':
6517         {
6518           if (LocaleCompare(attribute,"x") == 0)
6519             {
6520               region.x=SvIV(ST(i));
6521               break;
6522             }
6523           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6524             attribute);
6525           break;
6526         }
6527         case 'y':
6528         case 'Y':
6529         {
6530           if (LocaleCompare(attribute,"y") == 0)
6531             {
6532               region.y=SvIV(ST(i));
6533               break;
6534             }
6535           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6536             attribute);
6537           break;
6538         }
6539         default:
6540         {
6541           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6542             attribute);
6543           break;
6544         }
6545       }
6546     }
6547     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6548     if (p == (const Quantum *) NULL)
6549       PUSHs(&sv_undef);
6550     else
6551       {
6552         double
6553           scale;
6554
6555         scale=1.0;
6556         if (normalize != MagickFalse)
6557           scale=1.0/QuantumRange;
6558         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6559           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6560         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6561           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6562         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6563           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6564         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6565             (image->colorspace == CMYKColorspace))
6566           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6567         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6568           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6569       }
6570
6571   PerlException:
6572     InheritPerlException(exception,perl_exception);
6573     exception=DestroyExceptionInfo(exception);
6574     SvREFCNT_dec(perl_exception);
6575   }
6576 \f
6577 #
6578 ###############################################################################
6579 #                                                                             #
6580 #                                                                             #
6581 #                                                                             #
6582 #   G e t P i x e l s                                                         #
6583 #                                                                             #
6584 #                                                                             #
6585 #                                                                             #
6586 ###############################################################################
6587 #
6588 #
6589 void
6590 GetPixels(ref,...)
6591   Image::Magick ref=NO_INIT
6592   ALIAS:
6593     getpixels = 1
6594     getPixels = 2
6595   PPCODE:
6596   {
6597     AV
6598       *av;
6599
6600     char
6601       *attribute;
6602
6603     const char
6604       *map;
6605
6606     ExceptionInfo
6607       *exception;
6608
6609     Image
6610       *image;
6611
6612     MagickBooleanType
6613       normalize,
6614       status;
6615
6616     RectangleInfo
6617       region;
6618
6619     register ssize_t
6620       i;
6621
6622     ssize_t
6623       option;
6624
6625     struct PackageInfo
6626       *info;
6627
6628     SV
6629       *perl_exception,
6630       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6631
6632     PERL_UNUSED_VAR(ref);
6633     PERL_UNUSED_VAR(ix);
6634     exception=AcquireExceptionInfo();
6635     perl_exception=newSVpv("",0);
6636     reference=SvRV(ST(0));
6637     av=(AV *) reference;
6638     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6639       exception);
6640     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6641     if (image == (Image *) NULL)
6642       {
6643         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6644           PackageName);
6645         goto PerlException;
6646       }
6647     map="RGB";
6648     if (image->alpha_trait != UndefinedPixelTrait)
6649       map="RGBA";
6650     if (image->colorspace == CMYKColorspace)
6651       {
6652         map="CMYK";
6653         if (image->alpha_trait != UndefinedPixelTrait)
6654           map="CMYKA";
6655       }
6656     normalize=MagickFalse;
6657     region.x=0;
6658     region.y=0;
6659     region.width=image->columns;
6660     region.height=1;
6661     if (items == 1)
6662       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6663     for (i=2; i < items; i+=2)
6664     {
6665       attribute=(char *) SvPV(ST(i-1),na);
6666       switch (*attribute)
6667       {
6668         case 'g':
6669         case 'G':
6670         {
6671           if (LocaleCompare(attribute,"geometry") == 0)
6672             {
6673               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6674               break;
6675             }
6676           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6677             attribute);
6678           break;
6679         }
6680         case 'H':
6681         case 'h':
6682         {
6683           if (LocaleCompare(attribute,"height") == 0)
6684             {
6685               region.height=SvIV(ST(i));
6686               break;
6687             }
6688           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6689             attribute);
6690           break;
6691         }
6692         case 'M':
6693         case 'm':
6694         {
6695           if (LocaleCompare(attribute,"map") == 0)
6696             {
6697               map=SvPV(ST(i),na);
6698               break;
6699             }
6700           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6701             attribute);
6702           break;
6703         }
6704         case 'N':
6705         case 'n':
6706         {
6707           if (LocaleCompare(attribute,"normalize") == 0)
6708             {
6709               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6710                 SvPV(ST(i),na));
6711               if (option < 0)
6712                 {
6713                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6714                     SvPV(ST(i),na));
6715                   break;
6716                 }
6717              normalize=option != 0 ? MagickTrue : MagickFalse;
6718              break;
6719             }
6720           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6721             attribute);
6722           break;
6723         }
6724         case 'W':
6725         case 'w':
6726         {
6727           if (LocaleCompare(attribute,"width") == 0)
6728             {
6729               region.width=SvIV(ST(i));
6730               break;
6731             }
6732           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6733             attribute);
6734           break;
6735         }
6736         case 'x':
6737         case 'X':
6738         {
6739           if (LocaleCompare(attribute,"x") == 0)
6740             {
6741               region.x=SvIV(ST(i));
6742               break;
6743             }
6744           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6745             attribute);
6746           break;
6747         }
6748         case 'y':
6749         case 'Y':
6750         {
6751           if (LocaleCompare(attribute,"y") == 0)
6752             {
6753               region.y=SvIV(ST(i));
6754               break;
6755             }
6756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6757             attribute);
6758           break;
6759         }
6760         default:
6761         {
6762           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6763             attribute);
6764           break;
6765         }
6766       }
6767     }
6768     if (normalize != MagickFalse)
6769       {
6770         float
6771           *pixels;
6772
6773         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6774           region.height*sizeof(*pixels));
6775         if (pixels == (float *) NULL)
6776           {
6777             ThrowPerlException(exception,ResourceLimitError,
6778               "MemoryAllocationFailed",PackageName);
6779             goto PerlException;
6780           }
6781         status=ExportImagePixels(image,region.x,region.y,region.width,
6782           region.height,map,FloatPixel,pixels,exception);
6783         if (status == MagickFalse)
6784           PUSHs(&sv_undef);
6785         else
6786           {
6787             EXTEND(sp,strlen(map)*region.width*region.height);
6788             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6789               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6790           }
6791         pixels=(float *) RelinquishMagickMemory(pixels);
6792       }
6793     else
6794       {
6795         Quantum
6796           *pixels;
6797
6798         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6799           region.height*sizeof(*pixels));
6800         if (pixels == (Quantum *) NULL)
6801           {
6802             ThrowPerlException(exception,ResourceLimitError,
6803               "MemoryAllocationFailed",PackageName);
6804             goto PerlException;
6805           }
6806         status=ExportImagePixels(image,region.x,region.y,region.width,
6807           region.height,map,QuantumPixel,pixels,exception);
6808         if (status == MagickFalse)
6809           PUSHs(&sv_undef);
6810         else
6811           {
6812             EXTEND(sp,strlen(map)*region.width*region.height);
6813             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6814               PUSHs(sv_2mortal(newSViv(pixels[i])));
6815           }
6816         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6817       }
6818
6819   PerlException:
6820     InheritPerlException(exception,perl_exception);
6821     exception=DestroyExceptionInfo(exception);
6822     SvREFCNT_dec(perl_exception);
6823   }
6824 \f
6825 #
6826 ###############################################################################
6827 #                                                                             #
6828 #                                                                             #
6829 #                                                                             #
6830 #   I m a g e T o B l o b                                                     #
6831 #                                                                             #
6832 #                                                                             #
6833 #                                                                             #
6834 ###############################################################################
6835 #
6836 #
6837 void
6838 ImageToBlob(ref,...)
6839   Image::Magick ref=NO_INIT
6840   ALIAS:
6841     ImageToBlob  = 1
6842     imagetoblob  = 2
6843     toblob       = 3
6844     blob         = 4
6845   PPCODE:
6846   {
6847     char
6848       filename[MagickPathExtent];
6849
6850     ExceptionInfo
6851       *exception;
6852
6853     Image
6854       *image,
6855       *next;
6856
6857     register ssize_t
6858       i;
6859
6860     struct PackageInfo
6861       *info,
6862       *package_info;
6863
6864     size_t
6865       length;
6866
6867     ssize_t
6868       scene;
6869
6870     SV
6871       *perl_exception,
6872       *reference;
6873
6874     void
6875       *blob;
6876
6877     PERL_UNUSED_VAR(ref);
6878     PERL_UNUSED_VAR(ix);
6879     exception=AcquireExceptionInfo();
6880     perl_exception=newSVpv("",0);
6881     package_info=(struct PackageInfo *) NULL;
6882     if (sv_isobject(ST(0)) == 0)
6883       {
6884         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6885           PackageName);
6886         goto PerlException;
6887       }
6888     reference=SvRV(ST(0));
6889     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6890     if (image == (Image *) NULL)
6891       {
6892         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6893           PackageName);
6894         goto PerlException;
6895       }
6896     package_info=ClonePackageInfo(info,exception);
6897     for (i=2; i < items; i+=2)
6898       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6899     (void) CopyMagickString(filename,package_info->image_info->filename,
6900       MagickPathExtent);
6901     scene=0;
6902     for (next=image; next; next=next->next)
6903     {
6904       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6905       next->scene=scene++;
6906     }
6907     SetImageInfo(package_info->image_info,(unsigned int)
6908       GetImageListLength(image),exception);
6909     EXTEND(sp,(ssize_t) GetImageListLength(image));
6910     for ( ; image; image=image->next)
6911     {
6912       length=0;
6913       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6914       if (blob != (char *) NULL)
6915         {
6916           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6917           blob=(unsigned char *) RelinquishMagickMemory(blob);
6918         }
6919       if (package_info->image_info->adjoin)
6920         break;
6921     }
6922
6923   PerlException:
6924     if (package_info != (struct PackageInfo *) NULL)
6925       DestroyPackageInfo(package_info);
6926     InheritPerlException(exception,perl_exception);
6927     exception=DestroyExceptionInfo(exception);
6928     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6929   }
6930 \f
6931 #
6932 ###############################################################################
6933 #                                                                             #
6934 #                                                                             #
6935 #                                                                             #
6936 #   L a y e r s                                                               #
6937 #                                                                             #
6938 #                                                                             #
6939 #                                                                             #
6940 ###############################################################################
6941 #
6942 #
6943 void
6944 Layers(ref,...)
6945   Image::Magick ref=NO_INIT
6946   ALIAS:
6947     Layers                = 1
6948     layers           = 2
6949     OptimizeImageLayers   = 3
6950     optimizelayers        = 4
6951     optimizeimagelayers   = 5
6952   PPCODE:
6953   {
6954     AV
6955       *av;
6956
6957     char
6958       *attribute;
6959
6960     CompositeOperator
6961       compose;
6962
6963     ExceptionInfo
6964       *exception;
6965
6966     HV
6967       *hv;
6968
6969     Image
6970       *image,
6971       *layers;
6972
6973     LayerMethod
6974       method;
6975
6976     register ssize_t
6977       i;
6978
6979     ssize_t
6980       option,
6981       sp;
6982
6983     struct PackageInfo
6984       *info;
6985
6986     SV
6987       *av_reference,
6988       *perl_exception,
6989       *reference,
6990       *rv,
6991       *sv;
6992
6993     PERL_UNUSED_VAR(ref);
6994     PERL_UNUSED_VAR(ix);
6995     exception=AcquireExceptionInfo();
6996     perl_exception=newSVpv("",0);
6997     sv=NULL;
6998     if (sv_isobject(ST(0)) == 0)
6999       {
7000         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7001           PackageName);
7002         goto PerlException;
7003       }
7004     reference=SvRV(ST(0));
7005     hv=SvSTASH(reference);
7006     av=newAV();
7007     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7008     SvREFCNT_dec(av);
7009     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7010     if (image == (Image *) NULL)
7011       {
7012         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7013           PackageName);
7014         goto PerlException;
7015       }
7016     compose=image->compose;
7017     method=OptimizeLayer;
7018     for (i=2; i < items; i+=2)
7019     {
7020       attribute=(char *) SvPV(ST(i-1),na);
7021       switch (*attribute)
7022       {
7023         case 'C':
7024         case 'c':
7025         {
7026           if (LocaleCompare(attribute,"compose") == 0)
7027             {
7028               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7029                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7030               if (sp < 0)
7031                 {
7032                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7033                     SvPV(ST(i),na));
7034                   break;
7035                 }
7036               compose=(CompositeOperator) sp;
7037               break;
7038             }
7039           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7040             attribute);
7041           break;
7042         }
7043         case 'M':
7044         case 'm':
7045         {
7046           if (LocaleCompare(attribute,"method") == 0)
7047             {
7048               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7049                 SvPV(ST(i),na));
7050               if (option < 0)
7051                 {
7052                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7053                     SvPV(ST(i),na));
7054                   break;
7055                 }
7056               method=(LayerMethod) option;
7057               break;
7058             }
7059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7060             attribute);
7061           break;
7062         }
7063         default:
7064         {
7065           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7066             attribute);
7067           break;
7068         }
7069       }
7070     }
7071     layers=(Image *) NULL;
7072     switch (method)
7073     {
7074       case CompareAnyLayer:
7075       case CompareClearLayer:
7076       case CompareOverlayLayer:
7077       default:
7078       {
7079         layers=CompareImagesLayers(image,method,exception);
7080         break;
7081       }
7082       case MergeLayer:
7083       case FlattenLayer:
7084       case MosaicLayer:
7085       {
7086         layers=MergeImageLayers(image,method,exception);
7087         break;
7088       }
7089       case DisposeLayer:
7090       {
7091         layers=DisposeImages(image,exception);
7092         break;
7093       }
7094       case OptimizeImageLayer:
7095       {
7096         layers=OptimizeImageLayers(image,exception);
7097         break;
7098       }
7099       case OptimizePlusLayer:
7100       {
7101         layers=OptimizePlusImageLayers(image,exception);
7102         break;
7103       }
7104       case OptimizeTransLayer:
7105       {
7106         OptimizeImageTransparency(image,exception);
7107         break;
7108       }
7109       case RemoveDupsLayer:
7110       {
7111         RemoveDuplicateLayers(&image,exception);
7112         break;
7113       }
7114       case RemoveZeroLayer:
7115       {
7116         RemoveZeroDelayLayers(&image,exception);
7117         break;
7118       }
7119       case OptimizeLayer:
7120       {
7121         QuantizeInfo
7122           *quantize_info;
7123
7124         /*
7125           General Purpose, GIF Animation Optimizer.
7126         */
7127         layers=CoalesceImages(image,exception);
7128         if (layers == (Image *) NULL)
7129           break;
7130         image=layers;
7131         layers=OptimizeImageLayers(image,exception);
7132         if (layers == (Image *) NULL)
7133           break;
7134         image=DestroyImageList(image);
7135         image=layers;
7136         layers=(Image *) NULL;
7137         OptimizeImageTransparency(image,exception);
7138         quantize_info=AcquireQuantizeInfo(info->image_info);
7139         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7140         quantize_info=DestroyQuantizeInfo(quantize_info);
7141         break;
7142       }
7143       case CompositeLayer:
7144       {
7145         Image
7146           *source;
7147
7148         RectangleInfo
7149           geometry;
7150
7151         /*
7152           Split image sequence at the first 'NULL:' image.
7153         */
7154         source=image;
7155         while (source != (Image *) NULL)
7156         {
7157           source=GetNextImageInList(source);
7158           if ((source != (Image *) NULL) &&
7159               (LocaleCompare(source->magick,"NULL") == 0))
7160             break;
7161         }
7162         if (source != (Image *) NULL)
7163           {
7164             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7165                 (GetNextImageInList(source) == (Image *) NULL))
7166               source=(Image *) NULL;
7167             else
7168               {
7169                 /*
7170                   Separate the two lists, junk the null: image.
7171                 */
7172                 source=SplitImageList(source->previous);
7173                 DeleteImageFromList(&source);
7174               }
7175           }
7176         if (source == (Image *) NULL)
7177           {
7178             (void) ThrowMagickException(exception,GetMagickModule(),
7179               OptionError,"MissingNullSeparator","layers Composite");
7180             break;
7181           }
7182         /*
7183           Adjust offset with gravity and virtual canvas.
7184         */
7185         SetGeometry(image,&geometry);
7186         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7187         geometry.width=source->page.width != 0 ? source->page.width :
7188           source->columns;
7189         geometry.height=source->page.height != 0 ? source->page.height :
7190           source->rows;
7191         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7192           image->columns,image->page.height != 0 ? image->page.height :
7193           image->rows,image->gravity,&geometry);
7194         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7195         source=DestroyImageList(source);
7196         break;
7197       }
7198     }
7199     if (layers != (Image *) NULL)
7200       image=layers;
7201     else
7202       image=CloneImage(image,0,0,MagickTrue,exception);
7203     if (image == (Image *) NULL)
7204       goto PerlException;
7205     for ( ; image; image=image->next)
7206     {
7207       AddImageToRegistry(sv,image);
7208       rv=newRV(sv);
7209       av_push(av,sv_bless(rv,hv));
7210       SvREFCNT_dec(sv);
7211     }
7212     exception=DestroyExceptionInfo(exception);
7213     ST(0)=av_reference;
7214     SvREFCNT_dec(perl_exception);
7215     XSRETURN(1);
7216
7217   PerlException:
7218     InheritPerlException(exception,perl_exception);
7219     exception=DestroyExceptionInfo(exception);
7220     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7221     SvPOK_on(perl_exception);
7222     ST(0)=sv_2mortal(perl_exception);
7223     XSRETURN(1);
7224   }
7225 \f
7226 #
7227 ###############################################################################
7228 #                                                                             #
7229 #                                                                             #
7230 #                                                                             #
7231 #   M a g i c k T o M i m e                                                   #
7232 #                                                                             #
7233 #                                                                             #
7234 #                                                                             #
7235 ###############################################################################
7236 #
7237 #
7238 SV *
7239 MagickToMime(ref,name)
7240   Image::Magick ref=NO_INIT
7241   char *name
7242   ALIAS:
7243     magicktomime = 1
7244   CODE:
7245   {
7246     char
7247       *mime;
7248
7249     PERL_UNUSED_VAR(ref);
7250     PERL_UNUSED_VAR(ix);
7251     mime=MagickToMime(name);
7252     RETVAL=newSVpv(mime,0);
7253     mime=(char *) RelinquishMagickMemory(mime);
7254   }
7255   OUTPUT:
7256     RETVAL
7257 \f
7258 #
7259 ###############################################################################
7260 #                                                                             #
7261 #                                                                             #
7262 #                                                                             #
7263 #   M o g r i f y                                                             #
7264 #                                                                             #
7265 #                                                                             #
7266 #                                                                             #
7267 ###############################################################################
7268 #
7269 #
7270 void
7271 Mogrify(ref,...)
7272   Image::Magick ref=NO_INIT
7273   ALIAS:
7274     Comment            =   1
7275     CommentImage       =   2
7276     Label              =   3
7277     LabelImage         =   4
7278     AddNoise           =   5
7279     AddNoiseImage      =   6
7280     Colorize           =   7
7281     ColorizeImage      =   8
7282     Border             =   9
7283     BorderImage        =  10
7284     Blur               =  11
7285     BlurImage          =  12
7286     Chop               =  13
7287     ChopImage          =  14
7288     Crop               =  15
7289     CropImage          =  16
7290     Despeckle          =  17
7291     DespeckleImage     =  18
7292     Edge               =  19
7293     EdgeImage          =  20
7294     Emboss             =  21
7295     EmbossImage        =  22
7296     Enhance            =  23
7297     EnhanceImage       =  24
7298     Flip               =  25
7299     FlipImage          =  26
7300     Flop               =  27
7301     FlopImage          =  28
7302     Frame              =  29
7303     FrameImage         =  30
7304     Implode            =  31
7305     ImplodeImage       =  32
7306     Magnify            =  33
7307     MagnifyImage       =  34
7308     MedianFilter       =  35
7309     MedianConvolveImage  =  36
7310     Minify             =  37
7311     MinifyImage        =  38
7312     OilPaint           =  39
7313     OilPaintImage      =  40
7314     ReduceNoise        =  41
7315     ReduceNoiseImage   =  42
7316     Roll               =  43
7317     RollImage          =  44
7318     Rotate             =  45
7319     RotateImage        =  46
7320     Sample             =  47
7321     SampleImage        =  48
7322     Scale              =  49
7323     ScaleImage         =  50
7324     Shade              =  51
7325     ShadeImage         =  52
7326     Sharpen            =  53
7327     SharpenImage       =  54
7328     Shear              =  55
7329     ShearImage         =  56
7330     Spread             =  57
7331     SpreadImage        =  58
7332     Swirl              =  59
7333     SwirlImage         =  60
7334     Resize             =  61
7335     ResizeImage        =  62
7336     Zoom               =  63
7337     ZoomImage          =  64
7338     Annotate           =  65
7339     AnnotateImage      =  66
7340     ColorFloodfill     =  67
7341     ColorFloodfillImage=  68
7342     Composite          =  69
7343     CompositeImage     =  70
7344     Contrast           =  71
7345     ContrastImage      =  72
7346     CycleColormap      =  73
7347     CycleColormapImage =  74
7348     Draw               =  75
7349     DrawImage          =  76
7350     Equalize           =  77
7351     EqualizeImage      =  78
7352     Gamma              =  79
7353     GammaImage         =  80
7354     Map                =  81
7355     MapImage           =  82
7356     MatteFloodfill     =  83
7357     MatteFloodfillImage=  84
7358     Modulate           =  85
7359     ModulateImage      =  86
7360     Negate             =  87
7361     NegateImage        =  88
7362     Normalize          =  89
7363     NormalizeImage     =  90
7364     NumberColors       =  91
7365     NumberColorsImage  =  92
7366     Opaque             =  93
7367     OpaqueImage        =  94
7368     Quantize           =  95
7369     QuantizeImage      =  96
7370     Raise              =  97
7371     RaiseImage         =  98
7372     Segment            =  99
7373     SegmentImage       = 100
7374     Signature          = 101
7375     SignatureImage     = 102
7376     Solarize           = 103
7377     SolarizeImage      = 104
7378     Sync               = 105
7379     SyncImage          = 106
7380     Texture            = 107
7381     TextureImage       = 108
7382     Evaluate           = 109
7383     EvaluateImage      = 110
7384     Transparent        = 111
7385     TransparentImage   = 112
7386     Threshold          = 113
7387     ThresholdImage     = 114
7388     Charcoal           = 115
7389     CharcoalImage      = 116
7390     Trim               = 117
7391     TrimImage          = 118
7392     Wave               = 119
7393     WaveImage          = 120
7394     Separate           = 121
7395     SeparateImage      = 122
7396     Stereo             = 125
7397     StereoImage        = 126
7398     Stegano            = 127
7399     SteganoImage       = 128
7400     Deconstruct        = 129
7401     DeconstructImage   = 130
7402     GaussianBlur       = 131
7403     GaussianBlurImage  = 132
7404     Convolve           = 133
7405     ConvolveImage      = 134
7406     Profile            = 135
7407     ProfileImage       = 136
7408     UnsharpMask        = 137
7409     UnsharpMaskImage   = 138
7410     MotionBlur         = 139
7411     MotionBlurImage    = 140
7412     OrderedDither      = 141
7413     OrderedDitherImage = 142
7414     Shave              = 143
7415     ShaveImage         = 144
7416     Level              = 145
7417     LevelImage         = 146
7418     Clip               = 147
7419     ClipImage          = 148
7420     AffineTransform    = 149
7421     AffineTransformImage = 150
7422     Difference         = 151
7423     DifferenceImage    = 152
7424     AdaptiveThreshold  = 153
7425     AdaptiveThresholdImage = 154
7426     Resample           = 155
7427     ResampleImage      = 156
7428     Describe           = 157
7429     DescribeImage      = 158
7430     BlackThreshold     = 159
7431     BlackThresholdImage= 160
7432     WhiteThreshold     = 161
7433     WhiteThresholdImage= 162
7434     RotationalBlur     = 163
7435     RotationalBlurImage= 164
7436     Thumbnail          = 165
7437     ThumbnailImage     = 166
7438     Strip              = 167
7439     StripImage         = 168
7440     Tint               = 169
7441     TintImage          = 170
7442     Channel            = 171
7443     ChannelImage       = 172
7444     Splice             = 173
7445     SpliceImage        = 174
7446     Posterize          = 175
7447     PosterizeImage     = 176
7448     Shadow             = 177
7449     ShadowImage        = 178
7450     Identify           = 179
7451     IdentifyImage      = 180
7452     SepiaTone          = 181
7453     SepiaToneImage     = 182
7454     SigmoidalContrast  = 183
7455     SigmoidalContrastImage = 184
7456     Extent             = 185
7457     ExtentImage        = 186
7458     Vignette           = 187
7459     VignetteImage      = 188
7460     ContrastStretch    = 189
7461     ContrastStretchImage = 190
7462     Sans0              = 191
7463     Sans0Image         = 192
7464     Sans1              = 193
7465     Sans1Image         = 194
7466     AdaptiveSharpen    = 195
7467     AdaptiveSharpenImage = 196
7468     Transpose          = 197
7469     TransposeImage     = 198
7470     Transverse         = 199
7471     TransverseImage    = 200
7472     AutoOrient         = 201
7473     AutoOrientImage    = 202
7474     AdaptiveBlur       = 203
7475     AdaptiveBlurImage  = 204
7476     Sketch             = 205
7477     SketchImage        = 206
7478     UniqueColors       = 207
7479     UniqueColorsImage  = 208
7480     AdaptiveResize     = 209
7481     AdaptiveResizeImage= 210
7482     ClipMask           = 211
7483     ClipMaskImage      = 212
7484     LinearStretch      = 213
7485     LinearStretchImage = 214
7486     ColorMatrix        = 215
7487     ColorMatrixImage   = 216
7488     Mask               = 217
7489     MaskImage          = 218
7490     Polaroid           = 219
7491     PolaroidImage      = 220
7492     FloodfillPaint     = 221
7493     FloodfillPaintImage= 222
7494     Distort            = 223
7495     DistortImage       = 224
7496     Clut               = 225
7497     ClutImage          = 226
7498     LiquidRescale      = 227
7499     LiquidRescaleImage = 228
7500     Encipher           = 229
7501     EncipherImage      = 230
7502     Decipher           = 231
7503     DecipherImage      = 232
7504     Deskew             = 233
7505     DeskewImage        = 234
7506     Remap              = 235
7507     RemapImage         = 236
7508     SparseColor        = 237
7509     SparseColorImage   = 238
7510     Function           = 239
7511     FunctionImage      = 240
7512     SelectiveBlur      = 241
7513     SelectiveBlurImage = 242
7514     HaldClut           = 243
7515     HaldClutImage      = 244
7516     BlueShift          = 245
7517     BlueShiftImage     = 246
7518     ForwardFourierTransform  = 247
7519     ForwardFourierTransformImage = 248
7520     InverseFourierTransform = 249
7521     InverseFourierTransformImage = 250
7522     ColorDecisionList  = 251
7523     ColorDecisionListImage = 252
7524     AutoGamma          = 253
7525     AutoGammaImage     = 254
7526     AutoLevel          = 255
7527     AutoLevelImage     = 256
7528     LevelColors        = 257
7529     LevelImageColors   = 258
7530     Clamp              = 259
7531     ClampImage         = 260
7532     BrightnessContrast = 261
7533     BrightnessContrastImage = 262
7534     Morphology         = 263
7535     MorphologyImage    = 264
7536     Color              = 265
7537     ColorImage         = 266
7538     Mode               = 267
7539     ModeImage          = 268
7540     Statistic          = 269
7541     StatisticImage     = 270
7542     Perceptible        = 271
7543     PerceptibleImage   = 272
7544     Poly               = 273
7545     PolyImage          = 274
7546     Grayscale          = 275
7547     GrayscaleImage     = 276
7548     CannyEdge          = 278
7549     CannyEdgeImage     = 279
7550     HoughLine          = 280
7551     HoughLineImage     = 281
7552     MeanShift          = 282
7553     MeanShiftImage     = 283
7554     Kuwahara           = 284
7555     KuwaharaImage      = 285
7556     ConnectedComponent = 286
7557     ConnectedComponentImage = 287
7558     CopyPixels         = 288
7559     CopyImagePixels    = 289
7560     MogrifyRegion      = 666
7561   PPCODE:
7562   {
7563     AffineMatrix
7564       affine,
7565       current;
7566
7567     char
7568       attribute_flag[MaxArguments],
7569       message[MagickPathExtent];
7570
7571     ChannelType
7572       channel,
7573       channel_mask;
7574
7575     CompositeOperator
7576       compose;
7577
7578     const char
7579       *attribute,
7580       *value;
7581
7582     double
7583       angle;
7584
7585     ExceptionInfo
7586       *exception;
7587
7588     GeometryInfo
7589       geometry_info;
7590
7591     Image
7592       *image,
7593       *next,
7594       *region_image;
7595
7596     MagickBooleanType
7597       status;
7598
7599     MagickStatusType
7600       flags;
7601
7602     PixelInfo
7603       fill_color;
7604
7605     RectangleInfo
7606       geometry,
7607       region_info;
7608
7609     register ssize_t
7610       i;
7611
7612     ssize_t
7613       base,
7614       j,
7615       number_images;
7616
7617     struct Methods
7618       *rp;
7619
7620     struct PackageInfo
7621       *info;
7622
7623     SV
7624       *perl_exception,
7625       **pv,
7626       *reference,
7627       **reference_vector;
7628
7629     struct ArgumentList
7630       argument_list[MaxArguments];
7631
7632     PERL_UNUSED_VAR(ref);
7633     PERL_UNUSED_VAR(ix);
7634     exception=AcquireExceptionInfo();
7635     perl_exception=newSVpv("",0);
7636     reference_vector=NULL;
7637     region_image=NULL;
7638     number_images=0;
7639     base=2;
7640     if (sv_isobject(ST(0)) == 0)
7641       {
7642         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7643           PackageName);
7644         goto PerlException;
7645       }
7646     reference=SvRV(ST(0));
7647     region_info.width=0;
7648     region_info.height=0;
7649     region_info.x=0;
7650     region_info.y=0;
7651     region_image=(Image *) NULL;
7652     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7653     if (ix && (ix != 666))
7654       {
7655         /*
7656           Called as Method(...)
7657         */
7658         ix=(ix+1)/2;
7659         rp=(&Methods[ix-1]);
7660         attribute=rp->name;
7661       }
7662     else
7663       {
7664         /*
7665           Called as Mogrify("Method",...)
7666         */
7667         attribute=(char *) SvPV(ST(1),na);
7668         if (ix)
7669           {
7670             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7671             attribute=(char *) SvPV(ST(2),na);
7672             base++;
7673           }
7674         for (rp=Methods; ; rp++)
7675         {
7676           if (rp >= EndOf(Methods))
7677             {
7678               ThrowPerlException(exception,OptionError,
7679                 "UnrecognizedPerlMagickMethod",attribute);
7680               goto PerlException;
7681             }
7682           if (strEQcase(attribute,rp->name))
7683             break;
7684         }
7685         ix=rp-Methods+1;
7686         base++;
7687       }
7688     if (image == (Image *) NULL)
7689       {
7690         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7691         goto PerlException;
7692       }
7693     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7694     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7695     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7696     {
7697       Arguments
7698         *pp,
7699         *qq;
7700
7701       ssize_t
7702         ssize_test;
7703
7704       struct ArgumentList
7705         *al;
7706
7707       SV
7708         *sv;
7709
7710       sv=NULL;
7711       ssize_test=0;
7712       pp=(Arguments *) NULL;
7713       qq=rp->arguments;
7714       if (i == items)
7715         {
7716           pp=rp->arguments,
7717           sv=ST(i-1);
7718         }
7719       else
7720         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7721         {
7722           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7723             break;
7724           if (strEQcase(attribute,qq->method) > ssize_test)
7725             {
7726               pp=qq;
7727               ssize_test=strEQcase(attribute,qq->method);
7728             }
7729         }
7730       if (pp == (Arguments *) NULL)
7731         {
7732           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7733             attribute);
7734           goto continue_outer_loop;
7735         }
7736       al=(&argument_list[pp-rp->arguments]);
7737       switch (pp->type)
7738       {
7739         case ArrayReference:
7740         {
7741           if (SvTYPE(sv) != SVt_RV)
7742             {
7743               (void) FormatLocaleString(message,MagickPathExtent,
7744                 "invalid %.60s value",pp->method);
7745               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7746               goto continue_outer_loop;
7747             }
7748           al->array_reference=SvRV(sv);
7749           break;
7750         }
7751         case RealReference:
7752         {
7753           al->real_reference=SvNV(sv);
7754           break;
7755         }
7756         case FileReference:
7757         {
7758           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7759           break;
7760         }
7761         case ImageReference:
7762         {
7763           if (!sv_isobject(sv) ||
7764               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7765                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7766             {
7767               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7768                 PackageName);
7769               goto PerlException;
7770             }
7771           break;
7772         }
7773         case IntegerReference:
7774         {
7775           al->integer_reference=SvIV(sv);
7776           break;
7777         }
7778         case StringReference:
7779         {
7780           al->string_reference=(char *) SvPV(sv,al->length);
7781           if (sv_isobject(sv))
7782             al->image_reference=SetupList(aTHX_ SvRV(sv),
7783               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7784           break;
7785         }
7786         default:
7787         {
7788           /*
7789             Is a string; look up name.
7790           */
7791           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7792             {
7793               al->string_reference=(char *) SvPV(sv,al->length);
7794               al->integer_reference=(-1);
7795               break;
7796             }
7797           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7798             MagickFalse,SvPV(sv,na));
7799           if (pp->type == MagickChannelOptions)
7800             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7801           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7802             {
7803               (void) FormatLocaleString(message,MagickPathExtent,
7804                 "invalid %.60s value",pp->method);
7805               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7806               goto continue_outer_loop;
7807             }
7808           break;
7809         }
7810       }
7811       attribute_flag[pp-rp->arguments]++;
7812       continue_outer_loop: ;
7813     }
7814     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7815     pv=reference_vector;
7816     SetGeometryInfo(&geometry_info);
7817     channel=DefaultChannels;
7818     for (next=image; next; next=next->next)
7819     {
7820       image=next;
7821       SetGeometry(image,&geometry);
7822       if ((region_info.width*region_info.height) != 0)
7823         {
7824           region_image=image;
7825           image=CropImage(image,&region_info,exception);
7826         }
7827       switch (ix)
7828       {
7829         default:
7830         {
7831           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7832           ThrowPerlException(exception,OptionError,
7833             "UnrecognizedPerlMagickMethod",message);
7834           goto PerlException;
7835         }
7836         case 1:  /* Comment */
7837         {
7838           if (attribute_flag[0] == 0)
7839             argument_list[0].string_reference=(char *) NULL;
7840           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7841             info ? info->image_info : (ImageInfo *) NULL,image,
7842             argument_list[0].string_reference,exception),exception);
7843           break;
7844         }
7845         case 2:  /* Label */
7846         {
7847           if (attribute_flag[0] == 0)
7848             argument_list[0].string_reference=(char *) NULL;
7849           (void) SetImageProperty(image,"label",InterpretImageProperties(
7850             info ? info->image_info : (ImageInfo *) NULL,image,
7851             argument_list[0].string_reference,exception),exception);
7852           break;
7853         }
7854         case 3:  /* AddNoise */
7855         {
7856           double
7857             attenuate;
7858
7859           if (attribute_flag[0] == 0)
7860             argument_list[0].integer_reference=UniformNoise;
7861           attenuate=1.0;
7862           if (attribute_flag[1] != 0)
7863             attenuate=argument_list[1].real_reference;
7864           if (attribute_flag[2] != 0)
7865             channel=(ChannelType) argument_list[2].integer_reference;
7866           channel_mask=SetImageChannelMask(image,channel);
7867           image=AddNoiseImage(image,(NoiseType)
7868             argument_list[0].integer_reference,attenuate,exception);
7869           if (image != (Image *) NULL)
7870             (void) SetImageChannelMask(image,channel_mask);
7871           break;
7872         }
7873         case 4:  /* Colorize */
7874         {
7875           PixelInfo
7876             target;
7877
7878           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7879             0,0,&target,exception);
7880           if (attribute_flag[0] != 0)
7881             (void) QueryColorCompliance(argument_list[0].string_reference,
7882               AllCompliance,&target,exception);
7883           if (attribute_flag[1] == 0)
7884             argument_list[1].string_reference="100%";
7885           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7886             exception);
7887           break;
7888         }
7889         case 5:  /* Border */
7890         {
7891           CompositeOperator
7892             compose;
7893
7894           geometry.width=0;
7895           geometry.height=0;
7896           if (attribute_flag[0] != 0)
7897             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7898               &geometry,exception);
7899           if (attribute_flag[1] != 0)
7900             geometry.width=argument_list[1].integer_reference;
7901           if (attribute_flag[2] != 0)
7902             geometry.height=argument_list[2].integer_reference;
7903           if (attribute_flag[3] != 0)
7904             QueryColorCompliance(argument_list[3].string_reference,
7905               AllCompliance,&image->border_color,exception);
7906           if (attribute_flag[4] != 0)
7907             QueryColorCompliance(argument_list[4].string_reference,
7908               AllCompliance,&image->border_color,exception);
7909           if (attribute_flag[5] != 0)
7910             QueryColorCompliance(argument_list[5].string_reference,
7911               AllCompliance,&image->border_color,exception);
7912           compose=image->compose;
7913           if (attribute_flag[6] != 0)
7914             compose=(CompositeOperator) argument_list[6].integer_reference;
7915           image=BorderImage(image,&geometry,compose,exception);
7916           break;
7917         }
7918         case 6:  /* Blur */
7919         {
7920           if (attribute_flag[0] != 0)
7921             {
7922               flags=ParseGeometry(argument_list[0].string_reference,
7923                 &geometry_info);
7924               if ((flags & SigmaValue) == 0)
7925                 geometry_info.sigma=1.0;
7926             }
7927           if (attribute_flag[1] != 0)
7928             geometry_info.rho=argument_list[1].real_reference;
7929           if (attribute_flag[2] != 0)
7930             geometry_info.sigma=argument_list[2].real_reference;
7931           if (attribute_flag[3] != 0)
7932             channel=(ChannelType) argument_list[3].integer_reference;
7933           channel_mask=SetImageChannelMask(image,channel);
7934           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7935             exception);
7936           if (image != (Image *) NULL)
7937             (void) SetImageChannelMask(image,channel_mask);
7938           break;
7939         }
7940         case 7:  /* Chop */
7941         {
7942           if (attribute_flag[5] != 0)
7943             image->gravity=(GravityType) argument_list[5].integer_reference;
7944           if (attribute_flag[0] != 0)
7945             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7946               &geometry,exception);
7947           if (attribute_flag[1] != 0)
7948             geometry.width=argument_list[1].integer_reference;
7949           if (attribute_flag[2] != 0)
7950             geometry.height=argument_list[2].integer_reference;
7951           if (attribute_flag[3] != 0)
7952             geometry.x=argument_list[3].integer_reference;
7953           if (attribute_flag[4] != 0)
7954             geometry.y=argument_list[4].integer_reference;
7955           image=ChopImage(image,&geometry,exception);
7956           break;
7957         }
7958         case 8:  /* Crop */
7959         {
7960           if (attribute_flag[6] != 0)
7961             image->gravity=(GravityType) argument_list[6].integer_reference;
7962           if (attribute_flag[0] != 0)
7963             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7964               &geometry,exception);
7965           if (attribute_flag[1] != 0)
7966             geometry.width=argument_list[1].integer_reference;
7967           if (attribute_flag[2] != 0)
7968             geometry.height=argument_list[2].integer_reference;
7969           if (attribute_flag[3] != 0)
7970             geometry.x=argument_list[3].integer_reference;
7971           if (attribute_flag[4] != 0)
7972             geometry.y=argument_list[4].integer_reference;
7973           if (attribute_flag[5] != 0)
7974             image->fuzz=StringToDoubleInterval(
7975               argument_list[5].string_reference,(double) QuantumRange+1.0);
7976           image=CropImage(image,&geometry,exception);
7977           break;
7978         }
7979         case 9:  /* Despeckle */
7980         {
7981           image=DespeckleImage(image,exception);
7982           break;
7983         }
7984         case 10:  /* Edge */
7985         {
7986           if (attribute_flag[0] != 0)
7987             geometry_info.rho=argument_list[0].real_reference;
7988           image=EdgeImage(image,geometry_info.rho,exception);
7989           break;
7990         }
7991         case 11:  /* Emboss */
7992         {
7993           if (attribute_flag[0] != 0)
7994             {
7995               flags=ParseGeometry(argument_list[0].string_reference,
7996                 &geometry_info);
7997               if ((flags & SigmaValue) == 0)
7998                 geometry_info.sigma=1.0;
7999             }
8000           if (attribute_flag[1] != 0)
8001             geometry_info.rho=argument_list[1].real_reference;
8002           if (attribute_flag[2] != 0)
8003             geometry_info.sigma=argument_list[2].real_reference;
8004           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8005             exception);
8006           break;
8007         }
8008         case 12:  /* Enhance */
8009         {
8010           image=EnhanceImage(image,exception);
8011           break;
8012         }
8013         case 13:  /* Flip */
8014         {
8015           image=FlipImage(image,exception);
8016           break;
8017         }
8018         case 14:  /* Flop */
8019         {
8020           image=FlopImage(image,exception);
8021           break;
8022         }
8023         case 15:  /* Frame */
8024         {
8025           CompositeOperator
8026             compose;
8027
8028           FrameInfo
8029             frame_info;
8030
8031           if (attribute_flag[0] != 0)
8032             {
8033               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8034                 &geometry,exception);
8035               frame_info.width=geometry.width;
8036               frame_info.height=geometry.height;
8037               frame_info.outer_bevel=geometry.x;
8038               frame_info.inner_bevel=geometry.y;
8039             }
8040           if (attribute_flag[1] != 0)
8041             frame_info.width=argument_list[1].integer_reference;
8042           if (attribute_flag[2] != 0)
8043             frame_info.height=argument_list[2].integer_reference;
8044           if (attribute_flag[3] != 0)
8045             frame_info.inner_bevel=argument_list[3].integer_reference;
8046           if (attribute_flag[4] != 0)
8047             frame_info.outer_bevel=argument_list[4].integer_reference;
8048           if (attribute_flag[5] != 0)
8049             QueryColorCompliance(argument_list[5].string_reference,
8050               AllCompliance,&fill_color,exception);
8051           if (attribute_flag[6] != 0)
8052             QueryColorCompliance(argument_list[6].string_reference,
8053               AllCompliance,&fill_color,exception);
8054           frame_info.x=(ssize_t) frame_info.width;
8055           frame_info.y=(ssize_t) frame_info.height;
8056           frame_info.width=image->columns+2*frame_info.x;
8057           frame_info.height=image->rows+2*frame_info.y;
8058           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8059             image->matte_color=fill_color;
8060           compose=image->compose;
8061           if (attribute_flag[7] != 0)
8062             compose=(CompositeOperator) argument_list[7].integer_reference;
8063           image=FrameImage(image,&frame_info,compose,exception);
8064           break;
8065         }
8066         case 16:  /* Implode */
8067         {
8068           PixelInterpolateMethod
8069             method;
8070
8071           if (attribute_flag[0] == 0)
8072             argument_list[0].real_reference=0.5;
8073           method=UndefinedInterpolatePixel;
8074           if (attribute_flag[1] != 0)
8075             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8076           image=ImplodeImage(image,argument_list[0].real_reference,
8077             method,exception);
8078           break;
8079         }
8080         case 17:  /* Magnify */
8081         {
8082           image=MagnifyImage(image,exception);
8083           break;
8084         }
8085         case 18:  /* MedianFilter */
8086         {
8087           if (attribute_flag[0] != 0)
8088             {
8089               flags=ParseGeometry(argument_list[0].string_reference,
8090                 &geometry_info);
8091               if ((flags & SigmaValue) == 0)
8092                 geometry_info.sigma=geometry_info.rho;
8093             }
8094           if (attribute_flag[1] != 0)
8095             geometry_info.rho=argument_list[1].real_reference;
8096           if (attribute_flag[2] != 0)
8097             geometry_info.sigma=argument_list[2].real_reference;
8098           if (attribute_flag[3] != 0)
8099             channel=(ChannelType) argument_list[3].integer_reference;
8100           channel_mask=SetImageChannelMask(image,channel);
8101           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8102             (size_t) geometry_info.sigma,exception);
8103           if (image != (Image *) NULL)
8104             (void) SetImageChannelMask(image,channel_mask);
8105           break;
8106         }
8107         case 19:  /* Minify */
8108         {
8109           image=MinifyImage(image,exception);
8110           break;
8111         }
8112         case 20:  /* OilPaint */
8113         {
8114           if (attribute_flag[0] == 0)
8115             argument_list[0].real_reference=0.0;
8116           if (attribute_flag[1] == 0)
8117             argument_list[1].real_reference=1.0;
8118           image=OilPaintImage(image,argument_list[0].real_reference,
8119             argument_list[1].real_reference,exception);
8120           break;
8121         }
8122         case 21:  /* ReduceNoise */
8123         {
8124           if (attribute_flag[0] != 0)
8125             {
8126               flags=ParseGeometry(argument_list[0].string_reference,
8127                 &geometry_info);
8128               if ((flags & SigmaValue) == 0)
8129                 geometry_info.sigma=1.0;
8130             }
8131           if (attribute_flag[1] != 0)
8132             geometry_info.rho=argument_list[1].real_reference;
8133           if (attribute_flag[2] != 0)
8134             geometry_info.sigma=argument_list[2].real_reference;
8135           if (attribute_flag[3] != 0)
8136             channel=(ChannelType) argument_list[3].integer_reference;
8137           channel_mask=SetImageChannelMask(image,channel);
8138           image=StatisticImage(image,NonpeakStatistic,(size_t)
8139             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8140           if (image != (Image *) NULL)
8141             (void) SetImageChannelMask(image,channel_mask);
8142           break;
8143         }
8144         case 22:  /* Roll */
8145         {
8146           if (attribute_flag[0] != 0)
8147             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8148               &geometry,exception);
8149           if (attribute_flag[1] != 0)
8150             geometry.x=argument_list[1].integer_reference;
8151           if (attribute_flag[2] != 0)
8152             geometry.y=argument_list[2].integer_reference;
8153           image=RollImage(image,geometry.x,geometry.y,exception);
8154           break;
8155         }
8156         case 23:  /* Rotate */
8157         {
8158           if (attribute_flag[0] == 0)
8159             argument_list[0].real_reference=90.0;
8160           if (attribute_flag[1] != 0)
8161             {
8162               QueryColorCompliance(argument_list[1].string_reference,
8163                 AllCompliance,&image->background_color,exception);
8164               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8165                   (image->alpha_trait == UndefinedPixelTrait))
8166                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8167             }
8168           image=RotateImage(image,argument_list[0].real_reference,exception);
8169           break;
8170         }
8171         case 24:  /* Sample */
8172         {
8173           if (attribute_flag[0] != 0)
8174             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8175               &geometry,exception);
8176           if (attribute_flag[1] != 0)
8177             geometry.width=argument_list[1].integer_reference;
8178           if (attribute_flag[2] != 0)
8179             geometry.height=argument_list[2].integer_reference;
8180           image=SampleImage(image,geometry.width,geometry.height,exception);
8181           break;
8182         }
8183         case 25:  /* Scale */
8184         {
8185           if (attribute_flag[0] != 0)
8186             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8187               &geometry,exception);
8188           if (attribute_flag[1] != 0)
8189             geometry.width=argument_list[1].integer_reference;
8190           if (attribute_flag[2] != 0)
8191             geometry.height=argument_list[2].integer_reference;
8192           image=ScaleImage(image,geometry.width,geometry.height,exception);
8193           break;
8194         }
8195         case 26:  /* Shade */
8196         {
8197           if (attribute_flag[0] != 0)
8198             {
8199               flags=ParseGeometry(argument_list[0].string_reference,
8200                 &geometry_info);
8201               if ((flags & SigmaValue) == 0)
8202                 geometry_info.sigma=0.0;
8203             }
8204           if (attribute_flag[1] != 0)
8205             geometry_info.rho=argument_list[1].real_reference;
8206           if (attribute_flag[2] != 0)
8207             geometry_info.sigma=argument_list[2].real_reference;
8208           image=ShadeImage(image,
8209             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8210             geometry_info.rho,geometry_info.sigma,exception);
8211           break;
8212         }
8213         case 27:  /* Sharpen */
8214         {
8215           if (attribute_flag[0] != 0)
8216             {
8217               flags=ParseGeometry(argument_list[0].string_reference,
8218                 &geometry_info);
8219               if ((flags & SigmaValue) == 0)
8220                 geometry_info.sigma=1.0;
8221             }
8222           if (attribute_flag[1] != 0)
8223             geometry_info.rho=argument_list[1].real_reference;
8224           if (attribute_flag[2] != 0)
8225             geometry_info.sigma=argument_list[2].real_reference;
8226           if (attribute_flag[3] != 0)
8227             channel=(ChannelType) argument_list[3].integer_reference;
8228           channel_mask=SetImageChannelMask(image,channel);
8229           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8230             exception);
8231           if (image != (Image *) NULL)
8232             (void) SetImageChannelMask(image,channel_mask);
8233           break;
8234         }
8235         case 28:  /* Shear */
8236         {
8237           if (attribute_flag[0] != 0)
8238             {
8239               flags=ParseGeometry(argument_list[0].string_reference,
8240                 &geometry_info);
8241               if ((flags & SigmaValue) == 0)
8242                 geometry_info.sigma=geometry_info.rho;
8243             }
8244           if (attribute_flag[1] != 0)
8245             geometry_info.rho=argument_list[1].real_reference;
8246           if (attribute_flag[2] != 0)
8247             geometry_info.sigma=argument_list[2].real_reference;
8248           if (attribute_flag[3] != 0)
8249             QueryColorCompliance(argument_list[3].string_reference,
8250               AllCompliance,&image->background_color,exception);
8251           if (attribute_flag[4] != 0)
8252             QueryColorCompliance(argument_list[4].string_reference,
8253               AllCompliance,&image->background_color,exception);
8254           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8255             exception);
8256           break;
8257         }
8258         case 29:  /* Spread */
8259         {
8260           PixelInterpolateMethod
8261             method;
8262
8263           if (attribute_flag[0] == 0)
8264             argument_list[0].real_reference=1.0;
8265           method=UndefinedInterpolatePixel;
8266           if (attribute_flag[1] != 0)
8267             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8268           image=SpreadImage(image,argument_list[0].real_reference,method,
8269             exception);
8270           break;
8271         }
8272         case 30:  /* Swirl */
8273         {
8274           PixelInterpolateMethod
8275             method;
8276
8277           if (attribute_flag[0] == 0)
8278             argument_list[0].real_reference=50.0;
8279           method=UndefinedInterpolatePixel;
8280           if (attribute_flag[1] != 0)
8281             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8282           image=SwirlImage(image,argument_list[0].real_reference,
8283             method,exception);
8284           break;
8285         }
8286         case 31:  /* Resize */
8287         case 32:  /* Zoom */
8288         {
8289           if (attribute_flag[0] != 0)
8290             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8291               &geometry,exception);
8292           if (attribute_flag[1] != 0)
8293             geometry.width=argument_list[1].integer_reference;
8294           if (attribute_flag[2] != 0)
8295             geometry.height=argument_list[2].integer_reference;
8296           if (attribute_flag[3] == 0)
8297             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8298           if (attribute_flag[4] != 0)
8299             SetImageArtifact(image,"filter:support",
8300               argument_list[4].string_reference);
8301           image=ResizeImage(image,geometry.width,geometry.height,
8302             (FilterTypes) argument_list[3].integer_reference,
8303             exception);
8304           break;
8305         }
8306         case 33:  /* Annotate */
8307         {
8308           DrawInfo
8309             *draw_info;
8310
8311           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8312             (DrawInfo *) NULL);
8313           if (attribute_flag[0] != 0)
8314             {
8315               char
8316                 *text;
8317
8318               text=InterpretImageProperties(info ? info->image_info :
8319                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8320                 exception);
8321               (void) CloneString(&draw_info->text,text);
8322               text=DestroyString(text);
8323             }
8324           if (attribute_flag[1] != 0)
8325             (void) CloneString(&draw_info->font,
8326               argument_list[1].string_reference);
8327           if (attribute_flag[2] != 0)
8328             draw_info->pointsize=argument_list[2].real_reference;
8329           if (attribute_flag[3] != 0)
8330             (void) CloneString(&draw_info->density,
8331               argument_list[3].string_reference);
8332           if (attribute_flag[4] != 0)
8333             (void) QueryColorCompliance(argument_list[4].string_reference,
8334               AllCompliance,&draw_info->undercolor,exception);
8335           if (attribute_flag[5] != 0)
8336             {
8337               (void) QueryColorCompliance(argument_list[5].string_reference,
8338                 AllCompliance,&draw_info->stroke,exception);
8339               if (argument_list[5].image_reference != (Image *) NULL)
8340                 draw_info->stroke_pattern=CloneImage(
8341                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8342             }
8343           if (attribute_flag[6] != 0)
8344             {
8345               (void) QueryColorCompliance(argument_list[6].string_reference,
8346                 AllCompliance,&draw_info->fill,exception);
8347               if (argument_list[6].image_reference != (Image *) NULL)
8348                 draw_info->fill_pattern=CloneImage(
8349                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8350             }
8351           if (attribute_flag[7] != 0)
8352             {
8353               (void) CloneString(&draw_info->geometry,
8354                 argument_list[7].string_reference);
8355               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8356                 &geometry,exception);
8357               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8358                 geometry_info.sigma=geometry_info.xi;
8359             }
8360           if (attribute_flag[8] != 0)
8361             (void) QueryColorCompliance(argument_list[8].string_reference,
8362               AllCompliance,&draw_info->fill,exception);
8363           if (attribute_flag[11] != 0)
8364             draw_info->gravity=(GravityType)
8365               argument_list[11].integer_reference;
8366           if (attribute_flag[25] != 0)
8367             {
8368               AV
8369                 *av;
8370
8371               av=(AV *) argument_list[25].array_reference;
8372               if ((av_len(av) != 3) && (av_len(av) != 5))
8373                 {
8374                   ThrowPerlException(exception,OptionError,
8375                     "affine matrix must have 4 or 6 elements",PackageName);
8376                   goto PerlException;
8377                 }
8378               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8379               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8380               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8381               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8382               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8383                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8384                 {
8385                   ThrowPerlException(exception,OptionError,
8386                     "affine matrix is singular",PackageName);
8387                    goto PerlException;
8388                 }
8389               if (av_len(av) == 5)
8390                 {
8391                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8392                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8393                 }
8394             }
8395           for (j=12; j < 17; j++)
8396           {
8397             if (attribute_flag[j] == 0)
8398               continue;
8399             value=argument_list[j].string_reference;
8400             angle=argument_list[j].real_reference;
8401             current=draw_info->affine;
8402             GetAffineMatrix(&affine);
8403             switch (j)
8404             {
8405               case 12:
8406               {
8407                 /*
8408                   Translate.
8409                 */
8410                 flags=ParseGeometry(value,&geometry_info);
8411                 affine.tx=geometry_info.xi;
8412                 affine.ty=geometry_info.psi;
8413                 if ((flags & PsiValue) == 0)
8414                   affine.ty=affine.tx;
8415                 break;
8416               }
8417               case 13:
8418               {
8419                 /*
8420                   Scale.
8421                 */
8422                 flags=ParseGeometry(value,&geometry_info);
8423                 affine.sx=geometry_info.rho;
8424                 affine.sy=geometry_info.sigma;
8425                 if ((flags & SigmaValue) == 0)
8426                   affine.sy=affine.sx;
8427                 break;
8428               }
8429               case 14:
8430               {
8431                 /*
8432                   Rotate.
8433                 */
8434                 if (angle == 0.0)
8435                   break;
8436                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8437                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8438                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8439                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8440                 break;
8441               }
8442               case 15:
8443               {
8444                 /*
8445                   SkewX.
8446                 */
8447                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8448                 break;
8449               }
8450               case 16:
8451               {
8452                 /*
8453                   SkewY.
8454                 */
8455                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8456                 break;
8457               }
8458             }
8459             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8460             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8461             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8462             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8463             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8464               current.tx;
8465             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8466               current.ty;
8467           }
8468           if (attribute_flag[9] == 0)
8469             argument_list[9].real_reference=0.0;
8470           if (attribute_flag[10] == 0)
8471             argument_list[10].real_reference=0.0;
8472           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8473             {
8474               char
8475                 geometry[MagickPathExtent];
8476
8477               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8478                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8479                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8480               (void) CloneString(&draw_info->geometry,geometry);
8481             }
8482           if (attribute_flag[17] != 0)
8483             draw_info->stroke_width=argument_list[17].real_reference;
8484           if (attribute_flag[18] != 0)
8485             {
8486               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8487                 MagickTrue : MagickFalse;
8488               draw_info->stroke_antialias=draw_info->text_antialias;
8489             }
8490           if (attribute_flag[19] != 0)
8491             (void) CloneString(&draw_info->family,
8492               argument_list[19].string_reference);
8493           if (attribute_flag[20] != 0)
8494             draw_info->style=(StyleType) argument_list[20].integer_reference;
8495           if (attribute_flag[21] != 0)
8496             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8497           if (attribute_flag[22] != 0)
8498             draw_info->weight=argument_list[22].integer_reference;
8499           if (attribute_flag[23] != 0)
8500             draw_info->align=(AlignType) argument_list[23].integer_reference;
8501           if (attribute_flag[24] != 0)
8502             (void) CloneString(&draw_info->encoding,
8503               argument_list[24].string_reference);
8504           if (attribute_flag[25] != 0)
8505             draw_info->fill_pattern=CloneImage(
8506               argument_list[25].image_reference,0,0,MagickTrue,exception);
8507           if (attribute_flag[26] != 0)
8508             draw_info->fill_pattern=CloneImage(
8509               argument_list[26].image_reference,0,0,MagickTrue,exception);
8510           if (attribute_flag[27] != 0)
8511             draw_info->stroke_pattern=CloneImage(
8512               argument_list[27].image_reference,0,0,MagickTrue,exception);
8513           if (attribute_flag[29] != 0)
8514             draw_info->kerning=argument_list[29].real_reference;
8515           if (attribute_flag[30] != 0)
8516             draw_info->interline_spacing=argument_list[30].real_reference;
8517           if (attribute_flag[31] != 0)
8518             draw_info->interword_spacing=argument_list[31].real_reference;
8519           if (attribute_flag[32] != 0)
8520             draw_info->direction=(DirectionType)
8521               argument_list[32].integer_reference;
8522           (void) AnnotateImage(image,draw_info,exception);
8523           draw_info=DestroyDrawInfo(draw_info);
8524           break;
8525         }
8526         case 34:  /* ColorFloodfill */
8527         {
8528           DrawInfo
8529             *draw_info;
8530
8531           MagickBooleanType
8532             invert;
8533
8534           PixelInfo
8535             target;
8536
8537           draw_info=CloneDrawInfo(info ? info->image_info :
8538             (ImageInfo *) NULL,(DrawInfo *) NULL);
8539           if (attribute_flag[0] != 0)
8540             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8541               &geometry,exception);
8542           if (attribute_flag[1] != 0)
8543             geometry.x=argument_list[1].integer_reference;
8544           if (attribute_flag[2] != 0)
8545             geometry.y=argument_list[2].integer_reference;
8546           if (attribute_flag[3] != 0)
8547             (void) QueryColorCompliance(argument_list[3].string_reference,
8548               AllCompliance,&draw_info->fill,exception);
8549           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8550             geometry.x,geometry.y,&target,exception);
8551           invert=MagickFalse;
8552           if (attribute_flag[4] != 0)
8553             {
8554               QueryColorCompliance(argument_list[4].string_reference,
8555                 AllCompliance,&target,exception);
8556               invert=MagickTrue;
8557             }
8558           if (attribute_flag[5] != 0)
8559             image->fuzz=StringToDoubleInterval(
8560               argument_list[5].string_reference,(double) QuantumRange+1.0);
8561           if (attribute_flag[6] != 0)
8562             invert=(MagickBooleanType) argument_list[6].integer_reference;
8563           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8564             geometry.y,invert,exception);
8565           draw_info=DestroyDrawInfo(draw_info);
8566           break;
8567         }
8568         case 35:  /* Composite */
8569         {
8570           char
8571             composite_geometry[MagickPathExtent];
8572
8573           Image
8574             *composite_image,
8575             *rotate_image;
8576
8577           MagickBooleanType
8578             clip_to_self;
8579
8580           compose=OverCompositeOp;
8581           if (attribute_flag[0] != 0)
8582             composite_image=argument_list[0].image_reference;
8583           else
8584             {
8585               ThrowPerlException(exception,OptionError,
8586                 "CompositeImageRequired",PackageName);
8587               goto PerlException;
8588             }
8589           /*
8590             Parameter Handling used for BOTH normal and tiled composition.
8591           */
8592           if (attribute_flag[1] != 0) /* compose */
8593             compose=(CompositeOperator) argument_list[1].integer_reference;
8594           if (attribute_flag[6] != 0) /* opacity  */
8595             {
8596               if (compose != DissolveCompositeOp)
8597                 (void) SetImageAlpha(composite_image,(Quantum)
8598                   StringToDoubleInterval(argument_list[6].string_reference,
8599                   (double) QuantumRange+1.0),exception);
8600               else
8601                 {
8602                   CacheView
8603                     *composite_view;
8604
8605                   double
8606                     opacity;
8607
8608                   MagickBooleanType
8609                     sync;
8610
8611                   register ssize_t
8612                     x;
8613
8614                   register Quantum
8615                     *q;
8616
8617                   ssize_t
8618                     y;
8619
8620                   /*
8621                     Handle dissolve composite operator (patch by
8622                     Kevin A. McGrail).
8623                   */
8624                   (void) CloneString(&image->geometry,
8625                     argument_list[6].string_reference);
8626                   opacity=(Quantum) StringToDoubleInterval(
8627                     argument_list[6].string_reference,(double) QuantumRange+
8628                     1.0);
8629                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8630                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8631                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8632                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8633                   {
8634                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8635                       composite_image->columns,1,exception);
8636                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8637                     {
8638                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8639                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8640                           q);
8641                       q+=GetPixelChannels(composite_image);
8642                     }
8643                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8644                     if (sync == MagickFalse)
8645                       break;
8646                   }
8647                   composite_view=DestroyCacheView(composite_view);
8648                 }
8649             }
8650           if (attribute_flag[9] != 0)    /* "color=>" */
8651             QueryColorCompliance(argument_list[9].string_reference,
8652               AllCompliance,&composite_image->background_color,exception);
8653           if (attribute_flag[12] != 0) /* "interpolate=>" */
8654             image->interpolate=(PixelInterpolateMethod)
8655               argument_list[12].integer_reference;
8656           if (attribute_flag[13] != 0)   /* "args=>" */
8657             (void) SetImageArtifact(composite_image,"compose:args",
8658               argument_list[13].string_reference);
8659           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8660             (void) SetImageArtifact(composite_image,"compose:args",
8661               argument_list[14].string_reference);
8662           clip_to_self=MagickTrue;
8663           if (attribute_flag[15] != 0)
8664             clip_to_self=(MagickBooleanType)
8665               argument_list[15].integer_reference;
8666           /*
8667             Tiling Composition (with orthogonal rotate).
8668           */
8669           rotate_image=(Image *) NULL;
8670           if (attribute_flag[8] != 0)   /* "rotate=>" */
8671             {
8672                /*
8673                  Rotate image.
8674                */
8675                rotate_image=RotateImage(composite_image,
8676                  argument_list[8].real_reference,exception);
8677                if (rotate_image == (Image *) NULL)
8678                  break;
8679             }
8680           if ((attribute_flag[7] != 0) &&
8681               (argument_list[7].integer_reference != 0)) /* tile */
8682             {
8683               ssize_t
8684                 x,
8685                 y;
8686
8687               /*
8688                 Tile the composite image.
8689               */
8690              if (attribute_flag[8] != 0)   /* "tile=>" */
8691                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8692                  "false");
8693              else
8694                (void) SetImageArtifact(composite_image,
8695                  "compose:outside-overlay","false");
8696              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8697                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8698                 {
8699                   if (attribute_flag[8] != 0) /* rotate */
8700                     (void) CompositeImage(image,rotate_image,compose,
8701                       MagickTrue,x,y,exception);
8702                   else
8703                     (void) CompositeImage(image,composite_image,compose,
8704                       MagickTrue,x,y,exception);
8705                 }
8706               if (attribute_flag[8] != 0) /* rotate */
8707                 rotate_image=DestroyImage(rotate_image);
8708               break;
8709             }
8710           /*
8711             Parameter Handling used used ONLY for normal composition.
8712           */
8713           if (attribute_flag[5] != 0) /* gravity */
8714             image->gravity=(GravityType) argument_list[5].integer_reference;
8715           if (attribute_flag[2] != 0) /* geometry offset */
8716             {
8717               SetGeometry(image,&geometry);
8718               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8719                 &geometry);
8720               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8721                 &geometry);
8722             }
8723           if (attribute_flag[3] != 0) /* x offset */
8724             geometry.x=argument_list[3].integer_reference;
8725           if (attribute_flag[4] != 0) /* y offset */
8726             geometry.y=argument_list[4].integer_reference;
8727           if (attribute_flag[10] != 0) /* mask */
8728             {
8729               if ((image->compose == DisplaceCompositeOp) ||
8730                   (image->compose == DistortCompositeOp))
8731                 {
8732                   /*
8733                     Merge Y displacement into X displacement image.
8734                   */
8735                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8736                     exception);
8737                   (void) CompositeImage(composite_image,
8738                     argument_list[10].image_reference,CopyGreenCompositeOp,
8739                     MagickTrue,0,0,exception);
8740                 }
8741               else
8742                 {
8743                   Image
8744                     *mask_image;
8745
8746                   /*
8747                     Set a blending mask for the composition.
8748                   */
8749                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8750                     MagickTrue,exception);
8751                   (void) SetImageMask(composite_image,mask_image,exception);
8752                   mask_image=DestroyImage(mask_image);
8753                 }
8754             }
8755           if (attribute_flag[11] != 0) /* channel */
8756             channel=(ChannelType) argument_list[11].integer_reference;
8757           /*
8758             Composite two images (normal composition).
8759           */
8760           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8761             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8762             (double) composite_image->rows,(double) geometry.x,(double)
8763             geometry.y);
8764           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8765             exception);
8766           channel_mask=SetImageChannelMask(image,channel);
8767           if (attribute_flag[8] == 0) /* no rotate */
8768             CompositeImage(image,composite_image,compose,clip_to_self,
8769               geometry.x,geometry.y,exception);
8770           else
8771             {
8772               /*
8773                 Position adjust rotated image then composite.
8774               */
8775               geometry.x-=(ssize_t) (rotate_image->columns-
8776                 composite_image->columns)/2;
8777               geometry.y-=(ssize_t) (rotate_image->rows-
8778                 composite_image->rows)/2;
8779               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8780                 geometry.y,exception);
8781               rotate_image=DestroyImage(rotate_image);
8782             }
8783           if (attribute_flag[10] != 0) /* mask */
8784             {
8785               if ((image->compose == DisplaceCompositeOp) ||
8786                   (image->compose == DistortCompositeOp))
8787                 composite_image=DestroyImage(composite_image);
8788               else
8789                 (void) SetImageMask(image,(Image *) NULL,exception);
8790             }
8791           (void) SetImageChannelMask(image,channel_mask);
8792           break;
8793         }
8794         case 36:  /* Contrast */
8795         {
8796           if (attribute_flag[0] == 0)
8797             argument_list[0].integer_reference=0;
8798           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8799             MagickTrue : MagickFalse,exception);
8800           break;
8801         }
8802         case 37:  /* CycleColormap */
8803         {
8804           if (attribute_flag[0] == 0)
8805             argument_list[0].integer_reference=6;
8806           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8807             exception);
8808           break;
8809         }
8810         case 38:  /* Draw */
8811         {
8812           DrawInfo
8813             *draw_info;
8814
8815           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8816             (DrawInfo *) NULL);
8817           (void) CloneString(&draw_info->primitive,"point");
8818           if (attribute_flag[0] != 0)
8819             {
8820               if (argument_list[0].integer_reference < 0)
8821                 (void) CloneString(&draw_info->primitive,
8822                   argument_list[0].string_reference);
8823               else
8824                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8825                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8826             }
8827           if (attribute_flag[1] != 0)
8828             {
8829               if (LocaleCompare(draw_info->primitive,"path") == 0)
8830                 {
8831                   (void) ConcatenateString(&draw_info->primitive," '");
8832                   ConcatenateString(&draw_info->primitive,
8833                     argument_list[1].string_reference);
8834                   (void) ConcatenateString(&draw_info->primitive,"'");
8835                 }
8836               else
8837                 {
8838                   (void) ConcatenateString(&draw_info->primitive," ");
8839                   ConcatenateString(&draw_info->primitive,
8840                     argument_list[1].string_reference);
8841                 }
8842             }
8843           if (attribute_flag[2] != 0)
8844             {
8845               (void) ConcatenateString(&draw_info->primitive," ");
8846               (void) ConcatenateString(&draw_info->primitive,
8847                 CommandOptionToMnemonic(MagickMethodOptions,
8848                 argument_list[2].integer_reference));
8849             }
8850           if (attribute_flag[3] != 0)
8851             {
8852               (void) QueryColorCompliance(argument_list[3].string_reference,
8853                 AllCompliance,&draw_info->stroke,exception);
8854               if (argument_list[3].image_reference != (Image *) NULL)
8855                 draw_info->stroke_pattern=CloneImage(
8856                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8857             }
8858           if (attribute_flag[4] != 0)
8859             {
8860               (void) QueryColorCompliance(argument_list[4].string_reference,
8861                 AllCompliance,&draw_info->fill,exception);
8862               if (argument_list[4].image_reference != (Image *) NULL)
8863                 draw_info->fill_pattern=CloneImage(
8864                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8865             }
8866           if (attribute_flag[5] != 0)
8867             draw_info->stroke_width=argument_list[5].real_reference;
8868           if (attribute_flag[6] != 0)
8869             (void) CloneString(&draw_info->font,
8870               argument_list[6].string_reference);
8871           if (attribute_flag[7] != 0)
8872             (void) QueryColorCompliance(argument_list[7].string_reference,
8873               AllCompliance,&draw_info->border_color,exception);
8874           if (attribute_flag[8] != 0)
8875             draw_info->affine.tx=argument_list[8].real_reference;
8876           if (attribute_flag[9] != 0)
8877             draw_info->affine.ty=argument_list[9].real_reference;
8878           if (attribute_flag[20] != 0)
8879             {
8880               AV
8881                 *av;
8882
8883               av=(AV *) argument_list[20].array_reference;
8884               if ((av_len(av) != 3) && (av_len(av) != 5))
8885                 {
8886                   ThrowPerlException(exception,OptionError,
8887                     "affine matrix must have 4 or 6 elements",PackageName);
8888                   goto PerlException;
8889                 }
8890               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8891               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8892               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8893               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8894               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8895                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8896                 {
8897                   ThrowPerlException(exception,OptionError,
8898                     "affine matrix is singular",PackageName);
8899                    goto PerlException;
8900                 }
8901               if (av_len(av) == 5)
8902                 {
8903                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8904                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8905                 }
8906             }
8907           for (j=10; j < 15; j++)
8908           {
8909             if (attribute_flag[j] == 0)
8910               continue;
8911             value=argument_list[j].string_reference;
8912             angle=argument_list[j].real_reference;
8913             current=draw_info->affine;
8914             GetAffineMatrix(&affine);
8915             switch (j)
8916             {
8917               case 10:
8918               {
8919                 /*
8920                   Translate.
8921                 */
8922                 flags=ParseGeometry(value,&geometry_info);
8923                 affine.tx=geometry_info.xi;
8924                 affine.ty=geometry_info.psi;
8925                 if ((flags & PsiValue) == 0)
8926                   affine.ty=affine.tx;
8927                 break;
8928               }
8929               case 11:
8930               {
8931                 /*
8932                   Scale.
8933                 */
8934                 flags=ParseGeometry(value,&geometry_info);
8935                 affine.sx=geometry_info.rho;
8936                 affine.sy=geometry_info.sigma;
8937                 if ((flags & SigmaValue) == 0)
8938                   affine.sy=affine.sx;
8939                 break;
8940               }
8941               case 12:
8942               {
8943                 /*
8944                   Rotate.
8945                 */
8946                 if (angle == 0.0)
8947                   break;
8948                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8949                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8950                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8951                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8952                 break;
8953               }
8954               case 13:
8955               {
8956                 /*
8957                   SkewX.
8958                 */
8959                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8960                 break;
8961               }
8962               case 14:
8963               {
8964                 /*
8965                   SkewY.
8966                 */
8967                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8968                 break;
8969               }
8970             }
8971             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8972             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8973             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8974             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8975             draw_info->affine.tx=
8976               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8977             draw_info->affine.ty=
8978               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8979           }
8980           if (attribute_flag[15] != 0)
8981             draw_info->fill_pattern=CloneImage(
8982               argument_list[15].image_reference,0,0,MagickTrue,exception);
8983           if (attribute_flag[16] != 0)
8984             draw_info->pointsize=argument_list[16].real_reference;
8985           if (attribute_flag[17] != 0)
8986             {
8987               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8988                 ? MagickTrue : MagickFalse;
8989               draw_info->text_antialias=draw_info->stroke_antialias;
8990             }
8991           if (attribute_flag[18] != 0)
8992             (void) CloneString(&draw_info->density,
8993               argument_list[18].string_reference);
8994           if (attribute_flag[19] != 0)
8995             draw_info->stroke_width=argument_list[19].real_reference;
8996           if (attribute_flag[21] != 0)
8997             draw_info->dash_offset=argument_list[21].real_reference;
8998           if (attribute_flag[22] != 0)
8999             {
9000               AV
9001                 *av;
9002
9003               av=(AV *) argument_list[22].array_reference;
9004               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9005                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9006               if (draw_info->dash_pattern != (double *) NULL)
9007                 {
9008                   for (i=0; i <= av_len(av); i++)
9009                     draw_info->dash_pattern[i]=(double)
9010                       SvNV(*(av_fetch(av,i,0)));
9011                   draw_info->dash_pattern[i]=0.0;
9012                 }
9013             }
9014           if (attribute_flag[23] != 0)
9015             image->interpolate=(PixelInterpolateMethod)
9016               argument_list[23].integer_reference;
9017           if ((attribute_flag[24] != 0) &&
9018               (draw_info->fill_pattern != (Image *) NULL))
9019             flags=ParsePageGeometry(draw_info->fill_pattern,
9020               argument_list[24].string_reference,
9021               &draw_info->fill_pattern->tile_offset,exception);
9022           if (attribute_flag[25] != 0)
9023             {
9024               (void) ConcatenateString(&draw_info->primitive," '");
9025               (void) ConcatenateString(&draw_info->primitive,
9026                 argument_list[25].string_reference);
9027               (void) ConcatenateString(&draw_info->primitive,"'");
9028             }
9029           if (attribute_flag[26] != 0)
9030             draw_info->fill_pattern=CloneImage(
9031               argument_list[26].image_reference,0,0,MagickTrue,exception);
9032           if (attribute_flag[27] != 0)
9033             draw_info->stroke_pattern=CloneImage(
9034               argument_list[27].image_reference,0,0,MagickTrue,exception);
9035           if (attribute_flag[28] != 0)
9036             (void) CloneString(&draw_info->primitive,
9037               argument_list[28].string_reference);
9038           if (attribute_flag[29] != 0)
9039             draw_info->kerning=argument_list[29].real_reference;
9040           if (attribute_flag[30] != 0)
9041             draw_info->interline_spacing=argument_list[30].real_reference;
9042           if (attribute_flag[31] != 0)
9043             draw_info->interword_spacing=argument_list[31].real_reference;
9044           if (attribute_flag[32] != 0)
9045             draw_info->direction=(DirectionType)
9046               argument_list[32].integer_reference;
9047           DrawImage(image,draw_info,exception);
9048           draw_info=DestroyDrawInfo(draw_info);
9049           break;
9050         }
9051         case 39:  /* Equalize */
9052         {
9053           if (attribute_flag[0] != 0)
9054             channel=(ChannelType) argument_list[0].integer_reference;
9055           channel_mask=SetImageChannelMask(image,channel);
9056           EqualizeImage(image,exception);
9057           (void) SetImageChannelMask(image,channel_mask);
9058           break;
9059         }
9060         case 40:  /* Gamma */
9061         {
9062           if (attribute_flag[1] != 0)
9063             channel=(ChannelType) argument_list[1].integer_reference;
9064           if (attribute_flag[2] == 0)
9065             argument_list[2].real_reference=1.0;
9066           if (attribute_flag[3] == 0)
9067             argument_list[3].real_reference=1.0;
9068           if (attribute_flag[4] == 0)
9069             argument_list[4].real_reference=1.0;
9070           if (attribute_flag[0] == 0)
9071             {
9072               (void) FormatLocaleString(message,MagickPathExtent,
9073                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9074                 (double) argument_list[3].real_reference,
9075                 (double) argument_list[4].real_reference);
9076               argument_list[0].string_reference=message;
9077             }
9078           (void) GammaImage(image,StringToDouble(
9079             argument_list[0].string_reference,(char **) NULL),exception);
9080           break;
9081         }
9082         case 41:  /* Map */
9083         {
9084           QuantizeInfo
9085             *quantize_info;
9086
9087           if (attribute_flag[0] == 0)
9088             {
9089               ThrowPerlException(exception,OptionError,"MapImageRequired",
9090                 PackageName);
9091               goto PerlException;
9092             }
9093           quantize_info=AcquireQuantizeInfo(info->image_info);
9094           if (attribute_flag[1] != 0)
9095             quantize_info->dither_method=(DitherMethod)
9096               argument_list[1].integer_reference;
9097           (void) RemapImages(quantize_info,image,
9098             argument_list[0].image_reference,exception);
9099           quantize_info=DestroyQuantizeInfo(quantize_info);
9100           break;
9101         }
9102         case 42:  /* MatteFloodfill */
9103         {
9104           DrawInfo
9105             *draw_info;
9106
9107           MagickBooleanType
9108             invert;
9109
9110           PixelInfo
9111             target;
9112
9113           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9114             (DrawInfo *) NULL);
9115           if (attribute_flag[0] != 0)
9116             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9117               &geometry,exception);
9118           if (attribute_flag[1] != 0)
9119             geometry.x=argument_list[1].integer_reference;
9120           if (attribute_flag[2] != 0)
9121             geometry.y=argument_list[2].integer_reference;
9122           if (image->alpha_trait == UndefinedPixelTrait)
9123             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9124           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9125             geometry.x,geometry.y,&target,exception);
9126           if (attribute_flag[4] != 0)
9127             QueryColorCompliance(argument_list[4].string_reference,
9128               AllCompliance,&target,exception);
9129           if (attribute_flag[3] != 0)
9130             target.alpha=StringToDoubleInterval(
9131               argument_list[3].string_reference,(double) (double) QuantumRange+
9132               1.0);
9133           if (attribute_flag[5] != 0)
9134             image->fuzz=StringToDoubleInterval(
9135               argument_list[5].string_reference,(double) QuantumRange+1.0);
9136           invert=MagickFalse;
9137           if (attribute_flag[6] != 0)
9138             invert=(MagickBooleanType) argument_list[6].integer_reference;
9139           channel_mask=SetImageChannelMask(image,AlphaChannel);
9140           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9141             geometry.y,invert,exception);
9142           (void) SetImageChannelMask(image,channel_mask);
9143           draw_info=DestroyDrawInfo(draw_info);
9144           break;
9145         }
9146         case 43:  /* Modulate */
9147         {
9148           char
9149             modulate[MagickPathExtent];
9150
9151           geometry_info.rho=100.0;
9152           geometry_info.sigma=100.0;
9153           geometry_info.xi=100.0;
9154           if (attribute_flag[0] != 0)
9155             (void)ParseGeometry(argument_list[0].string_reference,
9156               &geometry_info);
9157           if (attribute_flag[1] != 0)
9158             geometry_info.xi=argument_list[1].real_reference;
9159           if (attribute_flag[2] != 0)
9160             geometry_info.sigma=argument_list[2].real_reference;
9161           if (attribute_flag[3] != 0)
9162             {
9163               geometry_info.sigma=argument_list[3].real_reference;
9164               SetImageArtifact(image,"modulate:colorspace","HWB");
9165             }
9166           if (attribute_flag[4] != 0)
9167             {
9168               geometry_info.rho=argument_list[4].real_reference;
9169               SetImageArtifact(image,"modulate:colorspace","HSB");
9170             }
9171           if (attribute_flag[5] != 0)
9172             {
9173               geometry_info.sigma=argument_list[5].real_reference;
9174               SetImageArtifact(image,"modulate:colorspace","HSL");
9175             }
9176           if (attribute_flag[6] != 0)
9177             {
9178               geometry_info.rho=argument_list[6].real_reference;
9179               SetImageArtifact(image,"modulate:colorspace","HWB");
9180             }
9181           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9182             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9183           (void) ModulateImage(image,modulate,exception);
9184           break;
9185         }
9186         case 44:  /* Negate */
9187         {
9188           if (attribute_flag[0] == 0)
9189             argument_list[0].integer_reference=0;
9190           if (attribute_flag[1] != 0)
9191             channel=(ChannelType) argument_list[1].integer_reference;
9192           channel_mask=SetImageChannelMask(image,channel);
9193           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9194             MagickTrue : MagickFalse,exception);
9195           (void) SetImageChannelMask(image,channel_mask);
9196           break;
9197         }
9198         case 45:  /* Normalize */
9199         {
9200           if (attribute_flag[0] != 0)
9201             channel=(ChannelType) argument_list[0].integer_reference;
9202           channel_mask=SetImageChannelMask(image,channel);
9203           NormalizeImage(image,exception);
9204           (void) SetImageChannelMask(image,channel_mask);
9205           break;
9206         }
9207         case 46:  /* NumberColors */
9208           break;
9209         case 47:  /* Opaque */
9210         {
9211           MagickBooleanType
9212             invert;
9213
9214           PixelInfo
9215             fill_color,
9216             target;
9217
9218           (void) QueryColorCompliance("none",AllCompliance,&target,
9219              exception);
9220           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9221             exception);
9222           if (attribute_flag[0] != 0)
9223             (void) QueryColorCompliance(argument_list[0].string_reference,
9224               AllCompliance,&target,exception);
9225           if (attribute_flag[1] != 0)
9226             (void) QueryColorCompliance(argument_list[1].string_reference,
9227               AllCompliance,&fill_color,exception);
9228           if (attribute_flag[2] != 0)
9229             image->fuzz=StringToDoubleInterval(
9230               argument_list[2].string_reference,(double) QuantumRange+1.0);
9231           if (attribute_flag[3] != 0)
9232             channel=(ChannelType) argument_list[3].integer_reference;
9233           invert=MagickFalse;
9234           if (attribute_flag[4] != 0)
9235             invert=(MagickBooleanType) argument_list[4].integer_reference;
9236           channel_mask=SetImageChannelMask(image,channel);
9237           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9238           (void) SetImageChannelMask(image,channel_mask);
9239           break;
9240         }
9241         case 48:  /* Quantize */
9242         {
9243           QuantizeInfo
9244             *quantize_info;
9245
9246           quantize_info=AcquireQuantizeInfo(info->image_info);
9247           if (attribute_flag[0] != 0)
9248             quantize_info->number_colors=(size_t)
9249               argument_list[0].integer_reference;
9250           if (attribute_flag[1] != 0)
9251             quantize_info->tree_depth=(size_t)
9252               argument_list[1].integer_reference;
9253           if (attribute_flag[2] != 0)
9254             quantize_info->colorspace=(ColorspaceType)
9255               argument_list[2].integer_reference;
9256           if (attribute_flag[3] != 0)
9257             quantize_info->dither_method=(DitherMethod)
9258               argument_list[3].integer_reference;
9259           if (attribute_flag[4] != 0)
9260             quantize_info->measure_error=
9261               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9262           if (attribute_flag[6] != 0)
9263             (void) QueryColorCompliance(argument_list[6].string_reference,
9264               AllCompliance,&image->transparent_color,exception);
9265           if (attribute_flag[7] != 0)
9266             quantize_info->dither_method=(DitherMethod)
9267               argument_list[7].integer_reference;
9268           if (attribute_flag[5] && argument_list[5].integer_reference)
9269             (void) QuantizeImages(quantize_info,image,exception);
9270           else
9271             if ((image->storage_class == DirectClass) ||
9272                (image->colors > quantize_info->number_colors) ||
9273                (quantize_info->colorspace == GRAYColorspace))
9274              (void) QuantizeImage(quantize_info,image,exception);
9275            else
9276              CompressImageColormap(image,exception);
9277           quantize_info=DestroyQuantizeInfo(quantize_info);
9278           break;
9279         }
9280         case 49:  /* Raise */
9281         {
9282           if (attribute_flag[0] != 0)
9283             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9284               &geometry,exception);
9285           if (attribute_flag[1] != 0)
9286             geometry.width=argument_list[1].integer_reference;
9287           if (attribute_flag[2] != 0)
9288             geometry.height=argument_list[2].integer_reference;
9289           if (attribute_flag[3] == 0)
9290             argument_list[3].integer_reference=1;
9291           (void) RaiseImage(image,&geometry,
9292             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9293             exception);
9294           break;
9295         }
9296         case 50:  /* Segment */
9297         {
9298           ColorspaceType
9299             colorspace;
9300
9301           double
9302             cluster_threshold,
9303             smoothing_threshold;
9304
9305           MagickBooleanType
9306             verbose;
9307
9308           cluster_threshold=1.0;
9309           smoothing_threshold=1.5;
9310           colorspace=sRGBColorspace;
9311           verbose=MagickFalse;
9312           if (attribute_flag[0] != 0)
9313             {
9314               flags=ParseGeometry(argument_list[0].string_reference,
9315                 &geometry_info);
9316               cluster_threshold=geometry_info.rho;
9317               if (flags & SigmaValue)
9318                 smoothing_threshold=geometry_info.sigma;
9319             }
9320           if (attribute_flag[1] != 0)
9321             cluster_threshold=argument_list[1].real_reference;
9322           if (attribute_flag[2] != 0)
9323             smoothing_threshold=argument_list[2].real_reference;
9324           if (attribute_flag[3] != 0)
9325             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9326           if (attribute_flag[4] != 0)
9327             verbose=argument_list[4].integer_reference != 0 ?
9328               MagickTrue : MagickFalse;
9329           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9330             smoothing_threshold,exception);
9331           break;
9332         }
9333         case 51:  /* Signature */
9334         {
9335           (void) SignatureImage(image,exception);
9336           break;
9337         }
9338         case 52:  /* Solarize */
9339         {
9340           geometry_info.rho=QuantumRange/2.0;
9341           if (attribute_flag[0] != 0)
9342             flags=ParseGeometry(argument_list[0].string_reference,
9343               &geometry_info);
9344           if (attribute_flag[1] != 0)
9345             geometry_info.rho=StringToDoubleInterval(
9346               argument_list[1].string_reference,(double) QuantumRange+1.0);
9347           (void) SolarizeImage(image,geometry_info.rho,exception);
9348           break;
9349         }
9350         case 53:  /* Sync */
9351         {
9352           (void) SyncImage(image,exception);
9353           break;
9354         }
9355         case 54:  /* Texture */
9356         {
9357           if (attribute_flag[0] == 0)
9358             break;
9359           TextureImage(image,argument_list[0].image_reference,exception);
9360           break;
9361         }
9362         case 55:  /* Evalute */
9363         {
9364           MagickEvaluateOperator
9365             op;
9366
9367           op=SetEvaluateOperator;
9368           if (attribute_flag[0] == MagickFalse)
9369             argument_list[0].real_reference=0.0;
9370           if (attribute_flag[1] != MagickFalse)
9371             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9372           if (attribute_flag[2] != MagickFalse)
9373             channel=(ChannelType) argument_list[2].integer_reference;
9374           channel_mask=SetImageChannelMask(image,channel);
9375           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9376             exception);
9377           (void) SetImageChannelMask(image,channel_mask);
9378           break;
9379         }
9380         case 56:  /* Transparent */
9381         {
9382           double
9383             opacity;
9384
9385           MagickBooleanType
9386             invert;
9387
9388           PixelInfo
9389             target;
9390
9391           (void) QueryColorCompliance("none",AllCompliance,&target,
9392             exception);
9393           if (attribute_flag[0] != 0)
9394             (void) QueryColorCompliance(argument_list[0].string_reference,
9395               AllCompliance,&target,exception);
9396           opacity=TransparentAlpha;
9397           if (attribute_flag[1] != 0)
9398             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9399               (double) QuantumRange+1.0);
9400           if (attribute_flag[2] != 0)
9401             image->fuzz=StringToDoubleInterval(
9402               argument_list[2].string_reference,(double) QuantumRange+1.0);
9403           if (attribute_flag[3] == 0)
9404             argument_list[3].integer_reference=0;
9405           invert=MagickFalse;
9406           if (attribute_flag[3] != 0)
9407             invert=(MagickBooleanType) argument_list[3].integer_reference;
9408           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9409             invert,exception);
9410           break;
9411         }
9412         case 57:  /* Threshold */
9413         {
9414           double
9415             threshold;
9416
9417           if (attribute_flag[0] == 0)
9418             argument_list[0].string_reference="50%";
9419           if (attribute_flag[1] != 0)
9420             channel=(ChannelType) argument_list[1].integer_reference;
9421           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9422             (double) QuantumRange+1.0);
9423           channel_mask=SetImageChannelMask(image,channel);
9424           (void) BilevelImage(image,threshold,exception);
9425           (void) SetImageChannelMask(image,channel_mask);
9426           break;
9427         }
9428         case 58:  /* Charcoal */
9429         {
9430           if (attribute_flag[0] != 0)
9431             {
9432               flags=ParseGeometry(argument_list[0].string_reference,
9433                 &geometry_info);
9434               if ((flags & SigmaValue) == 0)
9435                 geometry_info.sigma=1.0;
9436             }
9437           if (attribute_flag[1] != 0)
9438             geometry_info.rho=argument_list[1].real_reference;
9439           if (attribute_flag[2] != 0)
9440             geometry_info.sigma=argument_list[2].real_reference;
9441           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9442             exception);
9443           break;
9444         }
9445         case 59:  /* Trim */
9446         {
9447           if (attribute_flag[0] != 0)
9448             image->fuzz=StringToDoubleInterval(
9449               argument_list[0].string_reference,(double) QuantumRange+1.0);
9450           image=TrimImage(image,exception);
9451           break;
9452         }
9453         case 60:  /* Wave */
9454         {
9455           PixelInterpolateMethod
9456             method;
9457
9458           if (attribute_flag[0] != 0)
9459             {
9460               flags=ParseGeometry(argument_list[0].string_reference,
9461                 &geometry_info);
9462               if ((flags & SigmaValue) == 0)
9463                 geometry_info.sigma=1.0;
9464             }
9465           if (attribute_flag[1] != 0)
9466             geometry_info.rho=argument_list[1].real_reference;
9467           if (attribute_flag[2] != 0)
9468             geometry_info.sigma=argument_list[2].real_reference;
9469           method=UndefinedInterpolatePixel;
9470           if (attribute_flag[3] != 0)
9471             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9472           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9473             method,exception);
9474           break;
9475         }
9476         case 61:  /* Separate */
9477         {
9478           if (attribute_flag[0] != 0)
9479             channel=(ChannelType) argument_list[0].integer_reference;
9480           image=SeparateImage(image,channel,exception);
9481           break;
9482         }
9483         case 63:  /* Stereo */
9484         {
9485           if (attribute_flag[0] == 0)
9486             {
9487               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9488                 PackageName);
9489               goto PerlException;
9490             }
9491           if (attribute_flag[1] != 0)
9492             geometry.x=argument_list[1].integer_reference;
9493           if (attribute_flag[2] != 0)
9494             geometry.y=argument_list[2].integer_reference;
9495           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9496             geometry.x,geometry.y,exception);
9497           break;
9498         }
9499         case 64:  /* Stegano */
9500         {
9501           if (attribute_flag[0] == 0)
9502             {
9503               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9504                 PackageName);
9505               goto PerlException;
9506             }
9507           if (attribute_flag[1] == 0)
9508             argument_list[1].integer_reference=0;
9509           image->offset=argument_list[1].integer_reference;
9510           image=SteganoImage(image,argument_list[0].image_reference,exception);
9511           break;
9512         }
9513         case 65:  /* Deconstruct */
9514         {
9515           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9516           break;
9517         }
9518         case 66:  /* GaussianBlur */
9519         {
9520           if (attribute_flag[0] != 0)
9521             {
9522               flags=ParseGeometry(argument_list[0].string_reference,
9523                 &geometry_info);
9524               if ((flags & SigmaValue) == 0)
9525                 geometry_info.sigma=1.0;
9526             }
9527           if (attribute_flag[1] != 0)
9528             geometry_info.rho=argument_list[1].real_reference;
9529           if (attribute_flag[2] != 0)
9530             geometry_info.sigma=argument_list[2].real_reference;
9531           if (attribute_flag[3] != 0)
9532             channel=(ChannelType) argument_list[3].integer_reference;
9533           channel_mask=SetImageChannelMask(image,channel);
9534           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9535             exception);
9536           if (image != (Image *) NULL)
9537             (void) SetImageChannelMask(image,channel_mask);
9538           break;
9539         }
9540         case 67:  /* Convolve */
9541         {
9542           KernelInfo
9543             *kernel;
9544
9545           kernel=(KernelInfo *) NULL;
9546           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9547             break;
9548           if (attribute_flag[0] != 0)
9549             {
9550               AV
9551                 *av;
9552
9553               size_t
9554                 order;
9555
9556               kernel=AcquireKernelInfo((const char *) NULL,exception);
9557               if (kernel == (KernelInfo *) NULL)
9558                 break;
9559               av=(AV *) argument_list[0].array_reference;
9560               order=(size_t) sqrt(av_len(av)+1);
9561               kernel->width=order;
9562               kernel->height=order;
9563               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9564                 order*sizeof(*kernel->values));
9565               if (kernel->values == (MagickRealType *) NULL)
9566                 {
9567                   kernel=DestroyKernelInfo(kernel);
9568                   ThrowPerlException(exception,ResourceLimitFatalError,
9569                     "MemoryAllocationFailed",PackageName);
9570                   goto PerlException;
9571                 }
9572               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9573                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9574               for ( ; j < (ssize_t) (order*order); j++)
9575                 kernel->values[j]=0.0;
9576             }
9577           if (attribute_flag[1] != 0)
9578             channel=(ChannelType) argument_list[1].integer_reference;
9579           if (attribute_flag[2] != 0)
9580             SetImageArtifact(image,"filter:blur",
9581               argument_list[2].string_reference);
9582           if (attribute_flag[3] != 0)
9583             {
9584               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9585                 exception);
9586               if (kernel == (KernelInfo *) NULL)
9587                 break;
9588             }
9589           channel_mask=SetImageChannelMask(image,channel);
9590           image=ConvolveImage(image,kernel,exception);
9591           if (image != (Image *) NULL)
9592             (void) SetImageChannelMask(image,channel_mask);
9593           kernel=DestroyKernelInfo(kernel);
9594           break;
9595         }
9596         case 68:  /* Profile */
9597         {
9598           const char
9599             *name;
9600
9601           Image
9602             *profile_image;
9603
9604           ImageInfo
9605             *profile_info;
9606
9607           StringInfo
9608             *profile;
9609
9610           name="*";
9611           if (attribute_flag[0] != 0)
9612             name=argument_list[0].string_reference;
9613           if (attribute_flag[2] != 0)
9614             image->rendering_intent=(RenderingIntent)
9615               argument_list[2].integer_reference;
9616           if (attribute_flag[3] != 0)
9617             image->black_point_compensation=
9618               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9619           if (attribute_flag[1] != 0)
9620             {
9621               if (argument_list[1].length == 0)
9622                 {
9623                   /*
9624                     Remove a profile from the image.
9625                   */
9626                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9627                     exception);
9628                   break;
9629                 }
9630               /*
9631                 Associate user supplied profile with the image.
9632               */
9633               profile=AcquireStringInfo(argument_list[1].length);
9634               SetStringInfoDatum(profile,(const unsigned char *)
9635                 argument_list[1].string_reference);
9636               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9637                 (size_t) GetStringInfoLength(profile),exception);
9638               profile=DestroyStringInfo(profile);
9639               break;
9640             }
9641           /*
9642             Associate a profile with the image.
9643           */
9644           profile_info=CloneImageInfo(info ? info->image_info :
9645             (ImageInfo *) NULL);
9646           profile_image=ReadImages(profile_info,name,exception);
9647           if (profile_image == (Image *) NULL)
9648             break;
9649           ResetImageProfileIterator(profile_image);
9650           name=GetNextImageProfile(profile_image);
9651           while (name != (const char *) NULL)
9652           {
9653             const StringInfo
9654               *profile;
9655
9656             profile=GetImageProfile(profile_image,name);
9657             if (profile != (const StringInfo *) NULL)
9658               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9659                 (size_t) GetStringInfoLength(profile),exception);
9660             name=GetNextImageProfile(profile_image);
9661           }
9662           profile_image=DestroyImage(profile_image);
9663           profile_info=DestroyImageInfo(profile_info);
9664           break;
9665         }
9666         case 69:  /* UnsharpMask */
9667         {
9668           if (attribute_flag[0] != 0)
9669             {
9670               flags=ParseGeometry(argument_list[0].string_reference,
9671                 &geometry_info);
9672               if ((flags & SigmaValue) == 0)
9673                 geometry_info.sigma=1.0;
9674               if ((flags & XiValue) == 0)
9675                 geometry_info.xi=1.0;
9676               if ((flags & PsiValue) == 0)
9677                 geometry_info.psi=0.5;
9678             }
9679           if (attribute_flag[1] != 0)
9680             geometry_info.rho=argument_list[1].real_reference;
9681           if (attribute_flag[2] != 0)
9682             geometry_info.sigma=argument_list[2].real_reference;
9683           if (attribute_flag[3] != 0)
9684             geometry_info.xi=argument_list[3].real_reference;
9685           if (attribute_flag[4] != 0)
9686             geometry_info.psi=argument_list[4].real_reference;
9687           if (attribute_flag[5] != 0)
9688             channel=(ChannelType) argument_list[5].integer_reference;
9689           channel_mask=SetImageChannelMask(image,channel);
9690           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9691             geometry_info.xi,geometry_info.psi,exception);
9692           if (image != (Image *) NULL)
9693             (void) SetImageChannelMask(image,channel_mask);
9694           break;
9695         }
9696         case 70:  /* MotionBlur */
9697         {
9698           if (attribute_flag[0] != 0)
9699             {
9700               flags=ParseGeometry(argument_list[0].string_reference,
9701                 &geometry_info);
9702               if ((flags & SigmaValue) == 0)
9703                 geometry_info.sigma=1.0;
9704               if ((flags & XiValue) == 0)
9705                 geometry_info.xi=1.0;
9706             }
9707           if (attribute_flag[1] != 0)
9708             geometry_info.rho=argument_list[1].real_reference;
9709           if (attribute_flag[2] != 0)
9710             geometry_info.sigma=argument_list[2].real_reference;
9711           if (attribute_flag[3] != 0)
9712             geometry_info.xi=argument_list[3].real_reference;
9713           if (attribute_flag[4] != 0)
9714             channel=(ChannelType) argument_list[4].integer_reference;
9715           channel_mask=SetImageChannelMask(image,channel);
9716           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9717             geometry_info.xi,exception);
9718           if (image != (Image *) NULL)
9719             (void) SetImageChannelMask(image,channel_mask);
9720           break;
9721         }
9722         case 71:  /* OrderedDither */
9723         {
9724           if (attribute_flag[0] == 0)
9725             argument_list[0].string_reference="o8x8";
9726           if (attribute_flag[1] != 0)
9727             channel=(ChannelType) argument_list[1].integer_reference;
9728           channel_mask=SetImageChannelMask(image,channel);
9729           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9730             exception);
9731           (void) SetImageChannelMask(image,channel_mask);
9732           break;
9733         }
9734         case 72:  /* Shave */
9735         {
9736           if (attribute_flag[0] != 0)
9737             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9738               &geometry,exception);
9739           if (attribute_flag[1] != 0)
9740             geometry.width=argument_list[1].integer_reference;
9741           if (attribute_flag[2] != 0)
9742             geometry.height=argument_list[2].integer_reference;
9743           image=ShaveImage(image,&geometry,exception);
9744           break;
9745         }
9746         case 73:  /* Level */
9747         {
9748           double
9749             black_point,
9750             gamma,
9751             white_point;
9752
9753           black_point=0.0;
9754           white_point=(double) image->columns*image->rows;
9755           gamma=1.0;
9756           if (attribute_flag[0] != 0)
9757             {
9758               flags=ParseGeometry(argument_list[0].string_reference,
9759                 &geometry_info);
9760               black_point=geometry_info.rho;
9761               if ((flags & SigmaValue) != 0)
9762                 white_point=geometry_info.sigma;
9763               if ((flags & XiValue) != 0)
9764                 gamma=geometry_info.xi;
9765               if ((flags & PercentValue) != 0)
9766                 {
9767                   black_point*=(double) (QuantumRange/100.0);
9768                   white_point*=(double) (QuantumRange/100.0);
9769                 }
9770               if ((flags & SigmaValue) == 0)
9771                 white_point=(double) QuantumRange-black_point;
9772             }
9773           if (attribute_flag[1] != 0)
9774             black_point=argument_list[1].real_reference;
9775           if (attribute_flag[2] != 0)
9776             white_point=argument_list[2].real_reference;
9777           if (attribute_flag[3] != 0)
9778             gamma=argument_list[3].real_reference;
9779           if (attribute_flag[4] != 0)
9780             channel=(ChannelType) argument_list[4].integer_reference;
9781           if (attribute_flag[5] != 0)
9782             {
9783               argument_list[0].real_reference=argument_list[5].real_reference;
9784               attribute_flag[0]=attribute_flag[5];
9785             }
9786           channel_mask=SetImageChannelMask(image,channel);
9787           (void) LevelImage(image,black_point,white_point,gamma,exception);
9788           (void) SetImageChannelMask(image,channel_mask);
9789           break;
9790         }
9791         case 74:  /* Clip */
9792         {
9793           if (attribute_flag[0] == 0)
9794             argument_list[0].string_reference="#1";
9795           if (attribute_flag[1] == 0)
9796             argument_list[1].integer_reference=MagickTrue;
9797           (void) ClipImagePath(image,argument_list[0].string_reference,
9798             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9799             exception);
9800           break;
9801         }
9802         case 75:  /* AffineTransform */
9803         {
9804           DrawInfo
9805             *draw_info;
9806
9807           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9808             (DrawInfo *) NULL);
9809           if (attribute_flag[0] != 0)
9810             {
9811               AV
9812                 *av;
9813
9814               av=(AV *) argument_list[0].array_reference;
9815               if ((av_len(av) != 3) && (av_len(av) != 5))
9816                 {
9817                   ThrowPerlException(exception,OptionError,
9818                     "affine matrix must have 4 or 6 elements",PackageName);
9819                   goto PerlException;
9820                 }
9821               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9822               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9823               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9824               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9825               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9826                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9827                 {
9828                   ThrowPerlException(exception,OptionError,
9829                     "affine matrix is singular",PackageName);
9830                    goto PerlException;
9831                 }
9832               if (av_len(av) == 5)
9833                 {
9834                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9835                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9836                 }
9837             }
9838           for (j=1; j < 6; j++)
9839           {
9840             if (attribute_flag[j] == 0)
9841               continue;
9842             value=argument_list[j].string_reference;
9843             angle=argument_list[j].real_reference;
9844             current=draw_info->affine;
9845             GetAffineMatrix(&affine);
9846             switch (j)
9847             {
9848               case 1:
9849               {
9850                 /*
9851                   Translate.
9852                 */
9853                 flags=ParseGeometry(value,&geometry_info);
9854                 affine.tx=geometry_info.xi;
9855                 affine.ty=geometry_info.psi;
9856                 if ((flags & PsiValue) == 0)
9857                   affine.ty=affine.tx;
9858                 break;
9859               }
9860               case 2:
9861               {
9862                 /*
9863                   Scale.
9864                 */
9865                 flags=ParseGeometry(value,&geometry_info);
9866                 affine.sx=geometry_info.rho;
9867                 affine.sy=geometry_info.sigma;
9868                 if ((flags & SigmaValue) == 0)
9869                   affine.sy=affine.sx;
9870                 break;
9871               }
9872               case 3:
9873               {
9874                 /*
9875                   Rotate.
9876                 */
9877                 if (angle == 0.0)
9878                   break;
9879                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9880                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9881                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9882                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9883                 break;
9884               }
9885               case 4:
9886               {
9887                 /*
9888                   SkewX.
9889                 */
9890                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9891                 break;
9892               }
9893               case 5:
9894               {
9895                 /*
9896                   SkewY.
9897                 */
9898                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9899                 break;
9900               }
9901             }
9902             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9903             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9904             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9905             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9906             draw_info->affine.tx=
9907               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9908             draw_info->affine.ty=
9909               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9910           }
9911           if (attribute_flag[6] != 0)
9912             image->interpolate=(PixelInterpolateMethod)
9913               argument_list[6].integer_reference;
9914           if (attribute_flag[7] != 0)
9915             QueryColorCompliance(argument_list[7].string_reference,
9916               AllCompliance,&image->background_color,exception);
9917           image=AffineTransformImage(image,&draw_info->affine,exception);
9918           draw_info=DestroyDrawInfo(draw_info);
9919           break;
9920         }
9921         case 76:  /* Difference */
9922         {
9923           if (attribute_flag[0] == 0)
9924             {
9925               ThrowPerlException(exception,OptionError,
9926                 "ReferenceImageRequired",PackageName);
9927               goto PerlException;
9928             }
9929           if (attribute_flag[1] != 0)
9930             image->fuzz=StringToDoubleInterval(
9931               argument_list[1].string_reference,(double) QuantumRange+1.0);
9932           (void) IsImagesEqual(image,argument_list[0].image_reference,
9933             exception);
9934           break;
9935         }
9936         case 77:  /* AdaptiveThreshold */
9937         {
9938           if (attribute_flag[0] != 0)
9939             {
9940               flags=ParseGeometry(argument_list[0].string_reference,
9941                 &geometry_info);
9942               if ((flags & PercentValue) != 0)
9943                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9944             }
9945           if (attribute_flag[1] != 0)
9946             geometry_info.rho=argument_list[1].integer_reference;
9947           if (attribute_flag[2] != 0)
9948             geometry_info.sigma=argument_list[2].integer_reference;
9949           if (attribute_flag[3] != 0)
9950             geometry_info.xi=argument_list[3].integer_reference;;
9951           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9952             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9953           break;
9954         }
9955         case 78:  /* Resample */
9956         {
9957           size_t
9958             height,
9959             width;
9960
9961           if (attribute_flag[0] != 0)
9962             {
9963               flags=ParseGeometry(argument_list[0].string_reference,
9964                 &geometry_info);
9965               if ((flags & SigmaValue) == 0)
9966                 geometry_info.sigma=geometry_info.rho;
9967             }
9968           if (attribute_flag[1] != 0)
9969             geometry_info.rho=argument_list[1].real_reference;
9970           if (attribute_flag[2] != 0)
9971             geometry_info.sigma=argument_list[2].real_reference;
9972           if (attribute_flag[3] == 0)
9973             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9974           if (attribute_flag[4] == 0)
9975             SetImageArtifact(image,"filter:support",
9976               argument_list[4].string_reference);
9977           width=(size_t) (geometry_info.rho*image->columns/
9978             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9979           height=(size_t) (geometry_info.sigma*image->rows/
9980             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9981           image=ResizeImage(image,width,height,(FilterTypes)
9982             argument_list[3].integer_reference,exception);
9983           if (image != (Image *) NULL)
9984             {
9985               image->resolution.x=geometry_info.rho;
9986               image->resolution.y=geometry_info.sigma;
9987             }
9988           break;
9989         }
9990         case 79:  /* Describe */
9991         {
9992           if (attribute_flag[0] == 0)
9993             argument_list[0].file_reference=(FILE *) NULL;
9994           if (attribute_flag[1] != 0)
9995             (void) SetImageArtifact(image,"identify:features",
9996               argument_list[1].string_reference);
9997           (void) IdentifyImage(image,argument_list[0].file_reference,
9998             MagickTrue,exception);
9999           break;
10000         }
10001         case 80:  /* BlackThreshold */
10002         {
10003           if (attribute_flag[0] == 0)
10004             argument_list[0].string_reference="50%";
10005           if (attribute_flag[2] != 0)
10006             channel=(ChannelType) argument_list[2].integer_reference;
10007           channel_mask=SetImageChannelMask(image,channel);
10008           BlackThresholdImage(image,argument_list[0].string_reference,
10009             exception);
10010           (void) SetImageChannelMask(image,channel_mask);
10011           break;
10012         }
10013         case 81:  /* WhiteThreshold */
10014         {
10015           if (attribute_flag[0] == 0)
10016             argument_list[0].string_reference="50%";
10017           if (attribute_flag[2] != 0)
10018             channel=(ChannelType) argument_list[2].integer_reference;
10019           channel_mask=SetImageChannelMask(image,channel);
10020           WhiteThresholdImage(image,argument_list[0].string_reference,
10021             exception);
10022           (void) SetImageChannelMask(image,channel_mask);
10023           break;
10024         }
10025         case 82:  /* RotationalBlur */
10026         {
10027           if (attribute_flag[0] != 0)
10028             {
10029               flags=ParseGeometry(argument_list[0].string_reference,
10030                 &geometry_info);
10031             }
10032           if (attribute_flag[1] != 0)
10033             geometry_info.rho=argument_list[1].real_reference;
10034           if (attribute_flag[2] != 0)
10035             channel=(ChannelType) argument_list[2].integer_reference;
10036           channel_mask=SetImageChannelMask(image,channel);
10037           image=RotationalBlurImage(image,geometry_info.rho,exception);
10038           if (image != (Image *) NULL)
10039             (void) SetImageChannelMask(image,channel_mask);
10040           break;
10041         }
10042         case 83:  /* Thumbnail */
10043         {
10044           if (attribute_flag[0] != 0)
10045             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10046               &geometry,exception);
10047           if (attribute_flag[1] != 0)
10048             geometry.width=argument_list[1].integer_reference;
10049           if (attribute_flag[2] != 0)
10050             geometry.height=argument_list[2].integer_reference;
10051           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10052           break;
10053         }
10054         case 84:  /* Strip */
10055         {
10056           (void) StripImage(image,exception);
10057           break;
10058         }
10059         case 85:  /* Tint */
10060         {
10061           PixelInfo
10062             tint;
10063
10064           GetPixelInfo(image,&tint);
10065           if (attribute_flag[0] != 0)
10066             (void) QueryColorCompliance(argument_list[0].string_reference,
10067               AllCompliance,&tint,exception);
10068           if (attribute_flag[1] == 0)
10069             argument_list[1].string_reference="100";
10070           image=TintImage(image,argument_list[1].string_reference,&tint,
10071             exception);
10072           break;
10073         }
10074         case 86:  /* Channel */
10075         {
10076           if (attribute_flag[0] != 0)
10077             channel=(ChannelType) argument_list[0].integer_reference;
10078           image=SeparateImage(image,channel,exception);
10079           break;
10080         }
10081         case 87:  /* Splice */
10082         {
10083           if (attribute_flag[7] != 0)
10084             image->gravity=(GravityType) argument_list[7].integer_reference;
10085           if (attribute_flag[0] != 0)
10086             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10087               &geometry,exception);
10088           if (attribute_flag[1] != 0)
10089             geometry.width=argument_list[1].integer_reference;
10090           if (attribute_flag[2] != 0)
10091             geometry.height=argument_list[2].integer_reference;
10092           if (attribute_flag[3] != 0)
10093             geometry.x=argument_list[3].integer_reference;
10094           if (attribute_flag[4] != 0)
10095             geometry.y=argument_list[4].integer_reference;
10096           if (attribute_flag[5] != 0)
10097             image->fuzz=StringToDoubleInterval(
10098               argument_list[5].string_reference,(double) QuantumRange+1.0);
10099           if (attribute_flag[6] != 0)
10100             (void) QueryColorCompliance(argument_list[6].string_reference,
10101               AllCompliance,&image->background_color,exception);
10102           image=SpliceImage(image,&geometry,exception);
10103           break;
10104         }
10105         case 88:  /* Posterize */
10106         {
10107           if (attribute_flag[0] == 0)
10108             argument_list[0].integer_reference=3;
10109           if (attribute_flag[1] == 0)
10110             argument_list[1].integer_reference=0;
10111           (void) PosterizeImage(image,argument_list[0].integer_reference,
10112             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10113             NoDitherMethod,exception);
10114           break;
10115         }
10116         case 89:  /* Shadow */
10117         {
10118           if (attribute_flag[0] != 0)
10119             {
10120               flags=ParseGeometry(argument_list[0].string_reference,
10121                 &geometry_info);
10122               if ((flags & SigmaValue) == 0)
10123                 geometry_info.sigma=1.0;
10124               if ((flags & XiValue) == 0)
10125                 geometry_info.xi=4.0;
10126               if ((flags & PsiValue) == 0)
10127                 geometry_info.psi=4.0;
10128             }
10129           if (attribute_flag[1] != 0)
10130             geometry_info.rho=argument_list[1].real_reference;
10131           if (attribute_flag[2] != 0)
10132             geometry_info.sigma=argument_list[2].real_reference;
10133           if (attribute_flag[3] != 0)
10134             geometry_info.xi=argument_list[3].integer_reference;
10135           if (attribute_flag[4] != 0)
10136             geometry_info.psi=argument_list[4].integer_reference;
10137           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10138             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10139             ceil(geometry_info.psi-0.5),exception);
10140           break;
10141         }
10142         case 90:  /* Identify */
10143         {
10144           if (attribute_flag[0] == 0)
10145             argument_list[0].file_reference=(FILE *) NULL;
10146           if (attribute_flag[1] != 0)
10147             (void) SetImageArtifact(image,"identify:features",
10148               argument_list[1].string_reference);
10149           if ((attribute_flag[2] != 0) &&
10150               (argument_list[2].integer_reference != 0))
10151             (void) SetImageArtifact(image,"identify:unique","true");
10152           (void) IdentifyImage(image,argument_list[0].file_reference,
10153             MagickTrue,exception);
10154           break;
10155         }
10156         case 91:  /* SepiaTone */
10157         {
10158           if (attribute_flag[0] == 0)
10159             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10160           image=SepiaToneImage(image,argument_list[0].real_reference,
10161             exception);
10162           break;
10163         }
10164         case 92:  /* SigmoidalContrast */
10165         {
10166           MagickBooleanType
10167             sharpen;
10168
10169           if (attribute_flag[0] != 0)
10170             {
10171               flags=ParseGeometry(argument_list[0].string_reference,
10172                 &geometry_info);
10173               if ((flags & SigmaValue) == 0)
10174                 geometry_info.sigma=QuantumRange/2.0;
10175               if ((flags & PercentValue) != 0)
10176                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10177             }
10178           if (attribute_flag[1] != 0)
10179             geometry_info.rho=argument_list[1].real_reference;
10180           if (attribute_flag[2] != 0)
10181             geometry_info.sigma=argument_list[2].real_reference;
10182           if (attribute_flag[3] != 0)
10183             channel=(ChannelType) argument_list[3].integer_reference;
10184           sharpen=MagickTrue;
10185           if (attribute_flag[4] != 0)
10186             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10187               MagickFalse;
10188           channel_mask=SetImageChannelMask(image,channel);
10189           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10190             geometry_info.sigma,exception);
10191           (void) SetImageChannelMask(image,channel_mask);
10192           break;
10193         }
10194         case 93:  /* Extent */
10195         {
10196           if (attribute_flag[7] != 0)
10197             image->gravity=(GravityType) argument_list[7].integer_reference;
10198           if (attribute_flag[0] != 0)
10199             {
10200               int
10201                 flags;
10202
10203               flags=ParseGravityGeometry(image,
10204                 argument_list[0].string_reference,&geometry,exception);
10205               (void) flags;
10206               if (geometry.width == 0)
10207                 geometry.width=image->columns;
10208               if (geometry.height == 0)
10209                 geometry.height=image->rows;
10210             }
10211           if (attribute_flag[1] != 0)
10212             geometry.width=argument_list[1].integer_reference;
10213           if (attribute_flag[2] != 0)
10214             geometry.height=argument_list[2].integer_reference;
10215           if (attribute_flag[3] != 0)
10216             geometry.x=argument_list[3].integer_reference;
10217           if (attribute_flag[4] != 0)
10218             geometry.y=argument_list[4].integer_reference;
10219           if (attribute_flag[5] != 0)
10220             image->fuzz=StringToDoubleInterval(
10221               argument_list[5].string_reference,(double) QuantumRange+1.0);
10222           if (attribute_flag[6] != 0)
10223             (void) QueryColorCompliance(argument_list[6].string_reference,
10224               AllCompliance,&image->background_color,exception);
10225           image=ExtentImage(image,&geometry,exception);
10226           break;
10227         }
10228         case 94:  /* Vignette */
10229         {
10230           if (attribute_flag[0] != 0)
10231             {
10232               flags=ParseGeometry(argument_list[0].string_reference,
10233                 &geometry_info);
10234               if ((flags & SigmaValue) == 0)
10235                 geometry_info.sigma=1.0;
10236               if ((flags & XiValue) == 0)
10237                 geometry_info.xi=0.1*image->columns;
10238               if ((flags & PsiValue) == 0)
10239                 geometry_info.psi=0.1*image->rows;
10240             }
10241           if (attribute_flag[1] != 0)
10242             geometry_info.rho=argument_list[1].real_reference;
10243           if (attribute_flag[2] != 0)
10244             geometry_info.sigma=argument_list[2].real_reference;
10245           if (attribute_flag[3] != 0)
10246             geometry_info.xi=argument_list[3].integer_reference;
10247           if (attribute_flag[4] != 0)
10248             geometry_info.psi=argument_list[4].integer_reference;
10249           if (attribute_flag[5] != 0)
10250             (void) QueryColorCompliance(argument_list[5].string_reference,
10251               AllCompliance,&image->background_color,exception);
10252           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10253             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10254             ceil(geometry_info.psi-0.5),exception);
10255           break;
10256         }
10257         case 95:  /* ContrastStretch */
10258         {
10259           double
10260             black_point,
10261             white_point;
10262
10263           black_point=0.0;
10264           white_point=(double) image->columns*image->rows;
10265           if (attribute_flag[0] != 0)
10266             {
10267               flags=ParseGeometry(argument_list[0].string_reference,
10268                 &geometry_info);
10269               black_point=geometry_info.rho;
10270               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10271                 black_point;
10272               if ((flags & PercentValue) != 0)
10273                 {
10274                   black_point*=(double) image->columns*image->rows/100.0;
10275                   white_point*=(double) image->columns*image->rows/100.0;
10276                 }
10277               white_point=(double) image->columns*image->rows-
10278                 white_point;
10279             }
10280           if (attribute_flag[1] != 0)
10281             black_point=argument_list[1].real_reference;
10282           if (attribute_flag[2] != 0)
10283             white_point=argument_list[2].real_reference;
10284           if (attribute_flag[4] != 0)
10285             channel=(ChannelType) argument_list[4].integer_reference;
10286           channel_mask=SetImageChannelMask(image,channel);
10287           (void) ContrastStretchImage(image,black_point,white_point,exception);
10288           (void) SetImageChannelMask(image,channel_mask);
10289           break;
10290         }
10291         case 96:  /* Sans0 */
10292         {
10293           break;
10294         }
10295         case 97:  /* Sans1 */
10296         {
10297           break;
10298         }
10299         case 98:  /* AdaptiveSharpen */
10300         {
10301           if (attribute_flag[0] != 0)
10302             {
10303               flags=ParseGeometry(argument_list[0].string_reference,
10304                 &geometry_info);
10305               if ((flags & SigmaValue) == 0)
10306                 geometry_info.sigma=1.0;
10307               if ((flags & XiValue) == 0)
10308                 geometry_info.xi=0.0;
10309             }
10310           if (attribute_flag[1] != 0)
10311             geometry_info.rho=argument_list[1].real_reference;
10312           if (attribute_flag[2] != 0)
10313             geometry_info.sigma=argument_list[2].real_reference;
10314           if (attribute_flag[3] != 0)
10315             geometry_info.xi=argument_list[3].real_reference;
10316           if (attribute_flag[4] != 0)
10317             channel=(ChannelType) argument_list[4].integer_reference;
10318           channel_mask=SetImageChannelMask(image,channel);
10319           image=AdaptiveSharpenImage(image,geometry_info.rho,
10320             geometry_info.sigma,exception);
10321           if (image != (Image *) NULL)
10322             (void) SetImageChannelMask(image,channel_mask);
10323           break;
10324         }
10325         case 99:  /* Transpose */
10326         {
10327           image=TransposeImage(image,exception);
10328           break;
10329         }
10330         case 100:  /* Tranverse */
10331         {
10332           image=TransverseImage(image,exception);
10333           break;
10334         }
10335         case 101:  /* AutoOrient */
10336         {
10337           image=AutoOrientImage(image,image->orientation,exception);
10338           break;
10339         }
10340         case 102:  /* AdaptiveBlur */
10341         {
10342           if (attribute_flag[0] != 0)
10343             {
10344               flags=ParseGeometry(argument_list[0].string_reference,
10345                 &geometry_info);
10346               if ((flags & SigmaValue) == 0)
10347                 geometry_info.sigma=1.0;
10348               if ((flags & XiValue) == 0)
10349                 geometry_info.xi=0.0;
10350             }
10351           if (attribute_flag[1] != 0)
10352             geometry_info.rho=argument_list[1].real_reference;
10353           if (attribute_flag[2] != 0)
10354             geometry_info.sigma=argument_list[2].real_reference;
10355           if (attribute_flag[3] != 0)
10356             channel=(ChannelType) argument_list[3].integer_reference;
10357           channel_mask=SetImageChannelMask(image,channel);
10358           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10359             exception);
10360           if (image != (Image *) NULL)
10361             (void) SetImageChannelMask(image,channel_mask);
10362           break;
10363         }
10364         case 103:  /* Sketch */
10365         {
10366           if (attribute_flag[0] != 0)
10367             {
10368               flags=ParseGeometry(argument_list[0].string_reference,
10369                 &geometry_info);
10370               if ((flags & SigmaValue) == 0)
10371                 geometry_info.sigma=1.0;
10372               if ((flags & XiValue) == 0)
10373                 geometry_info.xi=1.0;
10374             }
10375           if (attribute_flag[1] != 0)
10376             geometry_info.rho=argument_list[1].real_reference;
10377           if (attribute_flag[2] != 0)
10378             geometry_info.sigma=argument_list[2].real_reference;
10379           if (attribute_flag[3] != 0)
10380             geometry_info.xi=argument_list[3].real_reference;
10381           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10382             geometry_info.xi,exception);
10383           break;
10384         }
10385         case 104:  /* UniqueColors */
10386         {
10387           image=UniqueImageColors(image,exception);
10388           break;
10389         }
10390         case 105:  /* AdaptiveResize */
10391         {
10392           if (attribute_flag[0] != 0)
10393             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10394               &geometry,exception);
10395           if (attribute_flag[1] != 0)
10396             geometry.width=argument_list[1].integer_reference;
10397           if (attribute_flag[2] != 0)
10398             geometry.height=argument_list[2].integer_reference;
10399           if (attribute_flag[3] != 0)
10400             image->filter=(FilterTypes) argument_list[4].integer_reference;
10401           if (attribute_flag[4] != 0)
10402             SetImageArtifact(image,"filter:support",
10403               argument_list[4].string_reference);
10404           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10405             exception);
10406           break;
10407         }
10408         case 106:  /* ClipMask */
10409         {
10410           Image
10411             *mask_image;
10412
10413           if (attribute_flag[0] == 0)
10414             {
10415               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10416                 PackageName);
10417               goto PerlException;
10418             }
10419           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10420             exception);
10421           (void) SetImageMask(image,mask_image,exception);
10422           mask_image=DestroyImage(mask_image);
10423           break;
10424         }
10425         case 107:  /* LinearStretch */
10426         {
10427            double
10428              black_point,
10429              white_point;
10430
10431            black_point=0.0;
10432            white_point=(double) image->columns*image->rows;
10433            if (attribute_flag[0] != 0)
10434              {
10435                flags=ParseGeometry(argument_list[0].string_reference,
10436                  &geometry_info);
10437                if ((flags & SigmaValue) != 0)
10438                   white_point=geometry_info.sigma;
10439                if ((flags & PercentValue) != 0)
10440                  {
10441                    black_point*=(double) image->columns*image->rows/100.0;
10442                    white_point*=(double) image->columns*image->rows/100.0;
10443                  }
10444                if ((flags & SigmaValue) == 0)
10445                  white_point=(double) image->columns*image->rows-black_point;
10446              }
10447           if (attribute_flag[1] != 0)
10448             black_point=argument_list[1].real_reference;
10449           if (attribute_flag[2] != 0)
10450             white_point=argument_list[2].real_reference;
10451           (void) LinearStretchImage(image,black_point,white_point,exception);
10452           break;
10453         }
10454         case 108:  /* ColorMatrix */
10455         {
10456           AV
10457             *av;
10458
10459           double
10460             *color_matrix;
10461
10462           KernelInfo
10463             *kernel_info;
10464
10465           size_t
10466             order;
10467
10468           if (attribute_flag[0] == 0)
10469             break;
10470           av=(AV *) argument_list[0].array_reference;
10471           order=(size_t) sqrt(av_len(av)+1);
10472           color_matrix=(double *) AcquireQuantumMemory(order,order*
10473             sizeof(*color_matrix));
10474           if (color_matrix == (double *) NULL)
10475             {
10476               ThrowPerlException(exception,ResourceLimitFatalError,
10477                 "MemoryAllocationFailed",PackageName);
10478               goto PerlException;
10479            }
10480           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10481             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10482           for ( ; j < (ssize_t) (order*order); j++)
10483             color_matrix[j]=0.0;
10484           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10485           if (kernel_info == (KernelInfo *) NULL)
10486             break;
10487           kernel_info->width=order;
10488           kernel_info->height=order;
10489           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10490             order*sizeof(*kernel_info->values));
10491           if (kernel_info->values != (MagickRealType *) NULL)
10492             {
10493               for (i=0; i < (ssize_t) (order*order); i++)
10494                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10495               image=ColorMatrixImage(image,kernel_info,exception);
10496             }
10497           kernel_info=DestroyKernelInfo(kernel_info);
10498           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10499           break;
10500         }
10501         case 109:  /* Mask */
10502         {
10503           Image
10504             *mask_image;
10505
10506           if (attribute_flag[0] == 0)
10507             {
10508               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10509                 PackageName);
10510               goto PerlException;
10511             }
10512           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10513             MagickTrue,exception);
10514           (void) SetImageMask(image,mask_image,exception);
10515           mask_image=DestroyImage(mask_image);
10516           break;
10517         }
10518         case 110:  /* Polaroid */
10519         {
10520           char
10521             *caption;
10522
10523           DrawInfo
10524             *draw_info;
10525
10526           double
10527             angle;
10528
10529           PixelInterpolateMethod
10530             method;
10531
10532           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10533             (DrawInfo *) NULL);
10534           caption=(char *) NULL;
10535           if (attribute_flag[0] != 0)
10536             caption=InterpretImageProperties(info ? info->image_info :
10537               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10538               exception);
10539           angle=0.0;
10540           if (attribute_flag[1] != 0)
10541             angle=argument_list[1].real_reference;
10542           if (attribute_flag[2] != 0)
10543             (void) CloneString(&draw_info->font,
10544               argument_list[2].string_reference);
10545           if (attribute_flag[3] != 0)
10546             (void) QueryColorCompliance(argument_list[3].string_reference,
10547               AllCompliance,&draw_info->stroke,exception);
10548           if (attribute_flag[4] != 0)
10549             (void) QueryColorCompliance(argument_list[4].string_reference,
10550               AllCompliance,&draw_info->fill,exception);
10551           if (attribute_flag[5] != 0)
10552             draw_info->stroke_width=argument_list[5].real_reference;
10553           if (attribute_flag[6] != 0)
10554             draw_info->pointsize=argument_list[6].real_reference;
10555           if (attribute_flag[7] != 0)
10556             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10557           if (attribute_flag[8] != 0)
10558             (void) QueryColorCompliance(argument_list[8].string_reference,
10559               AllCompliance,&image->background_color,exception);
10560           method=UndefinedInterpolatePixel;
10561           if (attribute_flag[9] != 0)
10562             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10563           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10564           draw_info=DestroyDrawInfo(draw_info);
10565           if (caption != (char *) NULL)
10566             caption=DestroyString(caption);
10567           break;
10568         }
10569         case 111:  /* FloodfillPaint */
10570         {
10571           DrawInfo
10572             *draw_info;
10573
10574           MagickBooleanType
10575             invert;
10576
10577           PixelInfo
10578             target;
10579
10580           draw_info=CloneDrawInfo(info ? info->image_info :
10581             (ImageInfo *) NULL,(DrawInfo *) NULL);
10582           if (attribute_flag[0] != 0)
10583             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10584               &geometry,exception);
10585           if (attribute_flag[1] != 0)
10586             geometry.x=argument_list[1].integer_reference;
10587           if (attribute_flag[2] != 0)
10588             geometry.y=argument_list[2].integer_reference;
10589           if (attribute_flag[3] != 0)
10590             (void) QueryColorCompliance(argument_list[3].string_reference,
10591               AllCompliance,&draw_info->fill,exception);
10592           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10593             geometry.x,geometry.y,&target,exception);
10594           if (attribute_flag[4] != 0)
10595             QueryColorCompliance(argument_list[4].string_reference,
10596               AllCompliance,&target,exception);
10597           if (attribute_flag[5] != 0)
10598             image->fuzz=StringToDoubleInterval(
10599               argument_list[5].string_reference,(double) QuantumRange+1.0);
10600           if (attribute_flag[6] != 0)
10601             channel=(ChannelType) argument_list[6].integer_reference;
10602           invert=MagickFalse;
10603           if (attribute_flag[7] != 0)
10604             invert=(MagickBooleanType) argument_list[7].integer_reference;
10605           channel_mask=SetImageChannelMask(image,channel);
10606           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10607             geometry.y,invert,exception);
10608           (void) SetImageChannelMask(image,channel_mask);
10609           draw_info=DestroyDrawInfo(draw_info);
10610           break;
10611         }
10612         case 112:  /* Distort */
10613         {
10614           AV
10615             *av;
10616
10617           double
10618             *coordinates;
10619
10620           DistortImageMethod
10621             method;
10622
10623           size_t
10624             number_coordinates;
10625
10626           VirtualPixelMethod
10627             virtual_pixel;
10628
10629           if (attribute_flag[0] == 0)
10630             break;
10631           method=UndefinedDistortion;
10632           if (attribute_flag[1] != 0)
10633             method=(DistortImageMethod) argument_list[1].integer_reference;
10634           av=(AV *) argument_list[0].array_reference;
10635           number_coordinates=(size_t) av_len(av)+1;
10636           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10637             sizeof(*coordinates));
10638           if (coordinates == (double *) NULL)
10639             {
10640               ThrowPerlException(exception,ResourceLimitFatalError,
10641                 "MemoryAllocationFailed",PackageName);
10642               goto PerlException;
10643             }
10644           for (j=0; j < (ssize_t) number_coordinates; j++)
10645             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10646           virtual_pixel=UndefinedVirtualPixelMethod;
10647           if (attribute_flag[2] != 0)
10648             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10649               argument_list[2].integer_reference,exception);
10650           image=DistortImage(image,method,number_coordinates,coordinates,
10651             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10652             exception);
10653           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10654             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10655               exception);
10656           coordinates=(double *) RelinquishMagickMemory(coordinates);
10657           break;
10658         }
10659         case 113:  /* Clut */
10660         {
10661           PixelInterpolateMethod
10662             method;
10663
10664           if (attribute_flag[0] == 0)
10665             {
10666               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10667                 PackageName);
10668               goto PerlException;
10669             }
10670           method=UndefinedInterpolatePixel;
10671           if (attribute_flag[1] != 0)
10672             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10673           if (attribute_flag[2] != 0)
10674             channel=(ChannelType) argument_list[2].integer_reference;
10675           channel_mask=SetImageChannelMask(image,channel);
10676           (void) ClutImage(image,argument_list[0].image_reference,method,
10677             exception);
10678           (void) SetImageChannelMask(image,channel_mask);
10679           break;
10680         }
10681         case 114:  /* LiquidRescale */
10682         {
10683           if (attribute_flag[0] != 0)
10684             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10685               &geometry,exception);
10686           if (attribute_flag[1] != 0)
10687             geometry.width=argument_list[1].integer_reference;
10688           if (attribute_flag[2] != 0)
10689             geometry.height=argument_list[2].integer_reference;
10690           if (attribute_flag[3] == 0)
10691             argument_list[3].real_reference=1.0;
10692           if (attribute_flag[4] == 0)
10693             argument_list[4].real_reference=0.0;
10694           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10695             argument_list[3].real_reference,argument_list[4].real_reference,
10696             exception);
10697           break;
10698         }
10699         case 115:  /* EncipherImage */
10700         {
10701           (void) EncipherImage(image,argument_list[0].string_reference,
10702             exception);
10703           break;
10704         }
10705         case 116:  /* DecipherImage */
10706         {
10707           (void) DecipherImage(image,argument_list[0].string_reference,
10708             exception);
10709           break;
10710         }
10711         case 117:  /* Deskew */
10712         {
10713           geometry_info.rho=QuantumRange/2.0;
10714           if (attribute_flag[0] != 0)
10715             flags=ParseGeometry(argument_list[0].string_reference,
10716               &geometry_info);
10717           if (attribute_flag[1] != 0)
10718             geometry_info.rho=StringToDoubleInterval(
10719               argument_list[1].string_reference,(double) QuantumRange+1.0);
10720           image=DeskewImage(image,geometry_info.rho,exception);
10721           break;
10722         }
10723         case 118:  /* Remap */
10724         {
10725           QuantizeInfo
10726             *quantize_info;
10727
10728           if (attribute_flag[0] == 0)
10729             {
10730               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10731                 PackageName);
10732               goto PerlException;
10733             }
10734           quantize_info=AcquireQuantizeInfo(info->image_info);
10735           if (attribute_flag[1] != 0)
10736             quantize_info->dither_method=(DitherMethod)
10737               argument_list[1].integer_reference;
10738           (void) RemapImages(quantize_info,image,
10739             argument_list[0].image_reference,exception);
10740           quantize_info=DestroyQuantizeInfo(quantize_info);
10741           break;
10742         }
10743         case 119:  /* SparseColor */
10744         {
10745           AV
10746             *av;
10747
10748           double
10749             *coordinates;
10750
10751           SparseColorMethod
10752             method;
10753
10754           size_t
10755             number_coordinates;
10756
10757           VirtualPixelMethod
10758             virtual_pixel;
10759
10760           if (attribute_flag[0] == 0)
10761             break;
10762           method=UndefinedColorInterpolate;
10763           if (attribute_flag[1] != 0)
10764             method=(SparseColorMethod) argument_list[1].integer_reference;
10765           av=(AV *) argument_list[0].array_reference;
10766           number_coordinates=(size_t) av_len(av)+1;
10767           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10768             sizeof(*coordinates));
10769           if (coordinates == (double *) NULL)
10770             {
10771               ThrowPerlException(exception,ResourceLimitFatalError,
10772                 "MemoryAllocationFailed",PackageName);
10773               goto PerlException;
10774             }
10775           for (j=0; j < (ssize_t) number_coordinates; j++)
10776             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10777           virtual_pixel=UndefinedVirtualPixelMethod;
10778           if (attribute_flag[2] != 0)
10779             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10780               argument_list[2].integer_reference,exception);
10781           if (attribute_flag[3] != 0)
10782             channel=(ChannelType) argument_list[3].integer_reference;
10783           channel_mask=SetImageChannelMask(image,channel);
10784           image=SparseColorImage(image,method,number_coordinates,coordinates,
10785             exception);
10786           if (image != (Image *) NULL)
10787             (void) SetImageChannelMask(image,channel_mask);
10788           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10789             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10790               exception);
10791           coordinates=(double *) RelinquishMagickMemory(coordinates);
10792           break;
10793         }
10794         case 120:  /* Function */
10795         {
10796           AV
10797             *av;
10798
10799           double
10800             *parameters;
10801
10802           MagickFunction
10803             function;
10804
10805           size_t
10806             number_parameters;
10807
10808           VirtualPixelMethod
10809             virtual_pixel;
10810
10811           if (attribute_flag[0] == 0)
10812             break;
10813           function=UndefinedFunction;
10814           if (attribute_flag[1] != 0)
10815             function=(MagickFunction) argument_list[1].integer_reference;
10816           av=(AV *) argument_list[0].array_reference;
10817           number_parameters=(size_t) av_len(av)+1;
10818           parameters=(double *) AcquireQuantumMemory(number_parameters,
10819             sizeof(*parameters));
10820           if (parameters == (double *) NULL)
10821             {
10822               ThrowPerlException(exception,ResourceLimitFatalError,
10823                 "MemoryAllocationFailed",PackageName);
10824               goto PerlException;
10825             }
10826           for (j=0; j < (ssize_t) number_parameters; j++)
10827             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10828           virtual_pixel=UndefinedVirtualPixelMethod;
10829           if (attribute_flag[2] != 0)
10830             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10831               argument_list[2].integer_reference,exception);
10832           (void) FunctionImage(image,function,number_parameters,parameters,
10833             exception);
10834           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10835             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10836               exception);
10837           parameters=(double *) RelinquishMagickMemory(parameters);
10838           break;
10839         }
10840         case 121:  /* SelectiveBlur */
10841         {
10842           if (attribute_flag[0] != 0)
10843             {
10844               flags=ParseGeometry(argument_list[0].string_reference,
10845                 &geometry_info);
10846               if ((flags & SigmaValue) == 0)
10847                 geometry_info.sigma=1.0;
10848               if ((flags & PercentValue) != 0)
10849                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10850             }
10851           if (attribute_flag[1] != 0)
10852             geometry_info.rho=argument_list[1].real_reference;
10853           if (attribute_flag[2] != 0)
10854             geometry_info.sigma=argument_list[2].real_reference;
10855           if (attribute_flag[3] != 0)
10856             geometry_info.xi=argument_list[3].integer_reference;;
10857           if (attribute_flag[5] != 0)
10858             channel=(ChannelType) argument_list[5].integer_reference;
10859           channel_mask=SetImageChannelMask(image,channel);
10860           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10861             geometry_info.xi,exception);
10862           if (image != (Image *) NULL)
10863             (void) SetImageChannelMask(image,channel_mask);
10864           break;
10865         }
10866         case 122:  /* HaldClut */
10867         {
10868           if (attribute_flag[0] == 0)
10869             {
10870               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10871                 PackageName);
10872               goto PerlException;
10873             }
10874           if (attribute_flag[1] != 0)
10875             channel=(ChannelType) argument_list[1].integer_reference;
10876           channel_mask=SetImageChannelMask(image,channel);
10877           (void) HaldClutImage(image,argument_list[0].image_reference,
10878             exception);
10879           (void) SetImageChannelMask(image,channel_mask);
10880           break;
10881         }
10882         case 123:  /* BlueShift */
10883         {
10884           if (attribute_flag[0] != 0)
10885             (void) ParseGeometry(argument_list[0].string_reference,
10886               &geometry_info);
10887           image=BlueShiftImage(image,geometry_info.rho,exception);
10888           break;
10889         }
10890         case 124:  /* ForwardFourierTransformImage */
10891         {
10892           image=ForwardFourierTransformImage(image,
10893             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10894             exception);
10895           break;
10896         }
10897         case 125:  /* InverseFourierTransformImage */
10898         {
10899           image=InverseFourierTransformImage(image,image->next,
10900             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10901             exception);
10902           break;
10903         }
10904         case 126:  /* ColorDecisionList */
10905         {
10906           if (attribute_flag[0] == 0)
10907             argument_list[0].string_reference=(char *) NULL;
10908           (void) ColorDecisionListImage(image,
10909             argument_list[0].string_reference,exception);
10910           break;
10911         }
10912         case 127:  /* AutoGamma */
10913         {
10914           if (attribute_flag[0] != 0)
10915             channel=(ChannelType) argument_list[0].integer_reference;
10916           channel_mask=SetImageChannelMask(image,channel);
10917           (void) AutoGammaImage(image,exception);
10918           (void) SetImageChannelMask(image,channel_mask);
10919           break;
10920         }
10921         case 128:  /* AutoLevel */
10922         {
10923           if (attribute_flag[0] != 0)
10924             channel=(ChannelType) argument_list[0].integer_reference;
10925           channel_mask=SetImageChannelMask(image,channel);
10926           (void) AutoLevelImage(image,exception);
10927           (void) SetImageChannelMask(image,channel_mask);
10928           break;
10929         }
10930         case 129:  /* LevelColors */
10931         {
10932           PixelInfo
10933             black_point,
10934             white_point;
10935
10936           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10937             exception);
10938           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10939             exception);
10940           if (attribute_flag[1] != 0)
10941              (void) QueryColorCompliance(
10942                argument_list[1].string_reference,AllCompliance,&black_point,
10943                exception);
10944           if (attribute_flag[2] != 0)
10945              (void) QueryColorCompliance(
10946                argument_list[2].string_reference,AllCompliance,&white_point,
10947                exception);
10948           if (attribute_flag[3] != 0)
10949             channel=(ChannelType) argument_list[3].integer_reference;
10950           channel_mask=SetImageChannelMask(image,channel);
10951           (void) LevelImageColors(image,&black_point,&white_point,
10952             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10953             exception);
10954           (void) SetImageChannelMask(image,channel_mask);
10955           break;
10956         }
10957         case 130:  /* Clamp */
10958         {
10959           if (attribute_flag[0] != 0)
10960             channel=(ChannelType) argument_list[0].integer_reference;
10961           channel_mask=SetImageChannelMask(image,channel);
10962           (void) ClampImage(image,exception);
10963           (void) SetImageChannelMask(image,channel_mask);
10964           break;
10965         }
10966         case 131:  /* BrightnessContrast */
10967         {
10968           double
10969             brightness,
10970             contrast;
10971
10972           brightness=0.0;
10973           contrast=0.0;
10974           if (attribute_flag[0] != 0)
10975             {
10976               flags=ParseGeometry(argument_list[0].string_reference,
10977                 &geometry_info);
10978               brightness=geometry_info.rho;
10979               if ((flags & SigmaValue) == 0)
10980                 contrast=geometry_info.sigma;
10981             }
10982           if (attribute_flag[1] != 0)
10983             brightness=argument_list[1].real_reference;
10984           if (attribute_flag[2] != 0)
10985             contrast=argument_list[2].real_reference;
10986           if (attribute_flag[4] != 0)
10987             channel=(ChannelType) argument_list[4].integer_reference;
10988           channel_mask=SetImageChannelMask(image,channel);
10989           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10990           (void) SetImageChannelMask(image,channel_mask);
10991           break;
10992         }
10993         case 132:  /* Morphology */
10994         {
10995           KernelInfo
10996             *kernel;
10997
10998           MorphologyMethod
10999             method;
11000
11001           ssize_t
11002             iterations;
11003
11004           if (attribute_flag[0] == 0)
11005             break;
11006           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11007           if (kernel == (KernelInfo *) NULL)
11008             break;
11009           if (attribute_flag[1] != 0)
11010             channel=(ChannelType) argument_list[1].integer_reference;
11011           method=UndefinedMorphology;
11012           if (attribute_flag[2] != 0)
11013             method=argument_list[2].integer_reference;
11014           iterations=1;
11015           if (attribute_flag[3] != 0)
11016             iterations=argument_list[3].integer_reference;
11017           channel_mask=SetImageChannelMask(image,channel);
11018           image=MorphologyImage(image,method,iterations,kernel,exception);
11019           if (image != (Image *) NULL)
11020             (void) SetImageChannelMask(image,channel_mask);
11021           kernel=DestroyKernelInfo(kernel);
11022           break;
11023         }
11024         case 133:  /* Mode */
11025         {
11026           if (attribute_flag[0] != 0)
11027             {
11028               flags=ParseGeometry(argument_list[0].string_reference,
11029                 &geometry_info);
11030               if ((flags & SigmaValue) == 0)
11031                 geometry_info.sigma=1.0;
11032             }
11033           if (attribute_flag[1] != 0)
11034             geometry_info.rho=argument_list[1].real_reference;
11035           if (attribute_flag[2] != 0)
11036             geometry_info.sigma=argument_list[2].real_reference;
11037           if (attribute_flag[3] != 0)
11038             channel=(ChannelType) argument_list[3].integer_reference;
11039           channel_mask=SetImageChannelMask(image,channel);
11040           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11041             (size_t) geometry_info.sigma,exception);
11042           if (image != (Image *) NULL)
11043             (void) SetImageChannelMask(image,channel_mask);
11044           break;
11045         }
11046         case 134:  /* Statistic */
11047         {
11048           StatisticType
11049             statistic;
11050
11051           statistic=UndefinedStatistic;
11052           if (attribute_flag[0] != 0)
11053             {
11054               flags=ParseGeometry(argument_list[0].string_reference,
11055                 &geometry_info);
11056               if ((flags & SigmaValue) == 0)
11057                 geometry_info.sigma=1.0;
11058             }
11059           if (attribute_flag[1] != 0)
11060             geometry_info.rho=argument_list[1].real_reference;
11061           if (attribute_flag[2] != 0)
11062             geometry_info.sigma=argument_list[2].real_reference;
11063           if (attribute_flag[3] != 0)
11064             channel=(ChannelType) argument_list[3].integer_reference;
11065           if (attribute_flag[4] != 0)
11066             statistic=(StatisticType) argument_list[4].integer_reference;
11067           channel_mask=SetImageChannelMask(image,channel);
11068           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11069             (size_t) geometry_info.sigma,exception);
11070           if (image != (Image *) NULL)
11071             (void) SetImageChannelMask(image,channel_mask);
11072           break;
11073         }
11074         case 135:  /* Perceptible */
11075         {
11076           double
11077             epsilon;
11078
11079           epsilon=MagickEpsilon;
11080           if (attribute_flag[0] != 0)
11081             epsilon=argument_list[0].real_reference;
11082           if (attribute_flag[1] != 0)
11083             channel=(ChannelType) argument_list[1].integer_reference;
11084           channel_mask=SetImageChannelMask(image,channel);
11085           (void) PerceptibleImage(image,epsilon,exception);
11086           (void) SetImageChannelMask(image,channel_mask);
11087           break;
11088         }
11089         case 136:  /* Poly */
11090         {
11091           AV
11092             *av;
11093
11094           double
11095             *terms;
11096
11097           size_t
11098             number_terms;
11099
11100           if (attribute_flag[0] == 0)
11101             break;
11102           if (attribute_flag[1] != 0)
11103             channel=(ChannelType) argument_list[1].integer_reference;
11104           av=(AV *) argument_list[0].array_reference;
11105           number_terms=(size_t) av_len(av);
11106           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11107           if (terms == (double *) NULL)
11108             {
11109               ThrowPerlException(exception,ResourceLimitFatalError,
11110                 "MemoryAllocationFailed",PackageName);
11111               goto PerlException;
11112             }
11113           for (j=0; j < av_len(av); j++)
11114             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11115           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11116           terms=(double *) RelinquishMagickMemory(terms);
11117           break;
11118         }
11119         case 137:  /* Grayscale */
11120         {
11121           PixelIntensityMethod
11122             method;
11123
11124           method=UndefinedPixelIntensityMethod;
11125           if (attribute_flag[0] != 0)
11126             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11127           (void) GrayscaleImage(image,method,exception);
11128           break;
11129         }
11130         case 138:  /* Canny */
11131         {
11132           if (attribute_flag[0] != 0)
11133             {
11134               flags=ParseGeometry(argument_list[0].string_reference,
11135                 &geometry_info);
11136               if ((flags & SigmaValue) == 0)
11137                 geometry_info.sigma=1.0;
11138               if ((flags & XiValue) == 0)
11139                 geometry_info.xi=0.10;
11140               if ((flags & PsiValue) == 0)
11141                 geometry_info.psi=0.30;
11142               if ((flags & PercentValue) != 0)
11143                 {
11144                   geometry_info.xi/=100.0;
11145                   geometry_info.psi/=100.0;
11146                 }
11147             }
11148           if (attribute_flag[1] != 0)
11149             geometry_info.rho=argument_list[1].real_reference;
11150           if (attribute_flag[2] != 0)
11151             geometry_info.sigma=argument_list[2].real_reference;
11152           if (attribute_flag[3] != 0)
11153             geometry_info.xi=argument_list[3].real_reference;
11154           if (attribute_flag[4] != 0)
11155             geometry_info.psi=argument_list[4].real_reference;
11156           if (attribute_flag[5] != 0)
11157             channel=(ChannelType) argument_list[5].integer_reference;
11158           channel_mask=SetImageChannelMask(image,channel);
11159           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11160             geometry_info.xi,geometry_info.psi,exception);
11161           if (image != (Image *) NULL)
11162             (void) SetImageChannelMask(image,channel_mask);
11163           break;
11164         }
11165         case 139:  /* HoughLine */
11166         {
11167           if (attribute_flag[0] != 0)
11168             {
11169               flags=ParseGeometry(argument_list[0].string_reference,
11170                 &geometry_info);
11171               if ((flags & SigmaValue) == 0)
11172                 geometry_info.sigma=geometry_info.rho;
11173               if ((flags & XiValue) == 0)
11174                 geometry_info.xi=40;
11175             }
11176           if (attribute_flag[1] != 0)
11177             geometry_info.rho=(double) argument_list[1].integer_reference;
11178           if (attribute_flag[2] != 0)
11179             geometry_info.sigma=(double) argument_list[2].integer_reference;
11180           if (attribute_flag[3] != 0)
11181             geometry_info.xi=(double) argument_list[3].integer_reference;
11182           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11183             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11184           break;
11185         }
11186         case 140:  /* MeanShift */
11187         {
11188           if (attribute_flag[0] != 0)
11189             {
11190               flags=ParseGeometry(argument_list[0].string_reference,
11191                 &geometry_info);
11192               if ((flags & SigmaValue) == 0)
11193                 geometry_info.sigma=geometry_info.rho;
11194               if ((flags & XiValue) == 0)
11195                 geometry_info.xi=0.10*QuantumRange;
11196               if ((flags & PercentValue) != 0)
11197                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11198             }
11199           if (attribute_flag[1] != 0)
11200             geometry_info.rho=(double) argument_list[1].integer_reference;
11201           if (attribute_flag[2] != 0)
11202             geometry_info.sigma=(double) argument_list[2].integer_reference;
11203           if (attribute_flag[3] != 0)
11204             geometry_info.xi=(double) argument_list[3].integer_reference;
11205           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11206             geometry_info.sigma,geometry_info.xi,exception);
11207           break;
11208         }
11209         case 141:  /* Kuwahara */
11210         {
11211           if (attribute_flag[0] != 0)
11212             {
11213               flags=ParseGeometry(argument_list[0].string_reference,
11214                 &geometry_info);
11215               if ((flags & SigmaValue) == 0)
11216                 geometry_info.sigma=geometry_info.rho-0.5;
11217             }
11218           if (attribute_flag[1] != 0)
11219             geometry_info.rho=argument_list[1].real_reference;
11220           if (attribute_flag[2] != 0)
11221             geometry_info.sigma=argument_list[2].real_reference;
11222           if (attribute_flag[3] != 0)
11223             channel=(ChannelType) argument_list[3].integer_reference;
11224           channel_mask=SetImageChannelMask(image,channel);
11225           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11226             exception);
11227           if (image != (Image *) NULL)
11228             (void) SetImageChannelMask(image,channel_mask);
11229           break;
11230         }
11231         case 142:  /* ConnectedComponent */
11232         {
11233           size_t
11234             connectivity;
11235
11236           connectivity=4;
11237           if (attribute_flag[0] != 0)
11238             connectivity=argument_list[0].integer_reference;
11239           image=ConnectedComponentsImage(image,connectivity,exception);
11240           break;
11241         }
11242         case 143:  /* Copy */
11243         {
11244           Image
11245             *source_image;
11246
11247           OffsetInfo
11248             offset;
11249
11250           source_image=image;
11251           if (attribute_flag[0] != 0)
11252             source_image=argument_list[0].image_reference;
11253           if (attribute_flag[1] != 0)
11254             flags=ParseGravityGeometry(image,argument_list[1].string_reference,
11255               &geometry,exception);
11256           if (attribute_flag[2] != 0)
11257             geometry.width=argument_list[2].integer_reference;
11258           if (attribute_flag[3] != 0)
11259             geometry.height=argument_list[3].integer_reference;
11260           if (attribute_flag[4] != 0)
11261             geometry.x=argument_list[4].integer_reference;
11262           if (attribute_flag[5] != 0)
11263             geometry.y=argument_list[5].integer_reference;
11264           if (attribute_flag[6] != 0)
11265             source_image->gravity=(GravityType)
11266               argument_list[6].integer_reference;
11267           if (attribute_flag[7] != 0)
11268             flags=ParseGravityGeometry(source_image,
11269               argument_list[0].string_reference,&offset,exception);
11270           offset.x=geometry.x;
11271           offset.y=geometry.y;
11272           if (attribute_flag[8] != 0)
11273             offset.x=argument_list[8].integer_reference;
11274           if (attribute_flag[9] != 0)
11275             offset.y=argument_list[9].integer_reference;
11276           source_image=image;
11277           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11278             exception);
11279           break;
11280         }
11281       }
11282       if (next != (Image *) NULL)
11283         (void) CatchImageException(next);
11284       if (region_image != (Image *) NULL)
11285         {
11286           /*
11287             Composite region.
11288           */
11289           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11290             region_info.x,region_info.y,exception);
11291           (void) status;
11292           (void) CatchImageException(region_image);
11293           image=DestroyImage(image);
11294           image=region_image;
11295         }
11296       if (image != (Image *) NULL)
11297         {
11298           number_images++;
11299           if (next && (next != image))
11300             {
11301               image->next=next->next;
11302               if (image->next != (Image *) NULL)
11303                 image->next->previous=image;
11304               DeleteImageFromRegistry(*pv,next);
11305             }
11306           sv_setiv(*pv,PTR2IV(image));
11307           next=image;
11308         }
11309       if (*pv)
11310         pv++;
11311     }
11312
11313   PerlException:
11314     if (reference_vector)
11315       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11316     InheritPerlException(exception,perl_exception);
11317     exception=DestroyExceptionInfo(exception);
11318     sv_setiv(perl_exception,(IV) number_images);
11319     SvPOK_on(perl_exception);
11320     ST(0)=sv_2mortal(perl_exception);
11321     XSRETURN(1);
11322   }
11323 \f
11324 #
11325 ###############################################################################
11326 #                                                                             #
11327 #                                                                             #
11328 #                                                                             #
11329 #   M o n t a g e                                                             #
11330 #                                                                             #
11331 #                                                                             #
11332 #                                                                             #
11333 ###############################################################################
11334 #
11335 #
11336 void
11337 Montage(ref,...)
11338   Image::Magick ref=NO_INIT
11339   ALIAS:
11340     MontageImage  = 1
11341     montage       = 2
11342     montageimage  = 3
11343   PPCODE:
11344   {
11345     AV
11346       *av;
11347
11348     char
11349       *attribute;
11350
11351     ExceptionInfo
11352       *exception;
11353
11354     HV
11355       *hv;
11356
11357     Image
11358       *image,
11359       *next;
11360
11361     PixelInfo
11362       transparent_color;
11363
11364     MontageInfo
11365       *montage_info;
11366
11367     register ssize_t
11368       i;
11369
11370     ssize_t
11371       sp;
11372
11373     struct PackageInfo
11374       *info;
11375
11376     SV
11377       *av_reference,
11378       *perl_exception,
11379       *reference,
11380       *rv,
11381       *sv;
11382
11383     PERL_UNUSED_VAR(ref);
11384     PERL_UNUSED_VAR(ix);
11385     exception=AcquireExceptionInfo();
11386     perl_exception=newSVpv("",0);
11387     sv=NULL;
11388     attribute=NULL;
11389     if (sv_isobject(ST(0)) == 0)
11390       {
11391         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11392           PackageName);
11393         goto PerlException;
11394       }
11395     reference=SvRV(ST(0));
11396     hv=SvSTASH(reference);
11397     av=newAV();
11398     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11399     SvREFCNT_dec(av);
11400     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11401     if (image == (Image *) NULL)
11402       {
11403         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11404           PackageName);
11405         goto PerlException;
11406       }
11407     /*
11408       Get options.
11409     */
11410     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11411     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11412     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11413       exception);
11414     for (i=2; i < items; i+=2)
11415     {
11416       attribute=(char *) SvPV(ST(i-1),na);
11417       switch (*attribute)
11418       {
11419         case 'B':
11420         case 'b':
11421         {
11422           if (LocaleCompare(attribute,"background") == 0)
11423             {
11424               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11425                 &montage_info->background_color,exception);
11426               for (next=image; next; next=next->next)
11427                 next->background_color=montage_info->background_color;
11428               break;
11429             }
11430           if (LocaleCompare(attribute,"border") == 0)
11431             {
11432               montage_info->border_width=SvIV(ST(i));
11433               break;
11434             }
11435           if (LocaleCompare(attribute,"bordercolor") == 0)
11436             {
11437               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11438                 &montage_info->border_color,exception);
11439               for (next=image; next; next=next->next)
11440                 next->border_color=montage_info->border_color;
11441               break;
11442             }
11443           if (LocaleCompare(attribute,"borderwidth") == 0)
11444             {
11445               montage_info->border_width=SvIV(ST(i));
11446               break;
11447             }
11448           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11449             attribute);
11450           break;
11451         }
11452         case 'C':
11453         case 'c':
11454         {
11455           if (LocaleCompare(attribute,"compose") == 0)
11456             {
11457               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11458                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11459               if (sp < 0)
11460                 {
11461                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11462                     SvPV(ST(i),na));
11463                   break;
11464                 }
11465               for (next=image; next; next=next->next)
11466                 next->compose=(CompositeOperator) sp;
11467               break;
11468             }
11469           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11470             attribute);
11471           break;
11472         }
11473         case 'F':
11474         case 'f':
11475         {
11476           if (LocaleCompare(attribute,"fill") == 0)
11477             {
11478               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11479                 &montage_info->fill,exception);
11480               break;
11481             }
11482           if (LocaleCompare(attribute,"font") == 0)
11483             {
11484               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11485               break;
11486             }
11487           if (LocaleCompare(attribute,"frame") == 0)
11488             {
11489               char
11490                 *p;
11491
11492               p=SvPV(ST(i),na);
11493               if (IsGeometry(p) == MagickFalse)
11494                 {
11495                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11496                     p);
11497                   break;
11498                 }
11499               (void) CloneString(&montage_info->frame,p);
11500               if (*p == '\0')
11501                 montage_info->frame=(char *) NULL;
11502               break;
11503             }
11504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11505             attribute);
11506           break;
11507         }
11508         case 'G':
11509         case 'g':
11510         {
11511           if (LocaleCompare(attribute,"geometry") == 0)
11512             {
11513               char
11514                 *p;
11515
11516               p=SvPV(ST(i),na);
11517               if (IsGeometry(p) == MagickFalse)
11518                 {
11519                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11520                     p);
11521                   break;
11522                 }
11523              (void) CloneString(&montage_info->geometry,p);
11524              if (*p == '\0')
11525                montage_info->geometry=(char *) NULL;
11526              break;
11527            }
11528          if (LocaleCompare(attribute,"gravity") == 0)
11529            {
11530              ssize_t
11531                in;
11532
11533              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11534                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11535              if (in < 0)
11536                {
11537                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11538                    SvPV(ST(i),na));
11539                  return;
11540                }
11541              montage_info->gravity=(GravityType) in;
11542              for (next=image; next; next=next->next)
11543                next->gravity=(GravityType) in;
11544              break;
11545            }
11546           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11547             attribute);
11548           break;
11549         }
11550         case 'L':
11551         case 'l':
11552         {
11553           if (LocaleCompare(attribute,"label") == 0)
11554             {
11555               for (next=image; next; next=next->next)
11556                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11557                   info ? info->image_info : (ImageInfo *) NULL,next,
11558                   SvPV(ST(i),na),exception),exception);
11559               break;
11560             }
11561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11562             attribute);
11563           break;
11564         }
11565         case 'M':
11566         case 'm':
11567         {
11568           if (LocaleCompare(attribute,"mattecolor") == 0)
11569             {
11570               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11571                 &montage_info->matte_color,exception);
11572               for (next=image; next; next=next->next)
11573                 next->matte_color=montage_info->matte_color;
11574               break;
11575             }
11576           if (LocaleCompare(attribute,"mode") == 0)
11577             {
11578               ssize_t
11579                 in;
11580
11581               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11582                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11583               switch (in)
11584               {
11585                 default:
11586                 {
11587                   ThrowPerlException(exception,OptionError,
11588                     "UnrecognizedModeType",SvPV(ST(i),na));
11589                   break;
11590                 }
11591                 case FrameMode:
11592                 {
11593                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11594                   montage_info->shadow=MagickTrue;
11595                   break;
11596                 }
11597                 case UnframeMode:
11598                 {
11599                   montage_info->frame=(char *) NULL;
11600                   montage_info->shadow=MagickFalse;
11601                   montage_info->border_width=0;
11602                   break;
11603                 }
11604                 case ConcatenateMode:
11605                 {
11606                   montage_info->frame=(char *) NULL;
11607                   montage_info->shadow=MagickFalse;
11608                   (void) CloneString(&montage_info->geometry,"+0+0");
11609                   montage_info->border_width=0;
11610                 }
11611               }
11612               break;
11613             }
11614           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11615             attribute);
11616           break;
11617         }
11618         case 'P':
11619         case 'p':
11620         {
11621           if (LocaleCompare(attribute,"pointsize") == 0)
11622             {
11623               montage_info->pointsize=SvIV(ST(i));
11624               break;
11625             }
11626           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11627             attribute);
11628           break;
11629         }
11630         case 'S':
11631         case 's':
11632         {
11633           if (LocaleCompare(attribute,"shadow") == 0)
11634             {
11635               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11636                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11637               if (sp < 0)
11638                 {
11639                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11640                     SvPV(ST(i),na));
11641                   break;
11642                 }
11643              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11644              break;
11645             }
11646           if (LocaleCompare(attribute,"stroke") == 0)
11647             {
11648               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11649                 &montage_info->stroke,exception);
11650               break;
11651             }
11652           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11653             attribute);
11654           break;
11655         }
11656         case 'T':
11657         case 't':
11658         {
11659           if (LocaleCompare(attribute,"texture") == 0)
11660             {
11661               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11662               break;
11663             }
11664           if (LocaleCompare(attribute,"tile") == 0)
11665             {
11666               char *p=SvPV(ST(i),na);
11667               if (IsGeometry(p) == MagickFalse)
11668                 {
11669                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11670                     p);
11671                   break;
11672                 }
11673               (void) CloneString(&montage_info->tile,p);
11674               if (*p == '\0')
11675                 montage_info->tile=(char *) NULL;
11676               break;
11677             }
11678           if (LocaleCompare(attribute,"title") == 0)
11679             {
11680               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11681               break;
11682             }
11683           if (LocaleCompare(attribute,"transparent") == 0)
11684             {
11685               PixelInfo
11686                 transparent_color;
11687
11688               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11689                 &transparent_color,exception);
11690               for (next=image; next; next=next->next)
11691                 (void) TransparentPaintImage(next,&transparent_color,
11692                   TransparentAlpha,MagickFalse,exception);
11693               break;
11694             }
11695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11696             attribute);
11697           break;
11698         }
11699         default:
11700         {
11701           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11702             attribute);
11703           break;
11704         }
11705       }
11706     }
11707     image=MontageImageList(info->image_info,montage_info,image,exception);
11708     montage_info=DestroyMontageInfo(montage_info);
11709     if (image == (Image *) NULL)
11710       goto PerlException;
11711     if (transparent_color.alpha != TransparentAlpha)
11712       for (next=image; next; next=next->next)
11713         (void) TransparentPaintImage(next,&transparent_color,
11714           TransparentAlpha,MagickFalse,exception);
11715     for (  ; image; image=image->next)
11716     {
11717       AddImageToRegistry(sv,image);
11718       rv=newRV(sv);
11719       av_push(av,sv_bless(rv,hv));
11720       SvREFCNT_dec(sv);
11721     }
11722     exception=DestroyExceptionInfo(exception);
11723     ST(0)=av_reference;
11724     SvREFCNT_dec(perl_exception);
11725     XSRETURN(1);
11726
11727   PerlException:
11728     InheritPerlException(exception,perl_exception);
11729     exception=DestroyExceptionInfo(exception);
11730     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11731     SvPOK_on(perl_exception);
11732     ST(0)=sv_2mortal(perl_exception);
11733     XSRETURN(1);
11734   }
11735 \f
11736 #
11737 ###############################################################################
11738 #                                                                             #
11739 #                                                                             #
11740 #                                                                             #
11741 #   M o r p h                                                                 #
11742 #                                                                             #
11743 #                                                                             #
11744 #                                                                             #
11745 ###############################################################################
11746 #
11747 #
11748 void
11749 Morph(ref,...)
11750   Image::Magick ref=NO_INIT
11751   ALIAS:
11752     MorphImage  = 1
11753     morph       = 2
11754     morphimage  = 3
11755   PPCODE:
11756   {
11757     AV
11758       *av;
11759
11760     char
11761       *attribute;
11762
11763     ExceptionInfo
11764       *exception;
11765
11766     HV
11767       *hv;
11768
11769     Image
11770       *image;
11771
11772     register ssize_t
11773       i;
11774
11775     ssize_t
11776       number_frames;
11777
11778     struct PackageInfo
11779       *info;
11780
11781     SV
11782       *av_reference,
11783       *perl_exception,
11784       *reference,
11785       *rv,
11786       *sv;
11787
11788     PERL_UNUSED_VAR(ref);
11789     PERL_UNUSED_VAR(ix);
11790     exception=AcquireExceptionInfo();
11791     perl_exception=newSVpv("",0);
11792     sv=NULL;
11793     av=NULL;
11794     attribute=NULL;
11795     if (sv_isobject(ST(0)) == 0)
11796       {
11797         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11798           PackageName);
11799         goto PerlException;
11800       }
11801     reference=SvRV(ST(0));
11802     hv=SvSTASH(reference);
11803     av=newAV();
11804     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11805     SvREFCNT_dec(av);
11806     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11807     if (image == (Image *) NULL)
11808       {
11809         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11810           PackageName);
11811         goto PerlException;
11812       }
11813     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11814     /*
11815       Get attribute.
11816     */
11817     number_frames=30;
11818     for (i=2; i < items; i+=2)
11819     {
11820       attribute=(char *) SvPV(ST(i-1),na);
11821       switch (*attribute)
11822       {
11823         case 'F':
11824         case 'f':
11825         {
11826           if (LocaleCompare(attribute,"frames") == 0)
11827             {
11828               number_frames=SvIV(ST(i));
11829               break;
11830             }
11831           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11832             attribute);
11833           break;
11834         }
11835         default:
11836         {
11837           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11838             attribute);
11839           break;
11840         }
11841       }
11842     }
11843     image=MorphImages(image,number_frames,exception);
11844     if (image == (Image *) NULL)
11845       goto PerlException;
11846     for ( ; image; image=image->next)
11847     {
11848       AddImageToRegistry(sv,image);
11849       rv=newRV(sv);
11850       av_push(av,sv_bless(rv,hv));
11851       SvREFCNT_dec(sv);
11852     }
11853     exception=DestroyExceptionInfo(exception);
11854     ST(0)=av_reference;
11855     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11856     XSRETURN(1);
11857
11858   PerlException:
11859     InheritPerlException(exception,perl_exception);
11860     exception=DestroyExceptionInfo(exception);
11861     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11862     SvPOK_on(perl_exception);
11863     ST(0)=sv_2mortal(perl_exception);
11864     XSRETURN(1);
11865   }
11866 \f
11867 #
11868 ###############################################################################
11869 #                                                                             #
11870 #                                                                             #
11871 #                                                                             #
11872 #   M o s a i c                                                               #
11873 #                                                                             #
11874 #                                                                             #
11875 #                                                                             #
11876 ###############################################################################
11877 #
11878 #
11879 void
11880 Mosaic(ref)
11881   Image::Magick ref=NO_INIT
11882   ALIAS:
11883     MosaicImage   = 1
11884     mosaic        = 2
11885     mosaicimage   = 3
11886   PPCODE:
11887   {
11888     AV
11889       *av;
11890
11891     ExceptionInfo
11892       *exception;
11893
11894     HV
11895       *hv;
11896
11897     Image
11898       *image;
11899
11900     struct PackageInfo
11901       *info;
11902
11903     SV
11904       *perl_exception,
11905       *reference,
11906       *rv,
11907       *sv;
11908
11909     PERL_UNUSED_VAR(ref);
11910     PERL_UNUSED_VAR(ix);
11911     exception=AcquireExceptionInfo();
11912     perl_exception=newSVpv("",0);
11913     sv=NULL;
11914     if (sv_isobject(ST(0)) == 0)
11915       {
11916         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11917           PackageName);
11918         goto PerlException;
11919       }
11920     reference=SvRV(ST(0));
11921     hv=SvSTASH(reference);
11922     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11923     if (image == (Image *) NULL)
11924       {
11925         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11926           PackageName);
11927         goto PerlException;
11928       }
11929     image=MergeImageLayers(image,MosaicLayer,exception);
11930     /*
11931       Create blessed Perl array for the returned image.
11932     */
11933     av=newAV();
11934     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11935     SvREFCNT_dec(av);
11936     AddImageToRegistry(sv,image);
11937     rv=newRV(sv);
11938     av_push(av,sv_bless(rv,hv));
11939     SvREFCNT_dec(sv);
11940     (void) CopyMagickString(info->image_info->filename,image->filename,
11941       MagickPathExtent);
11942     SetImageInfo(info->image_info,0,exception);
11943     exception=DestroyExceptionInfo(exception);
11944     SvREFCNT_dec(perl_exception);
11945     XSRETURN(1);
11946
11947   PerlException:
11948     InheritPerlException(exception,perl_exception);
11949     exception=DestroyExceptionInfo(exception);
11950     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11951     SvPOK_on(perl_exception);  /* return messages in string context */
11952     ST(0)=sv_2mortal(perl_exception);
11953     XSRETURN(1);
11954   }
11955 \f
11956 #
11957 ###############################################################################
11958 #                                                                             #
11959 #                                                                             #
11960 #                                                                             #
11961 #   P i n g                                                                   #
11962 #                                                                             #
11963 #                                                                             #
11964 #                                                                             #
11965 ###############################################################################
11966 #
11967 #
11968 void
11969 Ping(ref,...)
11970   Image::Magick ref=NO_INIT
11971   ALIAS:
11972     PingImage  = 1
11973     ping       = 2
11974     pingimage  = 3
11975   PPCODE:
11976   {
11977     AV
11978       *av;
11979
11980     char
11981       **keep,
11982       **list;
11983
11984     ExceptionInfo
11985       *exception;
11986
11987     Image
11988       *image,
11989       *next;
11990
11991     int
11992       n;
11993
11994     MagickBooleanType
11995       status;
11996
11997     register char
11998       **p;
11999
12000     register ssize_t
12001       i;
12002
12003     ssize_t
12004       ac;
12005
12006     STRLEN
12007       *length;
12008
12009     struct PackageInfo
12010       *info,
12011       *package_info;
12012
12013     SV
12014       *perl_exception,
12015       *reference;
12016
12017     size_t
12018       count;
12019
12020     PERL_UNUSED_VAR(ref);
12021     PERL_UNUSED_VAR(ix);
12022     exception=AcquireExceptionInfo();
12023     perl_exception=newSVpv("",0);
12024     package_info=(struct PackageInfo *) NULL;
12025     ac=(items < 2) ? 1 : items-1;
12026     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12027     keep=list;
12028     length=(STRLEN *) NULL;
12029     if (list == (char **) NULL)
12030       {
12031         ThrowPerlException(exception,ResourceLimitError,
12032           "MemoryAllocationFailed",PackageName);
12033         goto PerlException;
12034       }
12035     keep=list;
12036     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12037     if (length == (STRLEN *) NULL)
12038       {
12039         ThrowPerlException(exception,ResourceLimitError,
12040           "MemoryAllocationFailed",PackageName);
12041         goto PerlException;
12042       }
12043     if (sv_isobject(ST(0)) == 0)
12044       {
12045         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12046           PackageName);
12047         goto PerlException;
12048       }
12049     reference=SvRV(ST(0));
12050     if (SvTYPE(reference) != SVt_PVAV)
12051       {
12052         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12053           PackageName);
12054         goto PerlException;
12055       }
12056     av=(AV *) reference;
12057     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12058       exception);
12059     package_info=ClonePackageInfo(info,exception);
12060     n=1;
12061     if (items <= 1)
12062       *list=(char *) (*package_info->image_info->filename ?
12063         package_info->image_info->filename : "XC:black");
12064     else
12065       for (n=0, i=0; i < ac; i++)
12066       {
12067         list[n]=(char *) SvPV(ST(i+1),length[n]);
12068         if ((items >= 3) && strEQcase(list[n],"blob"))
12069           {
12070             void
12071               *blob;
12072
12073             i++;
12074             blob=(void *) (SvPV(ST(i+1),length[n]));
12075             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12076           }
12077         if ((items >= 3) && strEQcase(list[n],"filename"))
12078           continue;
12079         if ((items >= 3) && strEQcase(list[n],"file"))
12080           {
12081             FILE
12082               *file;
12083
12084             PerlIO
12085               *io_info;
12086
12087             i++;
12088             io_info=IoIFP(sv_2io(ST(i+1)));
12089             if (io_info == (PerlIO *) NULL)
12090               {
12091                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12092                   PackageName);
12093                 continue;
12094               }
12095             file=PerlIO_findFILE(io_info);
12096             if (file == (FILE *) NULL)
12097               {
12098                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12099                   PackageName);
12100                 continue;
12101               }
12102             SetImageInfoFile(package_info->image_info,file);
12103           }
12104         if ((items >= 3) && strEQcase(list[n],"magick"))
12105           continue;
12106         n++;
12107       }
12108     list[n]=(char *) NULL;
12109     keep=list;
12110     status=ExpandFilenames(&n,&list);
12111     if (status == MagickFalse)
12112       {
12113         ThrowPerlException(exception,ResourceLimitError,
12114           "MemoryAllocationFailed",PackageName);
12115         goto PerlException;
12116       }
12117     count=0;
12118     for (i=0; i < n; i++)
12119     {
12120       (void) CopyMagickString(package_info->image_info->filename,list[i],
12121         MagickPathExtent);
12122       image=PingImage(package_info->image_info,exception);
12123       if (image == (Image *) NULL)
12124         break;
12125       if ((package_info->image_info->file != (FILE *) NULL) ||
12126           (package_info->image_info->blob != (void *) NULL))
12127         DisassociateImageStream(image);
12128       count+=GetImageListLength(image);
12129       EXTEND(sp,4*count);
12130       for (next=image; next; next=next->next)
12131       {
12132         PUSHs(sv_2mortal(newSViv(next->columns)));
12133         PUSHs(sv_2mortal(newSViv(next->rows)));
12134         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12135         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12136       }
12137       image=DestroyImageList(image);
12138     }
12139     /*
12140       Free resources.
12141     */
12142     for (i=0; i < n; i++)
12143       if (list[i] != (char *) NULL)
12144         for (p=keep; list[i] != *p++; )
12145           if (*p == NULL)
12146             {
12147               list[i]=(char *) RelinquishMagickMemory(list[i]);
12148               break;
12149             }
12150
12151   PerlException:
12152     if (package_info != (struct PackageInfo *) NULL)
12153       DestroyPackageInfo(package_info);
12154     if (list && (list != keep))
12155       list=(char **) RelinquishMagickMemory(list);
12156     if (keep)
12157       keep=(char **) RelinquishMagickMemory(keep);
12158     if (length)
12159       length=(STRLEN *) RelinquishMagickMemory(length);
12160     InheritPerlException(exception,perl_exception);
12161     exception=DestroyExceptionInfo(exception);
12162     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12163   }
12164 \f
12165 #
12166 ###############################################################################
12167 #                                                                             #
12168 #                                                                             #
12169 #                                                                             #
12170 #   P r e v i e w                                                             #
12171 #                                                                             #
12172 #                                                                             #
12173 #                                                                             #
12174 ###############################################################################
12175 #
12176 #
12177 void
12178 Preview(ref,...)
12179   Image::Magick ref=NO_INIT
12180   ALIAS:
12181     PreviewImage = 1
12182     preview      = 2
12183     previewimage = 3
12184   PPCODE:
12185   {
12186     AV
12187       *av;
12188
12189     ExceptionInfo
12190       *exception;
12191
12192     HV
12193       *hv;
12194
12195     Image
12196       *image,
12197       *preview_image;
12198
12199     PreviewType
12200       preview_type;
12201
12202     struct PackageInfo
12203       *info;
12204
12205     SV
12206       *av_reference,
12207       *perl_exception,
12208       *reference,
12209       *rv,
12210       *sv;
12211
12212     PERL_UNUSED_VAR(ref);
12213     PERL_UNUSED_VAR(ix);
12214     exception=AcquireExceptionInfo();
12215     perl_exception=newSVpv("",0);
12216     sv=NULL;
12217     av=NULL;
12218     if (sv_isobject(ST(0)) == 0)
12219       {
12220         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12221           PackageName);
12222         goto PerlException;
12223       }
12224     reference=SvRV(ST(0));
12225     hv=SvSTASH(reference);
12226     av=newAV();
12227     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12228     SvREFCNT_dec(av);
12229     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12230     if (image == (Image *) NULL)
12231       {
12232         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12233           PackageName);
12234         goto PerlException;
12235       }
12236     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12237     preview_type=GammaPreview;
12238     if (items > 1)
12239       preview_type=(PreviewType)
12240         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12241     for ( ; image; image=image->next)
12242     {
12243       preview_image=PreviewImage(image,preview_type,exception);
12244       if (preview_image == (Image *) NULL)
12245         goto PerlException;
12246       AddImageToRegistry(sv,preview_image);
12247       rv=newRV(sv);
12248       av_push(av,sv_bless(rv,hv));
12249       SvREFCNT_dec(sv);
12250     }
12251     exception=DestroyExceptionInfo(exception);
12252     ST(0)=av_reference;
12253     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12254     XSRETURN(1);
12255
12256   PerlException:
12257     InheritPerlException(exception,perl_exception);
12258     exception=DestroyExceptionInfo(exception);
12259     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12260     SvPOK_on(perl_exception);
12261     ST(0)=sv_2mortal(perl_exception);
12262     XSRETURN(1);
12263   }
12264 \f
12265 #
12266 ###############################################################################
12267 #                                                                             #
12268 #                                                                             #
12269 #                                                                             #
12270 #   Q u e r y C o l o r                                                       #
12271 #                                                                             #
12272 #                                                                             #
12273 #                                                                             #
12274 ###############################################################################
12275 #
12276 #
12277 void
12278 QueryColor(ref,...)
12279   Image::Magick ref=NO_INIT
12280   ALIAS:
12281     querycolor = 1
12282   PPCODE:
12283   {
12284     char
12285       *name;
12286
12287     ExceptionInfo
12288       *exception;
12289
12290     PixelInfo
12291       color;
12292
12293     register ssize_t
12294       i;
12295
12296     SV
12297       *perl_exception;
12298
12299     PERL_UNUSED_VAR(ref);
12300     PERL_UNUSED_VAR(ix);
12301     exception=AcquireExceptionInfo();
12302     perl_exception=newSVpv("",0);
12303     if (items == 1)
12304       {
12305         const ColorInfo
12306           **colorlist;
12307
12308         size_t
12309           colors;
12310
12311         colorlist=GetColorInfoList("*",&colors,exception);
12312         EXTEND(sp,colors);
12313         for (i=0; i < (ssize_t) colors; i++)
12314         {
12315           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12316         }
12317         colorlist=(const ColorInfo **)
12318           RelinquishMagickMemory((ColorInfo **) colorlist);
12319         goto PerlException;
12320       }
12321     EXTEND(sp,5*items);
12322     for (i=1; i < items; i++)
12323     {
12324       name=(char *) SvPV(ST(i),na);
12325       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12326         {
12327           PUSHs(&sv_undef);
12328           continue;
12329         }
12330       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12331       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12332       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12333       if (color.colorspace == CMYKColorspace)
12334         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12335       if (color.alpha_trait != UndefinedPixelTrait)
12336         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12337     }
12338
12339   PerlException:
12340     InheritPerlException(exception,perl_exception);
12341     exception=DestroyExceptionInfo(exception);
12342     SvREFCNT_dec(perl_exception);
12343   }
12344 \f
12345 #
12346 ###############################################################################
12347 #                                                                             #
12348 #                                                                             #
12349 #                                                                             #
12350 #   Q u e r y C o l o r N a m e                                               #
12351 #                                                                             #
12352 #                                                                             #
12353 #                                                                             #
12354 ###############################################################################
12355 #
12356 #
12357 void
12358 QueryColorname(ref,...)
12359   Image::Magick ref=NO_INIT
12360   ALIAS:
12361     querycolorname = 1
12362   PPCODE:
12363   {
12364     AV
12365       *av;
12366
12367     char
12368       message[MagickPathExtent];
12369
12370     ExceptionInfo
12371       *exception;
12372
12373     Image
12374       *image;
12375
12376     PixelInfo
12377       target_color;
12378
12379     register ssize_t
12380       i;
12381
12382     struct PackageInfo
12383       *info;
12384
12385     SV
12386       *perl_exception,
12387       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12388
12389     PERL_UNUSED_VAR(ref);
12390     PERL_UNUSED_VAR(ix);
12391     exception=AcquireExceptionInfo();
12392     perl_exception=newSVpv("",0);
12393     reference=SvRV(ST(0));
12394     av=(AV *) reference;
12395     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12396       exception);
12397     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12398     if (image == (Image *) NULL)
12399       {
12400         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12401           PackageName);
12402         goto PerlException;
12403       }
12404     EXTEND(sp,items);
12405     for (i=1; i < items; i++)
12406     {
12407       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12408         exception);
12409       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12410         exception);
12411       PUSHs(sv_2mortal(newSVpv(message,0)));
12412     }
12413
12414   PerlException:
12415     InheritPerlException(exception,perl_exception);
12416     exception=DestroyExceptionInfo(exception);
12417     SvREFCNT_dec(perl_exception);
12418   }
12419 \f
12420 #
12421 ###############################################################################
12422 #                                                                             #
12423 #                                                                             #
12424 #                                                                             #
12425 #   Q u e r y F o n t                                                         #
12426 #                                                                             #
12427 #                                                                             #
12428 #                                                                             #
12429 ###############################################################################
12430 #
12431 #
12432 void
12433 QueryFont(ref,...)
12434   Image::Magick ref=NO_INIT
12435   ALIAS:
12436     queryfont = 1
12437   PPCODE:
12438   {
12439     char
12440       *name,
12441       message[MagickPathExtent];
12442
12443     ExceptionInfo
12444       *exception;
12445
12446     register ssize_t
12447       i;
12448
12449     SV
12450       *perl_exception;
12451
12452     volatile const TypeInfo
12453       *type_info;
12454
12455     PERL_UNUSED_VAR(ref);
12456     PERL_UNUSED_VAR(ix);
12457     exception=AcquireExceptionInfo();
12458     perl_exception=newSVpv("",0);
12459     if (items == 1)
12460       {
12461         const TypeInfo
12462           **typelist;
12463
12464         size_t
12465           types;
12466
12467         typelist=GetTypeInfoList("*",&types,exception);
12468         EXTEND(sp,types);
12469         for (i=0; i < (ssize_t) types; i++)
12470         {
12471           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12472         }
12473         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12474           typelist);
12475         goto PerlException;
12476       }
12477     EXTEND(sp,10*items);
12478     for (i=1; i < items; i++)
12479     {
12480       name=(char *) SvPV(ST(i),na);
12481       type_info=GetTypeInfo(name,exception);
12482       if (type_info == (TypeInfo *) NULL)
12483         {
12484           PUSHs(&sv_undef);
12485           continue;
12486         }
12487       if (type_info->name == (char *) NULL)
12488         PUSHs(&sv_undef);
12489       else
12490         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12491       if (type_info->description == (char *) NULL)
12492         PUSHs(&sv_undef);
12493       else
12494         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12495       if (type_info->family == (char *) NULL)
12496         PUSHs(&sv_undef);
12497       else
12498         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12499       if (type_info->style == UndefinedStyle)
12500         PUSHs(&sv_undef);
12501       else
12502         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12503           type_info->style),0)));
12504       if (type_info->stretch == UndefinedStretch)
12505         PUSHs(&sv_undef);
12506       else
12507         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12508           type_info->stretch),0)));
12509       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12510         type_info->weight);
12511       PUSHs(sv_2mortal(newSVpv(message,0)));
12512       if (type_info->encoding == (char *) NULL)
12513         PUSHs(&sv_undef);
12514       else
12515         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12516       if (type_info->foundry == (char *) NULL)
12517         PUSHs(&sv_undef);
12518       else
12519         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12520       if (type_info->format == (char *) NULL)
12521         PUSHs(&sv_undef);
12522       else
12523         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12524       if (type_info->metrics == (char *) NULL)
12525         PUSHs(&sv_undef);
12526       else
12527         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12528       if (type_info->glyphs == (char *) NULL)
12529         PUSHs(&sv_undef);
12530       else
12531         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12532     }
12533
12534   PerlException:
12535     InheritPerlException(exception,perl_exception);
12536     exception=DestroyExceptionInfo(exception);
12537     SvREFCNT_dec(perl_exception);
12538   }
12539 \f
12540 #
12541 ###############################################################################
12542 #                                                                             #
12543 #                                                                             #
12544 #                                                                             #
12545 #   Q u e r y F o n t M e t r i c s                                           #
12546 #                                                                             #
12547 #                                                                             #
12548 #                                                                             #
12549 ###############################################################################
12550 #
12551 #
12552 void
12553 QueryFontMetrics(ref,...)
12554   Image::Magick ref=NO_INIT
12555   ALIAS:
12556     queryfontmetrics = 1
12557   PPCODE:
12558   {
12559     AffineMatrix
12560       affine,
12561       current;
12562
12563     AV
12564       *av;
12565
12566     char
12567       *attribute;
12568
12569     double
12570       x,
12571       y;
12572
12573     DrawInfo
12574       *draw_info;
12575
12576     ExceptionInfo
12577       *exception;
12578
12579     GeometryInfo
12580       geometry_info;
12581
12582     Image
12583       *image;
12584
12585     MagickBooleanType
12586       status;
12587
12588     MagickStatusType
12589       flags;
12590
12591     register ssize_t
12592       i;
12593
12594     ssize_t
12595       type;
12596
12597     struct PackageInfo
12598       *info,
12599       *package_info;
12600
12601     SV
12602       *perl_exception,
12603       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12604
12605     TypeMetric
12606       metrics;
12607
12608     PERL_UNUSED_VAR(ref);
12609     PERL_UNUSED_VAR(ix);
12610     exception=AcquireExceptionInfo();
12611     package_info=(struct PackageInfo *) NULL;
12612     perl_exception=newSVpv("",0);
12613     reference=SvRV(ST(0));
12614     av=(AV *) reference;
12615     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12616       exception);
12617     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12618     if (image == (Image *) NULL)
12619       {
12620         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12621           PackageName);
12622         goto PerlException;
12623       }
12624     package_info=ClonePackageInfo(info,exception);
12625     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12626     CloneString(&draw_info->text,"");
12627     current=draw_info->affine;
12628     GetAffineMatrix(&affine);
12629     x=0.0;
12630     y=0.0;
12631     EXTEND(sp,7*items);
12632     for (i=2; i < items; i+=2)
12633     {
12634       attribute=(char *) SvPV(ST(i-1),na);
12635       switch (*attribute)
12636       {
12637         case 'A':
12638         case 'a':
12639         {
12640           if (LocaleCompare(attribute,"antialias") == 0)
12641             {
12642               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12643                 SvPV(ST(i),na));
12644               if (type < 0)
12645                 {
12646                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12647                     SvPV(ST(i),na));
12648                   break;
12649                 }
12650               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12651               break;
12652             }
12653           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12654             attribute);
12655           break;
12656         }
12657         case 'd':
12658         case 'D':
12659         {
12660           if (LocaleCompare(attribute,"density") == 0)
12661             {
12662               CloneString(&draw_info->density,SvPV(ST(i),na));
12663               break;
12664             }
12665           if (LocaleCompare(attribute,"direction") == 0)
12666             {
12667               draw_info->direction=(DirectionType) ParseCommandOption(
12668                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12669               break;
12670             }
12671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12672             attribute);
12673           break;
12674         }
12675         case 'e':
12676         case 'E':
12677         {
12678           if (LocaleCompare(attribute,"encoding") == 0)
12679             {
12680               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12681               break;
12682             }
12683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12684             attribute);
12685           break;
12686         }
12687         case 'f':
12688         case 'F':
12689         {
12690           if (LocaleCompare(attribute,"family") == 0)
12691             {
12692               CloneString(&draw_info->family,SvPV(ST(i),na));
12693               break;
12694             }
12695           if (LocaleCompare(attribute,"fill") == 0)
12696             {
12697               if (info)
12698                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12699                   &draw_info->fill,exception);
12700               break;
12701             }
12702           if (LocaleCompare(attribute,"font") == 0)
12703             {
12704               CloneString(&draw_info->font,SvPV(ST(i),na));
12705               break;
12706             }
12707           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12708             attribute);
12709           break;
12710         }
12711         case 'g':
12712         case 'G':
12713         {
12714           if (LocaleCompare(attribute,"geometry") == 0)
12715             {
12716               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12717               break;
12718             }
12719           if (LocaleCompare(attribute,"gravity") == 0)
12720             {
12721               draw_info->gravity=(GravityType) ParseCommandOption(
12722                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12723               break;
12724             }
12725           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12726             attribute);
12727           break;
12728         }
12729         case 'i':
12730         case 'I':
12731         {
12732           if (LocaleCompare(attribute,"interline-spacing") == 0)
12733             {
12734               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12735               draw_info->interline_spacing=geometry_info.rho;
12736               break;
12737             }
12738           if (LocaleCompare(attribute,"interword-spacing") == 0)
12739             {
12740               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12741               draw_info->interword_spacing=geometry_info.rho;
12742               break;
12743             }
12744           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12745             attribute);
12746           break;
12747         }
12748         case 'k':
12749         case 'K':
12750         {
12751           if (LocaleCompare(attribute,"kerning") == 0)
12752             {
12753               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12754               draw_info->kerning=geometry_info.rho;
12755               break;
12756             }
12757           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12758             attribute);
12759           break;
12760         }
12761         case 'p':
12762         case 'P':
12763         {
12764           if (LocaleCompare(attribute,"pointsize") == 0)
12765             {
12766               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12767               draw_info->pointsize=geometry_info.rho;
12768               break;
12769             }
12770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12771             attribute);
12772           break;
12773         }
12774         case 'r':
12775         case 'R':
12776         {
12777           if (LocaleCompare(attribute,"rotate") == 0)
12778             {
12779               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12780               affine.rx=geometry_info.rho;
12781               affine.ry=geometry_info.sigma;
12782               if ((flags & SigmaValue) == 0)
12783                 affine.ry=affine.rx;
12784               break;
12785             }
12786           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12787             attribute);
12788           break;
12789         }
12790         case 's':
12791         case 'S':
12792         {
12793           if (LocaleCompare(attribute,"scale") == 0)
12794             {
12795               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12796               affine.sx=geometry_info.rho;
12797               affine.sy=geometry_info.sigma;
12798               if ((flags & SigmaValue) == 0)
12799                 affine.sy=affine.sx;
12800               break;
12801             }
12802           if (LocaleCompare(attribute,"skew") == 0)
12803             {
12804               double
12805                 x_angle,
12806                 y_angle;
12807
12808               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12809               x_angle=geometry_info.rho;
12810               y_angle=geometry_info.sigma;
12811               if ((flags & SigmaValue) == 0)
12812                 y_angle=x_angle;
12813               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12814               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12815               break;
12816             }
12817           if (LocaleCompare(attribute,"stroke") == 0)
12818             {
12819               if (info)
12820                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12821                   &draw_info->stroke,exception);
12822               break;
12823             }
12824           if (LocaleCompare(attribute,"style") == 0)
12825             {
12826               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12827                 SvPV(ST(i),na));
12828               if (type < 0)
12829                 {
12830                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12831                     SvPV(ST(i),na));
12832                   break;
12833                 }
12834               draw_info->style=(StyleType) type;
12835               break;
12836             }
12837           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12838             attribute);
12839           break;
12840         }
12841         case 't':
12842         case 'T':
12843         {
12844           if (LocaleCompare(attribute,"text") == 0)
12845             {
12846               CloneString(&draw_info->text,SvPV(ST(i),na));
12847               break;
12848             }
12849           if (LocaleCompare(attribute,"translate") == 0)
12850             {
12851               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12852               affine.tx=geometry_info.rho;
12853               affine.ty=geometry_info.sigma;
12854               if ((flags & SigmaValue) == 0)
12855                 affine.ty=affine.tx;
12856               break;
12857             }
12858           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12859             attribute);
12860           break;
12861         }
12862         case 'w':
12863         case 'W':
12864         {
12865           if (LocaleCompare(attribute,"weight") == 0)
12866             {
12867               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12868               draw_info->weight=(size_t) geometry_info.rho;
12869               break;
12870             }
12871           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12872             attribute);
12873           break;
12874         }
12875         case 'x':
12876         case 'X':
12877         {
12878           if (LocaleCompare(attribute,"x") == 0)
12879             {
12880               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12881               x=geometry_info.rho;
12882               break;
12883             }
12884           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12885             attribute);
12886           break;
12887         }
12888         case 'y':
12889         case 'Y':
12890         {
12891           if (LocaleCompare(attribute,"y") == 0)
12892             {
12893               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12894               y=geometry_info.rho;
12895               break;
12896             }
12897           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12898             attribute);
12899           break;
12900         }
12901         default:
12902         {
12903           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12904             attribute);
12905           break;
12906         }
12907       }
12908     }
12909     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12910     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12911     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12912     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12913     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12914     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12915     if (draw_info->geometry == (char *) NULL)
12916       {
12917         draw_info->geometry=AcquireString((char *) NULL);
12918         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12919           "%.15g,%.15g",x,y);
12920       }
12921     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12922     (void) CatchImageException(image);
12923     if (status == MagickFalse)
12924       PUSHs(&sv_undef);
12925     else
12926       {
12927         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12928         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12929         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12930         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12931         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12932         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12933         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12934         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12935         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12936         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12937         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12938         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12939         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12940       }
12941     draw_info=DestroyDrawInfo(draw_info);
12942
12943   PerlException:
12944     if (package_info != (struct PackageInfo *) NULL)
12945       DestroyPackageInfo(package_info);
12946     InheritPerlException(exception,perl_exception);
12947     exception=DestroyExceptionInfo(exception);
12948     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12949   }
12950 \f
12951 #
12952 ###############################################################################
12953 #                                                                             #
12954 #                                                                             #
12955 #                                                                             #
12956 #   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                         #
12957 #                                                                             #
12958 #                                                                             #
12959 #                                                                             #
12960 ###############################################################################
12961 #
12962 #
12963 void
12964 QueryMultilineFontMetrics(ref,...)
12965   Image::Magick ref=NO_INIT
12966   ALIAS:
12967     querymultilinefontmetrics = 1
12968   PPCODE:
12969   {
12970     AffineMatrix
12971       affine,
12972       current;
12973
12974     AV
12975       *av;
12976
12977     char
12978       *attribute;
12979
12980     double
12981       x,
12982       y;
12983
12984     DrawInfo
12985       *draw_info;
12986
12987     ExceptionInfo
12988       *exception;
12989
12990     GeometryInfo
12991       geometry_info;
12992
12993     Image
12994       *image;
12995
12996     MagickBooleanType
12997       status;
12998
12999     MagickStatusType
13000       flags;
13001
13002     register ssize_t
13003       i;
13004
13005     ssize_t
13006       type;
13007
13008     struct PackageInfo
13009       *info,
13010       *package_info;
13011
13012     SV
13013       *perl_exception,
13014       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13015
13016     TypeMetric
13017       metrics;
13018
13019     PERL_UNUSED_VAR(ref);
13020     PERL_UNUSED_VAR(ix);
13021     exception=AcquireExceptionInfo();
13022     package_info=(struct PackageInfo *) NULL;
13023     perl_exception=newSVpv("",0);
13024     reference=SvRV(ST(0));
13025     av=(AV *) reference;
13026     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13027       exception);
13028     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13029     if (image == (Image *) NULL)
13030       {
13031         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13032           PackageName);
13033         goto PerlException;
13034       }
13035     package_info=ClonePackageInfo(info,exception);
13036     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13037     CloneString(&draw_info->text,"");
13038     current=draw_info->affine;
13039     GetAffineMatrix(&affine);
13040     x=0.0;
13041     y=0.0;
13042     EXTEND(sp,7*items);
13043     for (i=2; i < items; i+=2)
13044     {
13045       attribute=(char *) SvPV(ST(i-1),na);
13046       switch (*attribute)
13047       {
13048         case 'A':
13049         case 'a':
13050         {
13051           if (LocaleCompare(attribute,"antialias") == 0)
13052             {
13053               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13054                 SvPV(ST(i),na));
13055               if (type < 0)
13056                 {
13057                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13058                     SvPV(ST(i),na));
13059                   break;
13060                 }
13061               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13062               break;
13063             }
13064           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13065             attribute);
13066           break;
13067         }
13068         case 'd':
13069         case 'D':
13070         {
13071           if (LocaleCompare(attribute,"density") == 0)
13072             {
13073               CloneString(&draw_info->density,SvPV(ST(i),na));
13074               break;
13075             }
13076           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13077             attribute);
13078           break;
13079         }
13080         case 'e':
13081         case 'E':
13082         {
13083           if (LocaleCompare(attribute,"encoding") == 0)
13084             {
13085               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13086               break;
13087             }
13088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13089             attribute);
13090           break;
13091         }
13092         case 'f':
13093         case 'F':
13094         {
13095           if (LocaleCompare(attribute,"family") == 0)
13096             {
13097               CloneString(&draw_info->family,SvPV(ST(i),na));
13098               break;
13099             }
13100           if (LocaleCompare(attribute,"fill") == 0)
13101             {
13102               if (info)
13103                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13104                   &draw_info->fill,exception);
13105               break;
13106             }
13107           if (LocaleCompare(attribute,"font") == 0)
13108             {
13109               CloneString(&draw_info->font,SvPV(ST(i),na));
13110               break;
13111             }
13112           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13113             attribute);
13114           break;
13115         }
13116         case 'g':
13117         case 'G':
13118         {
13119           if (LocaleCompare(attribute,"geometry") == 0)
13120             {
13121               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13122               break;
13123             }
13124           if (LocaleCompare(attribute,"gravity") == 0)
13125             {
13126               draw_info->gravity=(GravityType) ParseCommandOption(
13127                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13128               break;
13129             }
13130           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13131             attribute);
13132           break;
13133         }
13134         case 'p':
13135         case 'P':
13136         {
13137           if (LocaleCompare(attribute,"pointsize") == 0)
13138             {
13139               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13140               draw_info->pointsize=geometry_info.rho;
13141               break;
13142             }
13143           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13144             attribute);
13145           break;
13146         }
13147         case 'r':
13148         case 'R':
13149         {
13150           if (LocaleCompare(attribute,"rotate") == 0)
13151             {
13152               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13153               affine.rx=geometry_info.rho;
13154               affine.ry=geometry_info.sigma;
13155               if ((flags & SigmaValue) == 0)
13156                 affine.ry=affine.rx;
13157               break;
13158             }
13159           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13160             attribute);
13161           break;
13162         }
13163         case 's':
13164         case 'S':
13165         {
13166           if (LocaleCompare(attribute,"scale") == 0)
13167             {
13168               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13169               affine.sx=geometry_info.rho;
13170               affine.sy=geometry_info.sigma;
13171               if ((flags & SigmaValue) == 0)
13172                 affine.sy=affine.sx;
13173               break;
13174             }
13175           if (LocaleCompare(attribute,"skew") == 0)
13176             {
13177               double
13178                 x_angle,
13179                 y_angle;
13180
13181               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13182               x_angle=geometry_info.rho;
13183               y_angle=geometry_info.sigma;
13184               if ((flags & SigmaValue) == 0)
13185                 y_angle=x_angle;
13186               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13187               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13188               break;
13189             }
13190           if (LocaleCompare(attribute,"stroke") == 0)
13191             {
13192               if (info)
13193                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13194                   &draw_info->stroke,exception);
13195               break;
13196             }
13197           if (LocaleCompare(attribute,"style") == 0)
13198             {
13199               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13200                 SvPV(ST(i),na));
13201               if (type < 0)
13202                 {
13203                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13204                     SvPV(ST(i),na));
13205                   break;
13206                 }
13207               draw_info->style=(StyleType) type;
13208               break;
13209             }
13210           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13211             attribute);
13212           break;
13213         }
13214         case 't':
13215         case 'T':
13216         {
13217           if (LocaleCompare(attribute,"text") == 0)
13218             {
13219               CloneString(&draw_info->text,SvPV(ST(i),na));
13220               break;
13221             }
13222           if (LocaleCompare(attribute,"translate") == 0)
13223             {
13224               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13225               affine.tx=geometry_info.rho;
13226               affine.ty=geometry_info.sigma;
13227               if ((flags & SigmaValue) == 0)
13228                 affine.ty=affine.tx;
13229               break;
13230             }
13231           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13232             attribute);
13233           break;
13234         }
13235         case 'w':
13236         case 'W':
13237         {
13238           if (LocaleCompare(attribute,"weight") == 0)
13239             {
13240               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13241               draw_info->weight=(size_t) geometry_info.rho;
13242               break;
13243             }
13244           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13245             attribute);
13246           break;
13247         }
13248         case 'x':
13249         case 'X':
13250         {
13251           if (LocaleCompare(attribute,"x") == 0)
13252             {
13253               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13254               x=geometry_info.rho;
13255               break;
13256             }
13257           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13258             attribute);
13259           break;
13260         }
13261         case 'y':
13262         case 'Y':
13263         {
13264           if (LocaleCompare(attribute,"y") == 0)
13265             {
13266               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13267               y=geometry_info.rho;
13268               break;
13269             }
13270           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13271             attribute);
13272           break;
13273         }
13274         default:
13275         {
13276           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13277             attribute);
13278           break;
13279         }
13280       }
13281     }
13282     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13283     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13284     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13285     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13286     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13287     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13288     if (draw_info->geometry == (char *) NULL)
13289       {
13290         draw_info->geometry=AcquireString((char *) NULL);
13291         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13292           "%.15g,%.15g",x,y);
13293       }
13294     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13295     (void) CatchException(exception);
13296     if (status == MagickFalse)
13297       PUSHs(&sv_undef);
13298     else
13299       {
13300         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13301         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13302         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13303         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13304         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13305         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13306         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13307         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13308         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13309         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13310         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13311         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13312         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13313       }
13314     draw_info=DestroyDrawInfo(draw_info);
13315
13316   PerlException:
13317     if (package_info != (struct PackageInfo *) NULL)
13318       DestroyPackageInfo(package_info);
13319     InheritPerlException(exception,perl_exception);
13320     exception=DestroyExceptionInfo(exception);
13321     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13322   }
13323 \f
13324 #
13325 ###############################################################################
13326 #                                                                             #
13327 #                                                                             #
13328 #                                                                             #
13329 #   Q u e r y F o r m a t                                                     #
13330 #                                                                             #
13331 #                                                                             #
13332 #                                                                             #
13333 ###############################################################################
13334 #
13335 #
13336 void
13337 QueryFormat(ref,...)
13338   Image::Magick ref=NO_INIT
13339   ALIAS:
13340     queryformat = 1
13341   PPCODE:
13342   {
13343     char
13344       *name;
13345
13346     ExceptionInfo
13347       *exception;
13348
13349     register ssize_t
13350       i;
13351
13352     SV
13353       *perl_exception;
13354
13355     volatile const MagickInfo
13356       *magick_info;
13357
13358     PERL_UNUSED_VAR(ref);
13359     PERL_UNUSED_VAR(ix);
13360     exception=AcquireExceptionInfo();
13361     perl_exception=newSVpv("",0);
13362     if (items == 1)
13363       {
13364         char
13365           format[MagickPathExtent];
13366
13367         const MagickInfo
13368           **format_list;
13369
13370         size_t
13371           types;
13372
13373         format_list=GetMagickInfoList("*",&types,exception);
13374         EXTEND(sp,types);
13375         for (i=0; i < (ssize_t) types; i++)
13376         {
13377           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13378           LocaleLower(format);
13379           PUSHs(sv_2mortal(newSVpv(format,0)));
13380         }
13381         format_list=(const MagickInfo **)
13382           RelinquishMagickMemory((MagickInfo *) format_list);
13383         goto PerlException;
13384       }
13385     EXTEND(sp,8*items);
13386     for (i=1; i < items; i++)
13387     {
13388       name=(char *) SvPV(ST(i),na);
13389       magick_info=GetMagickInfo(name,exception);
13390       if (magick_info == (const MagickInfo *) NULL)
13391         {
13392           PUSHs(&sv_undef);
13393           continue;
13394         }
13395       if (magick_info->description == (char *) NULL)
13396         PUSHs(&sv_undef);
13397       else
13398         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13399       if (magick_info->module == (char *) NULL)
13400         PUSHs(&sv_undef);
13401       else
13402         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13403     }
13404
13405   PerlException:
13406     InheritPerlException(exception,perl_exception);
13407     exception=DestroyExceptionInfo(exception);
13408     SvREFCNT_dec(perl_exception);
13409   }
13410 \f
13411 #
13412 ###############################################################################
13413 #                                                                             #
13414 #                                                                             #
13415 #                                                                             #
13416 #   Q u e r y O p t i o n                                                     #
13417 #                                                                             #
13418 #                                                                             #
13419 #                                                                             #
13420 ###############################################################################
13421 #
13422 #
13423 void
13424 QueryOption(ref,...)
13425   Image::Magick ref=NO_INIT
13426   ALIAS:
13427     queryoption = 1
13428   PPCODE:
13429   {
13430     char
13431       **options;
13432
13433     ExceptionInfo
13434       *exception;
13435
13436     register ssize_t
13437       i;
13438
13439     ssize_t
13440       j,
13441       option;
13442
13443     SV
13444       *perl_exception;
13445
13446     PERL_UNUSED_VAR(ref);
13447     PERL_UNUSED_VAR(ix);
13448     exception=AcquireExceptionInfo();
13449     perl_exception=newSVpv("",0);
13450     EXTEND(sp,8*items);
13451     for (i=1; i < items; i++)
13452     {
13453       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13454         SvPV(ST(i),na));
13455       options=GetCommandOptions((CommandOption) option);
13456       if (options == (char **) NULL)
13457         PUSHs(&sv_undef);
13458       else
13459         {
13460           for (j=0; options[j] != (char *) NULL; j++)
13461             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13462           options=DestroyStringList(options);
13463         }
13464     }
13465
13466     InheritPerlException(exception,perl_exception);
13467     exception=DestroyExceptionInfo(exception);
13468     SvREFCNT_dec(perl_exception);
13469   }
13470 \f
13471 #
13472 ###############################################################################
13473 #                                                                             #
13474 #                                                                             #
13475 #                                                                             #
13476 #   R e a d                                                                   #
13477 #                                                                             #
13478 #                                                                             #
13479 #                                                                             #
13480 ###############################################################################
13481 #
13482 #
13483 void
13484 Read(ref,...)
13485   Image::Magick ref=NO_INIT
13486   ALIAS:
13487     ReadImage  = 1
13488     read       = 2
13489     readimage  = 3
13490   PPCODE:
13491   {
13492     AV
13493       *av;
13494
13495     char
13496       **keep,
13497       **list;
13498
13499     ExceptionInfo
13500       *exception;
13501
13502     HV
13503       *hv;
13504
13505     Image
13506       *image;
13507
13508     int
13509       n;
13510
13511     MagickBooleanType
13512       status;
13513
13514     register char
13515       **p;
13516
13517     register ssize_t
13518       i;
13519
13520     ssize_t
13521       ac,
13522       number_images;
13523
13524     STRLEN
13525       *length;
13526
13527     struct PackageInfo
13528       *info,
13529       *package_info;
13530
13531     SV
13532       *perl_exception,  /* Perl variable for storing messages */
13533       *reference,
13534       *rv,
13535       *sv;
13536
13537     PERL_UNUSED_VAR(ref);
13538     PERL_UNUSED_VAR(ix);
13539     exception=AcquireExceptionInfo();
13540     perl_exception=newSVpv("",0);
13541     sv=NULL;
13542     package_info=(struct PackageInfo *) NULL;
13543     number_images=0;
13544     ac=(items < 2) ? 1 : items-1;
13545     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13546     keep=list;
13547     length=(STRLEN *) NULL;
13548     if (list == (char **) NULL)
13549       {
13550         ThrowPerlException(exception,ResourceLimitError,
13551           "MemoryAllocationFailed",PackageName);
13552         goto PerlException;
13553       }
13554     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13555     if (length == (STRLEN *) NULL)
13556       {
13557         ThrowPerlException(exception,ResourceLimitError,
13558           "MemoryAllocationFailed",PackageName);
13559         goto PerlException;
13560       }
13561     if (sv_isobject(ST(0)) == 0)
13562       {
13563         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13564           PackageName);
13565         goto PerlException;
13566       }
13567     reference=SvRV(ST(0));
13568     hv=SvSTASH(reference);
13569     if (SvTYPE(reference) != SVt_PVAV)
13570       {
13571         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13572           PackageName);
13573         goto PerlException;
13574       }
13575     av=(AV *) reference;
13576     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13577       exception);
13578     package_info=ClonePackageInfo(info,exception);
13579     n=1;
13580     if (items <= 1)
13581       *list=(char *) (*package_info->image_info->filename ?
13582         package_info->image_info->filename : "XC:black");
13583     else
13584       for (n=0, i=0; i < ac; i++)
13585       {
13586         list[n]=(char *) SvPV(ST(i+1),length[n]);
13587         if ((items >= 3) && strEQcase(list[n],"blob"))
13588           {
13589             void
13590               *blob;
13591
13592             i++;
13593             blob=(void *) (SvPV(ST(i+1),length[n]));
13594             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13595           }
13596         if ((items >= 3) && strEQcase(list[n],"filename"))
13597           continue;
13598         if ((items >= 3) && strEQcase(list[n],"file"))
13599           {
13600             FILE
13601               *file;
13602
13603             PerlIO
13604               *io_info;
13605
13606             i++;
13607             io_info=IoIFP(sv_2io(ST(i+1)));
13608             if (io_info == (PerlIO *) NULL)
13609               {
13610                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13611                   PackageName);
13612                 continue;
13613               }
13614             file=PerlIO_findFILE(io_info);
13615             if (file == (FILE *) NULL)
13616               {
13617                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13618                   PackageName);
13619                 continue;
13620               }
13621             SetImageInfoFile(package_info->image_info,file);
13622           }
13623         if ((items >= 3) && strEQcase(list[n],"magick"))
13624           continue;
13625         n++;
13626       }
13627     list[n]=(char *) NULL;
13628     keep=list;
13629     status=ExpandFilenames(&n,&list);
13630     if (status == MagickFalse)
13631       {
13632         ThrowPerlException(exception,ResourceLimitError,
13633           "MemoryAllocationFailed",PackageName);
13634         goto PerlException;
13635       }
13636     number_images=0;
13637     for (i=0; i < n; i++)
13638     {
13639       if ((package_info->image_info->file == (FILE *) NULL) &&
13640           (package_info->image_info->blob == (void *) NULL))
13641         image=ReadImages(package_info->image_info,list[i],exception);
13642       else
13643         {
13644           image=ReadImages(package_info->image_info,
13645             package_info->image_info->filename,exception);
13646           if (image != (Image *) NULL)
13647             DisassociateImageStream(image);
13648         }
13649       if (image == (Image *) NULL)
13650         break;
13651       for ( ; image; image=image->next)
13652       {
13653         AddImageToRegistry(sv,image);
13654         rv=newRV(sv);
13655         av_push(av,sv_bless(rv,hv));
13656         SvREFCNT_dec(sv);
13657         number_images++;
13658       }
13659     }
13660     /*
13661       Free resources.
13662     */
13663     for (i=0; i < n; i++)
13664       if (list[i] != (char *) NULL)
13665         for (p=keep; list[i] != *p++; )
13666           if (*p == (char *) NULL)
13667             {
13668               list[i]=(char *) RelinquishMagickMemory(list[i]);
13669               break;
13670             }
13671
13672   PerlException:
13673     if (package_info != (struct PackageInfo *) NULL)
13674       DestroyPackageInfo(package_info);
13675     if (list && (list != keep))
13676       list=(char **) RelinquishMagickMemory(list);
13677     if (keep)
13678       keep=(char **) RelinquishMagickMemory(keep);
13679     if (length)
13680       length=(STRLEN *) RelinquishMagickMemory(length);
13681     InheritPerlException(exception,perl_exception);
13682     exception=DestroyExceptionInfo(exception);
13683     sv_setiv(perl_exception,(IV) number_images);
13684     SvPOK_on(perl_exception);
13685     ST(0)=sv_2mortal(perl_exception);
13686     XSRETURN(1);
13687   }
13688 \f
13689 #
13690 ###############################################################################
13691 #                                                                             #
13692 #                                                                             #
13693 #                                                                             #
13694 #   R e m o t e                                                               #
13695 #                                                                             #
13696 #                                                                             #
13697 #                                                                             #
13698 ###############################################################################
13699 #
13700 #
13701 void
13702 Remote(ref,...)
13703   Image::Magick ref=NO_INIT
13704   ALIAS:
13705     RemoteCommand  = 1
13706     remote         = 2
13707     remoteCommand  = 3
13708   PPCODE:
13709   {
13710     AV
13711       *av;
13712
13713     ExceptionInfo
13714       *exception;
13715
13716     register ssize_t
13717       i;
13718
13719     SV
13720       *perl_exception,
13721       *reference;
13722
13723     struct PackageInfo
13724       *info;
13725
13726     PERL_UNUSED_VAR(ref);
13727     PERL_UNUSED_VAR(ix);
13728     exception=AcquireExceptionInfo();
13729     perl_exception=newSVpv("",0);
13730     reference=SvRV(ST(0));
13731     av=(AV *) reference;
13732     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13733       exception);
13734     for (i=1; i < items; i++)
13735       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13736         SvPV(ST(i),na),exception);
13737     InheritPerlException(exception,perl_exception);
13738     exception=DestroyExceptionInfo(exception);
13739     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13740   }
13741 \f
13742 #
13743 ###############################################################################
13744 #                                                                             #
13745 #                                                                             #
13746 #                                                                             #
13747 #   S e t                                                                     #
13748 #                                                                             #
13749 #                                                                             #
13750 #                                                                             #
13751 ###############################################################################
13752 #
13753 #
13754 void
13755 Set(ref,...)
13756   Image::Magick ref=NO_INIT
13757   ALIAS:
13758     SetAttributes  = 1
13759     SetAttribute   = 2
13760     set            = 3
13761     setattributes  = 4
13762     setattribute   = 5
13763   PPCODE:
13764   {
13765     ExceptionInfo
13766       *exception;
13767
13768     Image
13769       *image;
13770
13771     register ssize_t
13772       i;
13773
13774     struct PackageInfo
13775       *info;
13776
13777     SV
13778       *perl_exception,
13779       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13780
13781     PERL_UNUSED_VAR(ref);
13782     PERL_UNUSED_VAR(ix);
13783     exception=AcquireExceptionInfo();
13784     perl_exception=newSVpv("",0);
13785     if (sv_isobject(ST(0)) == 0)
13786       {
13787         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13788           PackageName);
13789         goto PerlException;
13790       }
13791     reference=SvRV(ST(0));
13792     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13793     if (items == 2)
13794       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13795     else
13796       for (i=2; i < items; i+=2)
13797         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13798
13799   PerlException:
13800     InheritPerlException(exception,perl_exception);
13801     exception=DestroyExceptionInfo(exception);
13802     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13803     SvPOK_on(perl_exception);
13804     ST(0)=sv_2mortal(perl_exception);
13805     XSRETURN(1);
13806   }
13807 \f
13808 #
13809 ###############################################################################
13810 #                                                                             #
13811 #                                                                             #
13812 #                                                                             #
13813 #   S e t P i x e l                                                           #
13814 #                                                                             #
13815 #                                                                             #
13816 #                                                                             #
13817 ###############################################################################
13818 #
13819 #
13820 void
13821 SetPixel(ref,...)
13822   Image::Magick ref=NO_INIT
13823   ALIAS:
13824     setpixel = 1
13825     setPixel = 2
13826   PPCODE:
13827   {
13828     AV
13829       *av;
13830
13831     char
13832       *attribute;
13833
13834     ChannelType
13835       channel,
13836       channel_mask;
13837
13838     ExceptionInfo
13839       *exception;
13840
13841     Image
13842       *image;
13843
13844     MagickBooleanType
13845       normalize;
13846
13847     RectangleInfo
13848       region;
13849
13850     register ssize_t
13851       i;
13852
13853     register Quantum
13854       *q;
13855
13856     ssize_t
13857       option;
13858
13859     struct PackageInfo
13860       *info;
13861
13862     SV
13863       *perl_exception,
13864       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13865
13866     PERL_UNUSED_VAR(ref);
13867     PERL_UNUSED_VAR(ix);
13868     exception=AcquireExceptionInfo();
13869     perl_exception=newSVpv("",0);
13870     reference=SvRV(ST(0));
13871     av=(AV *) reference;
13872     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13873       exception);
13874     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13875     if (image == (Image *) NULL)
13876       {
13877         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13878           PackageName);
13879         goto PerlException;
13880       }
13881     av=(AV *) NULL;
13882     normalize=MagickTrue;
13883     region.x=0;
13884     region.y=0;
13885     region.width=image->columns;
13886     region.height=1;
13887     if (items == 1)
13888       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13889     channel=DefaultChannels;
13890     for (i=2; i < items; i+=2)
13891     {
13892       attribute=(char *) SvPV(ST(i-1),na);
13893       switch (*attribute)
13894       {
13895         case 'C':
13896         case 'c':
13897         {
13898           if (LocaleCompare(attribute,"channel") == 0)
13899             {
13900               ssize_t
13901                 option;
13902
13903               option=ParseChannelOption(SvPV(ST(i),na));
13904               if (option < 0)
13905                 {
13906                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13907                     SvPV(ST(i),na));
13908                   return;
13909                 }
13910               channel=(ChannelType) option;
13911               break;
13912             }
13913           if (LocaleCompare(attribute,"color") == 0)
13914             {
13915               if (SvTYPE(ST(i)) != SVt_RV)
13916                 {
13917                   char
13918                     message[MagickPathExtent];
13919
13920                   (void) FormatLocaleString(message,MagickPathExtent,
13921                     "invalid %.60s value",attribute);
13922                   ThrowPerlException(exception,OptionError,message,
13923                     SvPV(ST(i),na));
13924                 }
13925               av=(AV *) SvRV(ST(i));
13926               break;
13927             }
13928           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13929             attribute);
13930           break;
13931         }
13932         case 'g':
13933         case 'G':
13934         {
13935           if (LocaleCompare(attribute,"geometry") == 0)
13936             {
13937               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13938               break;
13939             }
13940           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13941             attribute);
13942           break;
13943         }
13944         case 'N':
13945         case 'n':
13946         {
13947           if (LocaleCompare(attribute,"normalize") == 0)
13948             {
13949               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13950                 SvPV(ST(i),na));
13951               if (option < 0)
13952                 {
13953                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13954                     SvPV(ST(i),na));
13955                   break;
13956                 }
13957              normalize=option != 0 ? MagickTrue : MagickFalse;
13958              break;
13959             }
13960           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13961             attribute);
13962           break;
13963         }
13964         case 'x':
13965         case 'X':
13966         {
13967           if (LocaleCompare(attribute,"x") == 0)
13968             {
13969               region.x=SvIV(ST(i));
13970               break;
13971             }
13972           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13973             attribute);
13974           break;
13975         }
13976         case 'y':
13977         case 'Y':
13978         {
13979           if (LocaleCompare(attribute,"y") == 0)
13980             {
13981               region.y=SvIV(ST(i));
13982               break;
13983             }
13984           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13985             attribute);
13986           break;
13987         }
13988         default:
13989         {
13990           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13991             attribute);
13992           break;
13993         }
13994       }
13995     }
13996     (void) SetImageStorageClass(image,DirectClass,exception);
13997     channel_mask=SetImageChannelMask(image,channel);
13998     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13999     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14000         (SvTYPE(av) != SVt_PVAV))
14001       PUSHs(&sv_undef);
14002     else
14003       {
14004         double
14005           scale;
14006
14007         register ssize_t
14008           i;
14009
14010         i=0;
14011         scale=1.0;
14012         if (normalize != MagickFalse)
14013           scale=QuantumRange;
14014         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14015             (i <= av_len(av)))
14016           {
14017             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14018               av_fetch(av,i,0)))),q);
14019             i++;
14020           }
14021         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14022             (i <= av_len(av)))
14023           {
14024             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14025               av_fetch(av,i,0)))),q);
14026             i++;
14027           }
14028         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14029             (i <= av_len(av)))
14030           {
14031             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14032               av_fetch(av,i,0)))),q);
14033             i++;
14034           }
14035         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14036             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14037           {
14038             SetPixelBlack(image,ClampToQuantum(scale*
14039               SvNV(*(av_fetch(av,i,0)))),q);
14040             i++;
14041           }
14042         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14043             (i <= av_len(av)))
14044           {
14045             SetPixelAlpha(image,ClampToQuantum(scale*
14046               SvNV(*(av_fetch(av,i,0)))),q);
14047             i++;
14048           }
14049         (void) SyncAuthenticPixels(image,exception);
14050       }
14051     (void) SetImageChannelMask(image,channel_mask);
14052
14053   PerlException:
14054     InheritPerlException(exception,perl_exception);
14055     exception=DestroyExceptionInfo(exception);
14056     SvREFCNT_dec(perl_exception);
14057   }
14058 \f
14059 #
14060 ###############################################################################
14061 #                                                                             #
14062 #                                                                             #
14063 #                                                                             #
14064 #   S m u s h                                                                 #
14065 #                                                                             #
14066 #                                                                             #
14067 #                                                                             #
14068 ###############################################################################
14069 #
14070 #
14071 void
14072 Smush(ref,...)
14073   Image::Magick ref=NO_INIT
14074   ALIAS:
14075     SmushImage  = 1
14076     smush       = 2
14077     smushimage  = 3
14078   PPCODE:
14079   {
14080     AV
14081       *av;
14082
14083     char
14084       *attribute;
14085
14086     ExceptionInfo
14087       *exception;
14088
14089     HV
14090       *hv;
14091
14092     Image
14093       *image;
14094
14095     register ssize_t
14096       i;
14097
14098     ssize_t
14099       offset,
14100       stack;
14101
14102     struct PackageInfo
14103       *info;
14104
14105     SV
14106       *av_reference,
14107       *perl_exception,
14108       *reference,
14109       *rv,
14110       *sv;
14111
14112     PERL_UNUSED_VAR(ref);
14113     PERL_UNUSED_VAR(ix);
14114     exception=AcquireExceptionInfo();
14115     perl_exception=newSVpv("",0);
14116     sv=NULL;
14117     attribute=NULL;
14118     av=NULL;
14119     if (sv_isobject(ST(0)) == 0)
14120       {
14121         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14122           PackageName);
14123         goto PerlException;
14124       }
14125     reference=SvRV(ST(0));
14126     hv=SvSTASH(reference);
14127     av=newAV();
14128     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14129     SvREFCNT_dec(av);
14130     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14131     if (image == (Image *) NULL)
14132       {
14133         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14134           PackageName);
14135         goto PerlException;
14136       }
14137     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14138     /*
14139       Get options.
14140     */
14141     offset=0;
14142     stack=MagickTrue;
14143     for (i=2; i < items; i+=2)
14144     {
14145       attribute=(char *) SvPV(ST(i-1),na);
14146       switch (*attribute)
14147       {
14148         case 'O':
14149         case 'o':
14150         {
14151           if (LocaleCompare(attribute,"offset") == 0)
14152             {
14153               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14154               break;
14155             }
14156           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14157             attribute);
14158           break;
14159         }
14160         case 'S':
14161         case 's':
14162         {
14163           if (LocaleCompare(attribute,"stack") == 0)
14164             {
14165               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14166                 SvPV(ST(i),na));
14167               if (stack < 0)
14168                 {
14169                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14170                     SvPV(ST(i),na));
14171                   return;
14172                 }
14173               break;
14174             }
14175           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14176             attribute);
14177           break;
14178         }
14179         default:
14180         {
14181           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14182             attribute);
14183           break;
14184         }
14185       }
14186     }
14187     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14188       exception);
14189     if (image == (Image *) NULL)
14190       goto PerlException;
14191     for ( ; image; image=image->next)
14192     {
14193       AddImageToRegistry(sv,image);
14194       rv=newRV(sv);
14195       av_push(av,sv_bless(rv,hv));
14196       SvREFCNT_dec(sv);
14197     }
14198     exception=DestroyExceptionInfo(exception);
14199     ST(0)=av_reference;
14200     SvREFCNT_dec(perl_exception);
14201     XSRETURN(1);
14202
14203   PerlException:
14204     InheritPerlException(exception,perl_exception);
14205     exception=DestroyExceptionInfo(exception);
14206     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14207     SvPOK_on(perl_exception);
14208     ST(0)=sv_2mortal(perl_exception);
14209     XSRETURN(1);
14210   }
14211 \f
14212 #
14213 ###############################################################################
14214 #                                                                             #
14215 #                                                                             #
14216 #                                                                             #
14217 #   S t a t i s t i c s                                                       #
14218 #                                                                             #
14219 #                                                                             #
14220 #                                                                             #
14221 ###############################################################################
14222 #
14223 #
14224 void
14225 Statistics(ref,...)
14226   Image::Magick ref=NO_INIT
14227   ALIAS:
14228     StatisticsImage = 1
14229     statistics      = 2
14230     statisticsimage = 3
14231   PPCODE:
14232   {
14233 #define ChannelStatistics(channel) \
14234 { \
14235   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14236     (double) channel_statistics[channel].depth); \
14237   PUSHs(sv_2mortal(newSVpv(message,0))); \
14238   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14239     channel_statistics[channel].minima/scale); \
14240   PUSHs(sv_2mortal(newSVpv(message,0))); \
14241   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14242     channel_statistics[channel].maxima/scale); \
14243   PUSHs(sv_2mortal(newSVpv(message,0))); \
14244   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14245     channel_statistics[channel].mean/scale); \
14246   PUSHs(sv_2mortal(newSVpv(message,0))); \
14247   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14248     channel_statistics[channel].standard_deviation/scale); \
14249   PUSHs(sv_2mortal(newSVpv(message,0))); \
14250   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14251     channel_statistics[channel].kurtosis); \
14252   PUSHs(sv_2mortal(newSVpv(message,0))); \
14253   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14254     channel_statistics[channel].skewness); \
14255   PUSHs(sv_2mortal(newSVpv(message,0))); \
14256   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14257     channel_statistics[channel].entropy); \
14258   PUSHs(sv_2mortal(newSVpv(message,0))); \
14259 }
14260
14261     AV
14262       *av;
14263
14264     char
14265       message[MagickPathExtent];
14266
14267     ChannelStatistics
14268       *channel_statistics;
14269
14270     double
14271       scale;
14272
14273     ExceptionInfo
14274       *exception;
14275
14276     Image
14277       *image;
14278
14279     ssize_t
14280       count;
14281
14282     struct PackageInfo
14283       *info;
14284
14285     SV
14286       *perl_exception,
14287       *reference;
14288
14289     PERL_UNUSED_VAR(ref);
14290     PERL_UNUSED_VAR(ix);
14291     exception=AcquireExceptionInfo();
14292     perl_exception=newSVpv("",0);
14293     av=NULL;
14294     if (sv_isobject(ST(0)) == 0)
14295       {
14296         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14297           PackageName);
14298         goto PerlException;
14299       }
14300     reference=SvRV(ST(0));
14301     av=newAV();
14302     SvREFCNT_dec(av);
14303     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14304     if (image == (Image *) NULL)
14305       {
14306         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14307           PackageName);
14308         goto PerlException;
14309       }
14310     count=0;
14311     for ( ; image; image=image->next)
14312     {
14313       channel_statistics=GetImageStatistics(image,exception);
14314       if (channel_statistics == (ChannelStatistics *) NULL)
14315         continue;
14316       count++;
14317       EXTEND(sp,35*count);
14318       scale=(double) QuantumRange;
14319       ChannelStatistics(RedChannel);
14320       ChannelStatistics(GreenChannel);
14321       ChannelStatistics(BlueChannel);
14322       if (image->colorspace == CMYKColorspace)
14323         ChannelStatistics(BlackChannel);
14324       if (image->alpha_trait != UndefinedPixelTrait)
14325         ChannelStatistics(AlphaChannel);
14326       channel_statistics=(ChannelStatistics *)
14327         RelinquishMagickMemory(channel_statistics);
14328     }
14329
14330   PerlException:
14331     InheritPerlException(exception,perl_exception);
14332     exception=DestroyExceptionInfo(exception);
14333     SvREFCNT_dec(perl_exception);
14334   }
14335 \f
14336 #
14337 ###############################################################################
14338 #                                                                             #
14339 #                                                                             #
14340 #                                                                             #
14341 #   S y n c A u t h e n t i c P i x e l s                                     #
14342 #                                                                             #
14343 #                                                                             #
14344 #                                                                             #
14345 ###############################################################################
14346 #
14347 #
14348 void
14349 SyncAuthenticPixels(ref,...)
14350   Image::Magick ref = NO_INIT
14351   ALIAS:
14352     Syncauthenticpixels = 1
14353     SyncImagePixels = 2
14354     syncimagepixels = 3
14355   CODE:
14356   {
14357     ExceptionInfo
14358       *exception;
14359
14360     Image
14361       *image;
14362
14363     MagickBooleanType
14364       status;
14365
14366     struct PackageInfo
14367       *info;
14368
14369     SV
14370       *perl_exception,
14371       *reference;
14372
14373     PERL_UNUSED_VAR(ref);
14374     PERL_UNUSED_VAR(ix);
14375     exception=AcquireExceptionInfo();
14376     perl_exception=newSVpv("",0);
14377     if (sv_isobject(ST(0)) == 0)
14378       {
14379         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14380           PackageName);
14381         goto PerlException;
14382       }
14383
14384     reference=SvRV(ST(0));
14385     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14386     if (image == (Image *) NULL)
14387       {
14388         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14389           PackageName);
14390         goto PerlException;
14391       }
14392
14393     status=SyncAuthenticPixels(image,exception);
14394     if (status != MagickFalse)
14395       return;
14396
14397   PerlException:
14398     InheritPerlException(exception,perl_exception);
14399     exception=DestroyExceptionInfo(exception);
14400     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14401   }
14402 \f
14403 #
14404 ###############################################################################
14405 #                                                                             #
14406 #                                                                             #
14407 #                                                                             #
14408 #   T r a n s f o r m                                                         #
14409 #                                                                             #
14410 #                                                                             #
14411 #                                                                             #
14412 ###############################################################################
14413 #
14414 #
14415 void
14416 Transform(ref,...)
14417   Image::Magick ref=NO_INIT
14418   ALIAS:
14419     TransformImage = 1
14420     transform      = 2
14421     transformimage = 3
14422   PPCODE:
14423   {
14424     AV
14425       *av;
14426
14427     char
14428       *attribute,
14429       *crop_geometry,
14430       *geometry;
14431
14432     ExceptionInfo
14433       *exception;
14434
14435     HV
14436       *hv;
14437
14438     Image
14439       *clone,
14440       *image;
14441
14442     register ssize_t
14443       i;
14444
14445     struct PackageInfo
14446       *info;
14447
14448     SV
14449       *av_reference,
14450       *perl_exception,
14451       *reference,
14452       *rv,
14453       *sv;
14454
14455     PERL_UNUSED_VAR(ref);
14456     PERL_UNUSED_VAR(ix);
14457     exception=AcquireExceptionInfo();
14458     perl_exception=newSVpv("",0);
14459     sv=NULL;
14460     av=NULL;
14461     attribute=NULL;
14462     if (sv_isobject(ST(0)) == 0)
14463       {
14464         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14465           PackageName);
14466         goto PerlException;
14467       }
14468     reference=SvRV(ST(0));
14469     hv=SvSTASH(reference);
14470     av=newAV();
14471     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14472     SvREFCNT_dec(av);
14473     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14474     if (image == (Image *) NULL)
14475       {
14476         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14477           PackageName);
14478         goto PerlException;
14479       }
14480     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14481     /*
14482       Get attribute.
14483     */
14484     crop_geometry=(char *) NULL;
14485     geometry=(char *) NULL;
14486     for (i=2; i < items; i+=2)
14487     {
14488       attribute=(char *) SvPV(ST(i-1),na);
14489       switch (*attribute)
14490       {
14491         case 'c':
14492         case 'C':
14493         {
14494           if (LocaleCompare(attribute,"crop") == 0)
14495             {
14496               crop_geometry=SvPV(ST(i),na);
14497               break;
14498             }
14499           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14500             attribute);
14501           break;
14502         }
14503         case 'g':
14504         case 'G':
14505         {
14506           if (LocaleCompare(attribute,"geometry") == 0)
14507             {
14508               geometry=SvPV(ST(i),na);
14509               break;
14510             }
14511           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14512             attribute);
14513           break;
14514         }
14515         default:
14516         {
14517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14518             attribute);
14519           break;
14520         }
14521       }
14522     }
14523     for ( ; image; image=image->next)
14524     {
14525       clone=CloneImage(image,0,0,MagickTrue,exception);
14526       if (clone == (Image *) NULL)
14527         goto PerlException;
14528       TransformImage(&clone,crop_geometry,geometry,exception);
14529       for ( ; clone; clone=clone->next)
14530       {
14531         AddImageToRegistry(sv,clone);
14532         rv=newRV(sv);
14533         av_push(av,sv_bless(rv,hv));
14534         SvREFCNT_dec(sv);
14535       }
14536     }
14537     exception=DestroyExceptionInfo(exception);
14538     ST(0)=av_reference;
14539     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14540     XSRETURN(1);
14541
14542   PerlException:
14543     InheritPerlException(exception,perl_exception);
14544     exception=DestroyExceptionInfo(exception);
14545     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14546     SvPOK_on(perl_exception);
14547     ST(0)=sv_2mortal(perl_exception);
14548     XSRETURN(1);
14549   }
14550 \f
14551 #
14552 ###############################################################################
14553 #                                                                             #
14554 #                                                                             #
14555 #                                                                             #
14556 #   W r i t e                                                                 #
14557 #                                                                             #
14558 #                                                                             #
14559 #                                                                             #
14560 ###############################################################################
14561 #
14562 #
14563 void
14564 Write(ref,...)
14565   Image::Magick ref=NO_INIT
14566   ALIAS:
14567     WriteImage    = 1
14568     write         = 2
14569     writeimage    = 3
14570   PPCODE:
14571   {
14572     char
14573       filename[MagickPathExtent];
14574
14575     ExceptionInfo
14576       *exception;
14577
14578     Image
14579       *image,
14580       *next;
14581
14582     register ssize_t
14583       i;
14584
14585     ssize_t
14586       number_images,
14587       scene;
14588
14589     struct PackageInfo
14590       *info,
14591       *package_info;
14592
14593     SV
14594       *perl_exception,
14595       *reference;
14596
14597     PERL_UNUSED_VAR(ref);
14598     PERL_UNUSED_VAR(ix);
14599     exception=AcquireExceptionInfo();
14600     perl_exception=newSVpv("",0);
14601     number_images=0;
14602     package_info=(struct PackageInfo *) NULL;
14603     if (sv_isobject(ST(0)) == 0)
14604       {
14605         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14606           PackageName);
14607         goto PerlException;
14608       }
14609     reference=SvRV(ST(0));
14610     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14611     if (image == (Image *) NULL)
14612       {
14613         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14614           PackageName);
14615         goto PerlException;
14616       }
14617     package_info=ClonePackageInfo(info,exception);
14618     if (items == 2)
14619       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14620     else
14621       if (items > 2)
14622         for (i=2; i < items; i+=2)
14623           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14624             exception);
14625     (void) CopyMagickString(filename,package_info->image_info->filename,
14626       MagickPathExtent);
14627     scene=0;
14628     for (next=image; next; next=next->next)
14629     {
14630       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14631       next->scene=scene++;
14632     }
14633     *package_info->image_info->magick='\0';
14634     SetImageInfo(package_info->image_info,(unsigned int)
14635       GetImageListLength(image),exception);
14636     for (next=image; next; next=next->next)
14637     {
14638       (void) WriteImage(package_info->image_info,next,exception);
14639       number_images++;
14640       if (package_info->image_info->adjoin)
14641         break;
14642     }
14643
14644   PerlException:
14645     if (package_info != (struct PackageInfo *) NULL)
14646       DestroyPackageInfo(package_info);
14647     InheritPerlException(exception,perl_exception);
14648     exception=DestroyExceptionInfo(exception);
14649     sv_setiv(perl_exception,(IV) number_images);
14650     SvPOK_on(perl_exception);
14651     ST(0)=sv_2mortal(perl_exception);
14652     XSRETURN(1);
14653   }