]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
cc1661358b6450391570b898574826721553a143
[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-2017 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include <MagickCore/MagickCore.h>
57 #include "EXTERN.h"
58 #include "perl.h"
59 #include "XSUB.h"
60 #include <math.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "Mode", { {"geometry", StringReference},
535       {"width", IntegerReference},{"height", IntegerReference},
536       {"channel", MagickChannelOptions} } },
537     { "Statistic", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
540     { "Perceptible", { {"epsilon", RealReference},
541       {"channel", MagickChannelOptions} } },
542     { "Poly", { {"terms", ArrayReference},
543       {"channel", MagickChannelOptions} } },
544     { "Grayscale", { {"method", MagickNoiseOptions} } },
545     { "CannyEdge", { {"geometry", StringReference},
546       {"radius", RealReference}, {"sigma", RealReference},
547       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
548     { "HoughLine", { {"geometry", StringReference},
549       {"width", IntegerReference}, {"height", IntegerReference},
550       {"threshold", IntegerReference} } },
551     { "MeanShift", { {"geometry", StringReference},
552       {"width", IntegerReference}, {"height", IntegerReference},
553       {"distance", RealReference} } },
554     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
555       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
556     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
557     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
558       {"width", IntegerReference}, {"height", IntegerReference},
559       {"x", IntegerReference}, {"y", IntegerReference},
560       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
561       {"dx", IntegerReference}, {"dy", IntegerReference} } },
562     { "Color", { {"color", StringReference} } },
563     { "WaveletDenoise", {  {"geometry", StringReference},
564       {"threshold", RealReference}, {"softness", RealReference},
565       {"channel", MagickChannelOptions} } },
566     { "Colorspace", { {"colorspace", MagickColorspaceOptions} } },
567   };
568
569 static SplayTreeInfo
570   *magick_registry = (SplayTreeInfo *) NULL;
571 \f
572 /*
573   Forward declarations.
574 */
575 static Image
576   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
577
578 static ssize_t
579   strEQcase(const char *,const char *);
580 \f
581 /*
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 %                                                                             %
584 %                                                                             %
585 %                                                                             %
586 %   C l o n e P a c k a g e I n f o                                           %
587 %                                                                             %
588 %                                                                             %
589 %                                                                             %
590 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591 %
592 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
593 %  a new one.
594 %
595 %  The format of the ClonePackageInfo routine is:
596 %
597 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
598 %        exception)
599 %
600 %  A description of each parameter follows:
601 %
602 %    o info: a structure of type info.
603 %
604 %    o exception: Return any errors or warnings in this structure.
605 %
606 */
607 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
608   ExceptionInfo *exception)
609 {
610   struct PackageInfo
611     *clone_info;
612
613   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
614   if (clone_info == (struct PackageInfo *) NULL)
615     {
616       ThrowPerlException(exception,ResourceLimitError,
617         "UnableToClonePackageInfo",PackageName);
618       return((struct PackageInfo *) NULL);
619     }
620   if (info == (struct PackageInfo *) NULL)
621     {
622       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
623       return(clone_info);
624     }
625   *clone_info=(*info);
626   clone_info->image_info=CloneImageInfo(info->image_info);
627   return(clone_info);
628 }
629 \f
630 /*
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 %                                                                             %
633 %                                                                             %
634 %                                                                             %
635 %   c o n s t a n t                                                           %
636 %                                                                             %
637 %                                                                             %
638 %                                                                             %
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 %
641 %  constant() returns a double value for the specified name.
642 %
643 %  The format of the constant routine is:
644 %
645 %      double constant(char *name,ssize_t sans)
646 %
647 %  A description of each parameter follows:
648 %
649 %    o value: Method constant returns a double value for the specified name.
650 %
651 %    o name: The name of the constant.
652 %
653 %    o sans: This integer value is not used.
654 %
655 */
656 static double constant(char *name,ssize_t sans)
657 {
658   (void) sans;
659   errno=0;
660   switch (*name)
661   {
662     case 'B':
663     {
664       if (strEQ(name,"BlobError"))
665         return(BlobError);
666       if (strEQ(name,"BlobWarning"))
667         return(BlobWarning);
668       break;
669     }
670     case 'C':
671     {
672       if (strEQ(name,"CacheError"))
673         return(CacheError);
674       if (strEQ(name,"CacheWarning"))
675         return(CacheWarning);
676       if (strEQ(name,"CoderError"))
677         return(CoderError);
678       if (strEQ(name,"CoderWarning"))
679         return(CoderWarning);
680       if (strEQ(name,"ConfigureError"))
681         return(ConfigureError);
682       if (strEQ(name,"ConfigureWarning"))
683         return(ConfigureWarning);
684       if (strEQ(name,"CorruptImageError"))
685         return(CorruptImageError);
686       if (strEQ(name,"CorruptImageWarning"))
687         return(CorruptImageWarning);
688       break;
689     }
690     case 'D':
691     {
692       if (strEQ(name,"DelegateError"))
693         return(DelegateError);
694       if (strEQ(name,"DelegateWarning"))
695         return(DelegateWarning);
696       if (strEQ(name,"DrawError"))
697         return(DrawError);
698       if (strEQ(name,"DrawWarning"))
699         return(DrawWarning);
700       break;
701     }
702     case 'E':
703     {
704       if (strEQ(name,"ErrorException"))
705         return(ErrorException);
706       if (strEQ(name,"ExceptionError"))
707         return(CoderError);
708       if (strEQ(name,"ExceptionWarning"))
709         return(CoderWarning);
710       break;
711     }
712     case 'F':
713     {
714       if (strEQ(name,"FatalErrorException"))
715         return(FatalErrorException);
716       if (strEQ(name,"FileOpenError"))
717         return(FileOpenError);
718       if (strEQ(name,"FileOpenWarning"))
719         return(FileOpenWarning);
720       break;
721     }
722     case 'I':
723     {
724       if (strEQ(name,"ImageError"))
725         return(ImageError);
726       if (strEQ(name,"ImageWarning"))
727         return(ImageWarning);
728       break;
729     }
730     case 'M':
731     {
732       if (strEQ(name,"MaxRGB"))
733         return(QuantumRange);
734       if (strEQ(name,"MissingDelegateError"))
735         return(MissingDelegateError);
736       if (strEQ(name,"MissingDelegateWarning"))
737         return(MissingDelegateWarning);
738       if (strEQ(name,"ModuleError"))
739         return(ModuleError);
740       if (strEQ(name,"ModuleWarning"))
741         return(ModuleWarning);
742       break;
743     }
744     case 'O':
745     {
746       if (strEQ(name,"Opaque"))
747         return(OpaqueAlpha);
748       if (strEQ(name,"OptionError"))
749         return(OptionError);
750       if (strEQ(name,"OptionWarning"))
751         return(OptionWarning);
752       break;
753     }
754     case 'Q':
755     {
756       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
757         return(MAGICKCORE_QUANTUM_DEPTH);
758       if (strEQ(name,"QuantumDepth"))
759         return(MAGICKCORE_QUANTUM_DEPTH);
760       if (strEQ(name,"QuantumRange"))
761         return(QuantumRange);
762       break;
763     }
764     case 'R':
765     {
766       if (strEQ(name,"ResourceLimitError"))
767         return(ResourceLimitError);
768       if (strEQ(name,"ResourceLimitWarning"))
769         return(ResourceLimitWarning);
770       if (strEQ(name,"RegistryError"))
771         return(RegistryError);
772       if (strEQ(name,"RegistryWarning"))
773         return(RegistryWarning);
774       break;
775     }
776     case 'S':
777     {
778       if (strEQ(name,"StreamError"))
779         return(StreamError);
780       if (strEQ(name,"StreamWarning"))
781         return(StreamWarning);
782       if (strEQ(name,"Success"))
783         return(0);
784       break;
785     }
786     case 'T':
787     {
788       if (strEQ(name,"Transparent"))
789         return(TransparentAlpha);
790       if (strEQ(name,"TypeError"))
791         return(TypeError);
792       if (strEQ(name,"TypeWarning"))
793         return(TypeWarning);
794       break;
795     }
796     case 'W':
797     {
798       if (strEQ(name,"WarningException"))
799         return(WarningException);
800       break;
801     }
802     case 'X':
803     {
804       if (strEQ(name,"XServerError"))
805         return(XServerError);
806       if (strEQ(name,"XServerWarning"))
807         return(XServerWarning);
808       break;
809     }
810   }
811   errno=EINVAL;
812   return(0);
813 }
814 \f
815 /*
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %                                                                             %
818 %                                                                             %
819 %                                                                             %
820 %   D e s t r o y P a c k a g e I n f o                                       %
821 %                                                                             %
822 %                                                                             %
823 %                                                                             %
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 %
826 %  Method DestroyPackageInfo frees a previously created info structure.
827 %
828 %  The format of the DestroyPackageInfo routine is:
829 %
830 %      DestroyPackageInfo(struct PackageInfo *info)
831 %
832 %  A description of each parameter follows:
833 %
834 %    o info: a structure of type info.
835 %
836 */
837 static void DestroyPackageInfo(struct PackageInfo *info)
838 {
839   info->image_info=DestroyImageInfo(info->image_info);
840   info=(struct PackageInfo *) RelinquishMagickMemory(info);
841 }
842 \f
843 /*
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845 %                                                                             %
846 %                                                                             %
847 %                                                                             %
848 %   G e t L i s t                                                             %
849 %                                                                             %
850 %                                                                             %
851 %                                                                             %
852 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853 %
854 %  Method GetList is recursively called by SetupList to traverse the
855 %  Image__Magick reference.  If building an reference_vector (see SetupList),
856 %  *current is the current position in *reference_vector and *last is the final
857 %  entry in *reference_vector.
858 %
859 %  The format of the GetList routine is:
860 %
861 %      GetList(info)
862 %
863 %  A description of each parameter follows:
864 %
865 %    o info: a structure of type info.
866 %
867 */
868 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
869   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
870 {
871   Image
872     *image;
873
874   if (reference == (SV *) NULL)
875     return(NULL);
876   switch (SvTYPE(reference))
877   {
878     case SVt_PVAV:
879     {
880       AV
881         *av;
882
883       Image
884         *head,
885         *previous;
886
887       register ssize_t
888         i;
889
890       ssize_t
891         n;
892
893       /*
894         Array of images.
895       */
896       previous=(Image *) NULL;
897       head=(Image *) NULL;
898       av=(AV *) reference;
899       n=av_len(av);
900       for (i=0; i <= n; i++)
901       {
902         SV
903           **rv;
904
905         rv=av_fetch(av,i,0);
906         if (rv && *rv && sv_isobject(*rv))
907           {
908             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
909               exception);
910             if (image == (Image *) NULL)
911               continue;
912             if (image == previous)
913               {
914                 image=CloneImage(image,0,0,MagickTrue,exception);
915                 if (image == (Image *) NULL)
916                   return(NULL);
917               }
918             image->previous=previous;
919             *(previous ? &previous->next : &head)=image;
920             for (previous=image; previous->next; previous=previous->next) ;
921           }
922       }
923       return(head);
924     }
925     case SVt_PVMG:
926     {
927       /*
928         Blessed scalar, one image.
929       */
930       image=INT2PTR(Image *,SvIV(reference));
931       if (image == (Image *) NULL)
932         return(NULL);
933       image->previous=(Image *) NULL;
934       image->next=(Image *) NULL;
935       if (reference_vector)
936         {
937           if (*current == *last)
938             {
939               *last+=256;
940               if (*reference_vector == (SV **) NULL)
941                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
942                   sizeof(*reference_vector));
943               else
944                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
945                   *last,sizeof(*reference_vector));
946             }
947           if (*reference_vector == (SV **) NULL)
948             {
949               ThrowPerlException(exception,ResourceLimitError,
950                 "MemoryAllocationFailed",PackageName);
951               return((Image *) NULL);
952             }
953           (*reference_vector)[*current]=reference;
954           (*reference_vector)[++(*current)]=NULL;
955         }
956       return(image);
957     }
958     default:
959       break;
960   }
961   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
962     (double) SvTYPE(reference));
963   return((Image *) NULL);
964 }
965 \f
966 /*
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 %                                                                             %
969 %                                                                             %
970 %                                                                             %
971 %   G e t P a c k a g e I n f o                                               %
972 %                                                                             %
973 %                                                                             %
974 %                                                                             %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
976 %
977 %  Method GetPackageInfo looks up or creates an info structure for the given
978 %  Image__Magick reference.  If it does create a new one, the information in
979 %  package_info is used to initialize it.
980 %
981 %  The format of the GetPackageInfo routine is:
982 %
983 %      struct PackageInfo *GetPackageInfo(void *reference,
984 %        struct PackageInfo *package_info,ExceptionInfo *exception)
985 %
986 %  A description of each parameter follows:
987 %
988 %    o info: a structure of type info.
989 %
990 %    o exception: Return any errors or warnings in this structure.
991 %
992 */
993 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
994   struct PackageInfo *package_info,ExceptionInfo *exception)
995 {
996   char
997     message[MagickPathExtent];
998
999   struct PackageInfo
1000     *clone_info;
1001
1002   SV
1003     *sv;
1004
1005   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1006     PackageName,XS_VERSION,reference);
1007   sv=perl_get_sv(message,(TRUE | 0x02));
1008   if (sv == (SV *) NULL)
1009     {
1010       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1011         message);
1012       return(package_info);
1013     }
1014   if (SvREFCNT(sv) == 0)
1015     (void) SvREFCNT_inc(sv);
1016   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1017     return(clone_info);
1018   clone_info=ClonePackageInfo(package_info,exception);
1019   sv_setiv(sv,PTR2IV(clone_info));
1020   return(clone_info);
1021 }
1022 \f
1023 /*
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 %                                                                             %
1026 %                                                                             %
1027 %                                                                             %
1028 %   S e t A t t r i b u t e                                                   %
1029 %                                                                             %
1030 %                                                                             %
1031 %                                                                             %
1032 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1033 %
1034 %  SetAttribute() sets the attribute to the value in sval.  This can change
1035 %  either or both of image or info.
1036 %
1037 %  The format of the SetAttribute routine is:
1038 %
1039 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1040 %        SV *sval,ExceptionInfo *exception)
1041 %
1042 %  A description of each parameter follows:
1043 %
1044 %    o list: a list of strings.
1045 %
1046 %    o string: a character string.
1047 %
1048 */
1049
1050 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1051 {
1052   char
1053     *q;
1054
1055   double
1056     value;
1057
1058   value=InterpretSiPrefixValue(string,&q);
1059   if (*q == '%')
1060     value*=interval/100.0;
1061   return(value);
1062 }
1063
1064 static inline double StringToDouble(const char *string,char **sentinal)
1065 {
1066   return(InterpretLocaleValue(string,sentinal));
1067 }
1068
1069 static double StringToDoubleInterval(const char *string,const double interval)
1070 {
1071   char
1072     *q;
1073
1074   double
1075     value;
1076
1077   value=InterpretLocaleValue(string,&q);
1078   if (*q == '%')
1079     value*=interval/100.0;
1080   return(value);
1081 }
1082
1083 static inline ssize_t StringToLong(const char *value)
1084 {
1085   return(strtol(value,(char **) NULL,10));
1086 }
1087
1088 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1089   const char *attribute,SV *sval,ExceptionInfo *exception)
1090 {
1091   GeometryInfo
1092     geometry_info;
1093
1094   long
1095     x,
1096     y;
1097
1098   PixelInfo
1099     pixel;
1100
1101   MagickStatusType
1102     flags;
1103
1104   PixelInfo
1105     *color,
1106     target_color;
1107
1108   ssize_t
1109     sp;
1110
1111   switch (*attribute)
1112   {
1113     case 'A':
1114     case 'a':
1115     {
1116       if (LocaleCompare(attribute,"adjoin") == 0)
1117         {
1118           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1119             SvPV(sval,na)) : SvIV(sval);
1120           if (sp < 0)
1121             {
1122               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1123                 SvPV(sval,na));
1124               break;
1125             }
1126           if (info)
1127             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1128           break;
1129         }
1130       if (LocaleCompare(attribute,"alpha") == 0)
1131         {
1132           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1133             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1134           if (sp < 0)
1135             {
1136               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1137                 SvPV(sval,na));
1138               break;
1139             }
1140           for ( ; image; image=image->next)
1141             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1142               exception);
1143           break;
1144         }
1145       if (LocaleCompare(attribute,"antialias") == 0)
1146         {
1147           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1148             SvPV(sval,na)) : SvIV(sval);
1149           if (sp < 0)
1150             {
1151               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1152                 SvPV(sval,na));
1153               break;
1154             }
1155           if (info)
1156             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1157           break;
1158         }
1159       if (LocaleCompare(attribute,"area-limit") == 0)
1160         {
1161           MagickSizeType
1162             limit;
1163
1164           limit=MagickResourceInfinity;
1165           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1166             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1167               100.0);
1168           (void) SetMagickResourceLimit(AreaResource,limit);
1169           break;
1170         }
1171       if (LocaleCompare(attribute,"attenuate") == 0)
1172         {
1173           if (info)
1174             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1175           break;
1176         }
1177       if (LocaleCompare(attribute,"authenticate") == 0)
1178         {
1179           if (info)
1180             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1181           break;
1182         }
1183       if (info)
1184         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1185       for ( ; image; image=image->next)
1186         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1187       break;
1188     }
1189     case 'B':
1190     case 'b':
1191     {
1192       if (LocaleCompare(attribute,"background") == 0)
1193         {
1194           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1195             exception);
1196           if (info)
1197             info->image_info->background_color=target_color;
1198           for ( ; image; image=image->next)
1199             image->background_color=target_color;
1200           break;
1201         }
1202       if (LocaleCompare(attribute,"blue-primary") == 0)
1203         {
1204           for ( ; image; image=image->next)
1205           {
1206             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1207             image->chromaticity.blue_primary.x=geometry_info.rho;
1208             image->chromaticity.blue_primary.y=geometry_info.sigma;
1209             if ((flags & SigmaValue) == 0)
1210               image->chromaticity.blue_primary.y=
1211                 image->chromaticity.blue_primary.x;
1212           }
1213           break;
1214         }
1215       if (LocaleCompare(attribute,"bordercolor") == 0)
1216         {
1217           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1218             exception);
1219           if (info)
1220             info->image_info->border_color=target_color;
1221           for ( ; image; image=image->next)
1222             image->border_color=target_color;
1223           break;
1224         }
1225       if (info)
1226         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1227       for ( ; image; image=image->next)
1228         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1229       break;
1230     }
1231     case 'C':
1232     case 'c':
1233     {
1234       if (LocaleCompare(attribute,"cache-threshold") == 0)
1235         {
1236           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1237             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1238           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1239             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1240           break;
1241         }
1242       if (LocaleCompare(attribute,"clip-mask") == 0)
1243         {
1244           Image
1245             *clip_mask;
1246
1247           clip_mask=(Image *) NULL;
1248           if (SvPOK(sval))
1249             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1250           for ( ; image; image=image->next)
1251             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1252           break;
1253         }
1254       if (LocaleNCompare(attribute,"colormap",8) == 0)
1255         {
1256           for ( ; image; image=image->next)
1257           {
1258             int
1259               items;
1260
1261             long
1262               i;
1263
1264             if (image->storage_class == DirectClass)
1265               continue;
1266             i=0;
1267             items=sscanf(attribute,"%*[^[][%ld",&i);
1268             (void) items;
1269             if (i > (ssize_t) image->colors)
1270               i%=image->colors;
1271             if ((strchr(SvPV(sval,na),',') == 0) ||
1272                 (strchr(SvPV(sval,na),')') != 0))
1273               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1274                 image->colormap+i,exception);
1275             else
1276               {
1277                 color=image->colormap+i;
1278                 pixel.red=color->red;
1279                 pixel.green=color->green;
1280                 pixel.blue=color->blue;
1281                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1282                 pixel.red=geometry_info.rho;
1283                 pixel.green=geometry_info.sigma;
1284                 pixel.blue=geometry_info.xi;
1285                 color->red=ClampToQuantum(pixel.red);
1286                 color->green=ClampToQuantum(pixel.green);
1287                 color->blue=ClampToQuantum(pixel.blue);
1288               }
1289           }
1290           break;
1291         }
1292       if (LocaleCompare(attribute,"colorspace") == 0)
1293         {
1294           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1295             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1296           if (sp < 0)
1297             {
1298               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1299                 SvPV(sval,na));
1300               break;
1301             }
1302           for ( ; image; image=image->next)
1303             (void) SetImageColorspace(image,(ColorspaceType) sp,exception);
1304           break;
1305         }
1306       if (LocaleCompare(attribute,"comment") == 0)
1307         {
1308           for ( ; image; image=image->next)
1309             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1310               info ? info->image_info : (ImageInfo *) NULL,image,
1311               SvPV(sval,na),exception),exception);
1312           break;
1313         }
1314       if (LocaleCompare(attribute,"compression") == 0)
1315         {
1316           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1317             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1318           if (sp < 0)
1319             {
1320               ThrowPerlException(exception,OptionError,
1321                 "UnrecognizedImageCompression",SvPV(sval,na));
1322               break;
1323             }
1324           if (info)
1325             info->image_info->compression=(CompressionType) sp;
1326           for ( ; image; image=image->next)
1327             image->compression=(CompressionType) sp;
1328           break;
1329         }
1330       if (info)
1331         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1332       for ( ; image; image=image->next)
1333         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1334       break;
1335     }
1336     case 'D':
1337     case 'd':
1338     {
1339       if (LocaleCompare(attribute,"debug") == 0)
1340         {
1341           SetLogEventMask(SvPV(sval,na));
1342           break;
1343         }
1344       if (LocaleCompare(attribute,"delay") == 0)
1345         {
1346           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1347           for ( ; image; image=image->next)
1348           {
1349             image->delay=(size_t) floor(geometry_info.rho+0.5);
1350             if ((flags & SigmaValue) != 0)
1351               image->ticks_per_second=(ssize_t)
1352                 floor(geometry_info.sigma+0.5);
1353           }
1354           break;
1355         }
1356       if (LocaleCompare(attribute,"disk-limit") == 0)
1357         {
1358           MagickSizeType
1359             limit;
1360
1361           limit=MagickResourceInfinity;
1362           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1363             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1364               100.0);
1365           (void) SetMagickResourceLimit(DiskResource,limit);
1366           break;
1367         }
1368       if (LocaleCompare(attribute,"density") == 0)
1369         {
1370           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1371             {
1372               ThrowPerlException(exception,OptionError,"MissingGeometry",
1373                 SvPV(sval,na));
1374               break;
1375             }
1376           if (info)
1377             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1378           for ( ; image; image=image->next)
1379           {
1380             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1381             image->resolution.x=geometry_info.rho;
1382             image->resolution.y=geometry_info.sigma;
1383             if ((flags & SigmaValue) == 0)
1384               image->resolution.y=image->resolution.x;
1385           }
1386           break;
1387         }
1388       if (LocaleCompare(attribute,"depth") == 0)
1389         {
1390           if (info)
1391             info->image_info->depth=SvIV(sval);
1392           for ( ; image; image=image->next)
1393             (void) SetImageDepth(image,SvIV(sval),exception);
1394           break;
1395         }
1396       if (LocaleCompare(attribute,"dispose") == 0)
1397         {
1398           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1399             SvPV(sval,na)) : SvIV(sval);
1400           if (sp < 0)
1401             {
1402               ThrowPerlException(exception,OptionError,
1403                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1404               break;
1405             }
1406           for ( ; image; image=image->next)
1407             image->dispose=(DisposeType) sp;
1408           break;
1409         }
1410       if (LocaleCompare(attribute,"dither") == 0)
1411         {
1412           if (info)
1413             {
1414               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1415                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1416               if (sp < 0)
1417                 {
1418                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1419                     SvPV(sval,na));
1420                   break;
1421                 }
1422               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1423             }
1424           break;
1425         }
1426       if (LocaleCompare(attribute,"display") == 0)
1427         {
1428           display:
1429           if (info)
1430             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1431           break;
1432         }
1433       if (info)
1434         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1435       for ( ; image; image=image->next)
1436         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1437       break;
1438     }
1439     case 'E':
1440     case 'e':
1441     {
1442       if (LocaleCompare(attribute,"endian") == 0)
1443         {
1444           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1445             SvPV(sval,na)) : SvIV(sval);
1446           if (sp < 0)
1447             {
1448               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1449                 SvPV(sval,na));
1450               break;
1451             }
1452           if (info)
1453             info->image_info->endian=(EndianType) sp;
1454           for ( ; image; image=image->next)
1455             image->endian=(EndianType) sp;
1456           break;
1457         }
1458       if (LocaleCompare(attribute,"extract") == 0)
1459         {
1460           /*
1461             Set image extract geometry.
1462           */
1463           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1464           break;
1465         }
1466       if (info)
1467         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1468       for ( ; image; image=image->next)
1469         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1470       break;
1471     }
1472     case 'F':
1473     case 'f':
1474     {
1475       if (LocaleCompare(attribute,"filename") == 0)
1476         {
1477           if (info)
1478             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1479               MagickPathExtent);
1480           for ( ; image; image=image->next)
1481             (void) CopyMagickString(image->filename,SvPV(sval,na),
1482               MagickPathExtent);
1483           break;
1484         }
1485       if (LocaleCompare(attribute,"file") == 0)
1486         {
1487           FILE
1488             *file;
1489
1490           PerlIO
1491             *io_info;
1492
1493           if (info == (struct PackageInfo *) NULL)
1494             break;
1495           io_info=IoIFP(sv_2io(sval));
1496           if (io_info == (PerlIO *) NULL)
1497             {
1498               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1499                 PackageName);
1500               break;
1501             }
1502           file=PerlIO_findFILE(io_info);
1503           if (file == (FILE *) NULL)
1504             {
1505               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1506                 PackageName);
1507               break;
1508             }
1509           SetImageInfoFile(info->image_info,file);
1510           break;
1511         }
1512       if (LocaleCompare(attribute,"fill") == 0)
1513         {
1514           if (info)
1515             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1516           break;
1517         }
1518       if (LocaleCompare(attribute,"font") == 0)
1519         {
1520           if (info)
1521             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1522           break;
1523         }
1524       if (LocaleCompare(attribute,"foreground") == 0)
1525         break;
1526       if (LocaleCompare(attribute,"fuzz") == 0)
1527         {
1528           if (info)
1529             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1530               QuantumRange+1.0);
1531           for ( ; image; image=image->next)
1532             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1533               QuantumRange+1.0);
1534           break;
1535         }
1536       if (info)
1537         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1538       for ( ; image; image=image->next)
1539         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1540       break;
1541     }
1542     case 'G':
1543     case 'g':
1544     {
1545       if (LocaleCompare(attribute,"gamma") == 0)
1546         {
1547           for ( ; image; image=image->next)
1548             image->gamma=SvNV(sval);
1549           break;
1550         }
1551       if (LocaleCompare(attribute,"gravity") == 0)
1552         {
1553           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1554             SvPV(sval,na)) : SvIV(sval);
1555           if (sp < 0)
1556             {
1557               ThrowPerlException(exception,OptionError,
1558                 "UnrecognizedGravityType",SvPV(sval,na));
1559               break;
1560             }
1561           if (info)
1562             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1563           for ( ; image; image=image->next)
1564             image->gravity=(GravityType) sp;
1565           break;
1566         }
1567       if (LocaleCompare(attribute,"green-primary") == 0)
1568         {
1569           for ( ; image; image=image->next)
1570           {
1571             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1572             image->chromaticity.green_primary.x=geometry_info.rho;
1573             image->chromaticity.green_primary.y=geometry_info.sigma;
1574             if ((flags & SigmaValue) == 0)
1575               image->chromaticity.green_primary.y=
1576                 image->chromaticity.green_primary.x;
1577           }
1578           break;
1579         }
1580       if (info)
1581         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1582       for ( ; image; image=image->next)
1583         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1584       break;
1585     }
1586     case 'I':
1587     case 'i':
1588     {
1589       if (LocaleNCompare(attribute,"index",5) == 0)
1590         {
1591           int
1592             items;
1593
1594           long
1595             index;
1596
1597           register Quantum
1598             *q;
1599
1600           CacheView
1601             *image_view;
1602
1603           for ( ; image; image=image->next)
1604           {
1605             if (image->storage_class != PseudoClass)
1606               continue;
1607             x=0;
1608             y=0;
1609             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1610             (void) items;
1611             image_view=AcquireAuthenticCacheView(image,exception);
1612             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1613             if (q != (Quantum *) NULL)
1614               {
1615                 items=sscanf(SvPV(sval,na),"%ld",&index);
1616                 if ((index >= 0) && (index < (ssize_t) image->colors))
1617                   SetPixelIndex(image,index,q);
1618                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1619               }
1620             image_view=DestroyCacheView(image_view);
1621           }
1622           break;
1623         }
1624       if (LocaleCompare(attribute,"iterations") == 0)
1625         {
1626   iterations:
1627           for ( ; image; image=image->next)
1628             image->iterations=SvIV(sval);
1629           break;
1630         }
1631       if (LocaleCompare(attribute,"interlace") == 0)
1632         {
1633           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1634             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1635           if (sp < 0)
1636             {
1637               ThrowPerlException(exception,OptionError,
1638                 "UnrecognizedInterlaceType",SvPV(sval,na));
1639               break;
1640             }
1641           if (info)
1642             info->image_info->interlace=(InterlaceType) sp;
1643           for ( ; image; image=image->next)
1644             image->interlace=(InterlaceType) sp;
1645           break;
1646         }
1647       if (info)
1648         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1649       for ( ; image; image=image->next)
1650         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1651       break;
1652     }
1653     case 'L':
1654     case 'l':
1655     {
1656       if (LocaleCompare(attribute,"label") == 0)
1657         {
1658           for ( ; image; image=image->next)
1659             (void) SetImageProperty(image,"label",InterpretImageProperties(
1660               info ? info->image_info : (ImageInfo *) NULL,image,
1661               SvPV(sval,na),exception),exception);
1662           break;
1663         }
1664       if (LocaleCompare(attribute,"loop") == 0)
1665         goto iterations;
1666       if (info)
1667         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1668       for ( ; image; image=image->next)
1669         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1670       break;
1671     }
1672     case 'M':
1673     case 'm':
1674     {
1675       if (LocaleCompare(attribute,"magick") == 0)
1676         {
1677           if (info)
1678             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1679               "%s:",SvPV(sval,na));
1680           for ( ; image; image=image->next)
1681             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1682           break;
1683         }
1684       if (LocaleCompare(attribute,"map-limit") == 0)
1685         {
1686           MagickSizeType
1687             limit;
1688
1689           limit=MagickResourceInfinity;
1690           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1691             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1692               100.0);
1693           (void) SetMagickResourceLimit(MapResource,limit);
1694           break;
1695         }
1696       if (LocaleCompare(attribute,"mask") == 0)
1697         {
1698           Image
1699             *mask;
1700
1701           mask=(Image *) NULL;
1702           if (SvPOK(sval))
1703             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1704           for ( ; image; image=image->next)
1705             SetImageMask(image,ReadPixelMask,mask,exception);
1706           break;
1707         }
1708       if (LocaleCompare(attribute,"mattecolor") == 0)
1709         {
1710           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1711             exception);
1712           if (info)
1713             info->image_info->alpha_color=target_color;
1714           for ( ; image; image=image->next)
1715             image->alpha_color=target_color;
1716           break;
1717         }
1718       if (LocaleCompare(attribute,"matte") == 0)
1719         {
1720           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1721             SvPV(sval,na)) : SvIV(sval);
1722           if (sp < 0)
1723             {
1724               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1725                 SvPV(sval,na));
1726               break;
1727             }
1728           for ( ; image; image=image->next)
1729             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1730           break;
1731         }
1732       if (LocaleCompare(attribute,"memory-limit") == 0)
1733         {
1734           MagickSizeType
1735             limit;
1736
1737           limit=MagickResourceInfinity;
1738           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1739             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1740               100.0);
1741           (void) SetMagickResourceLimit(MemoryResource,limit);
1742           break;
1743         }
1744       if (LocaleCompare(attribute,"monochrome") == 0)
1745         {
1746           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1747             SvPV(sval,na)) : SvIV(sval);
1748           if (sp < 0)
1749             {
1750               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1751                 SvPV(sval,na));
1752               break;
1753             }
1754           if (info)
1755             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1756           for ( ; image; image=image->next)
1757             (void) SetImageType(image,BilevelType,exception);
1758           break;
1759         }
1760       if (info)
1761         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1762       for ( ; image; image=image->next)
1763         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1764       break;
1765     }
1766     case 'O':
1767     case 'o':
1768     {
1769       if (LocaleCompare(attribute,"option") == 0)
1770         {
1771           if (info)
1772             DefineImageOption(info->image_info,SvPV(sval,na));
1773           break;
1774         }
1775       if (LocaleCompare(attribute,"orientation") == 0)
1776         {
1777           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1778             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1779           if (sp < 0)
1780             {
1781               ThrowPerlException(exception,OptionError,
1782                 "UnrecognizedOrientationType",SvPV(sval,na));
1783               break;
1784             }
1785           if (info)
1786             info->image_info->orientation=(OrientationType) sp;
1787           for ( ; image; image=image->next)
1788             image->orientation=(OrientationType) sp;
1789           break;
1790         }
1791       if (info)
1792         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1793       for ( ; image; image=image->next)
1794         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1795       break;
1796     }
1797     case 'P':
1798     case 'p':
1799     {
1800       if (LocaleCompare(attribute,"page") == 0)
1801         {
1802           char
1803             *geometry;
1804
1805           geometry=GetPageGeometry(SvPV(sval,na));
1806           if (info)
1807             (void) CloneString(&info->image_info->page,geometry);
1808           for ( ; image; image=image->next)
1809             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1810           geometry=(char *) RelinquishMagickMemory(geometry);
1811           break;
1812         }
1813       if (LocaleNCompare(attribute,"pixel",5) == 0)
1814         {
1815           int
1816             items;
1817
1818           PixelInfo
1819             pixel;
1820
1821           register Quantum
1822             *q;
1823
1824           CacheView
1825             *image_view;
1826
1827           for ( ; image; image=image->next)
1828           {
1829             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1830               break;
1831             x=0;
1832             y=0;
1833             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1834             (void) items;
1835             image_view=AcquireVirtualCacheView(image,exception);
1836             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1837             if (q != (Quantum *) NULL)
1838               {
1839                 if ((strchr(SvPV(sval,na),',') == 0) ||
1840                     (strchr(SvPV(sval,na),')') != 0))
1841                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1842                     &pixel,exception);
1843                 else
1844                   {
1845                     GetPixelInfo(image,&pixel);
1846                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1847                     pixel.red=geometry_info.rho;
1848                     if ((flags & SigmaValue) != 0)
1849                       pixel.green=geometry_info.sigma;
1850                     if ((flags & XiValue) != 0)
1851                       pixel.blue=geometry_info.xi;
1852                     if ((flags & PsiValue) != 0)
1853                       pixel.alpha=geometry_info.psi;
1854                     if ((flags & ChiValue) != 0)
1855                       pixel.black=geometry_info.chi;
1856                   }
1857                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1858                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1859                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1860                 if (image->colorspace == CMYKColorspace)
1861                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1862                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1863                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1864               }
1865             image_view=DestroyCacheView(image_view);
1866           }
1867           break;
1868         }
1869       if (LocaleCompare(attribute,"pointsize") == 0)
1870         {
1871           if (info)
1872             {
1873               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1874               info->image_info->pointsize=geometry_info.rho;
1875             }
1876           break;
1877         }
1878       if (info)
1879         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1880       for ( ; image; image=image->next)
1881         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1882       break;
1883     }
1884     case 'Q':
1885     case 'q':
1886     {
1887       if (LocaleCompare(attribute,"quality") == 0)
1888         {
1889           if (info)
1890             info->image_info->quality=SvIV(sval);
1891           for ( ; image; image=image->next)
1892             image->quality=SvIV(sval);
1893           break;
1894         }
1895       if (info)
1896         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1897       for ( ; image; image=image->next)
1898         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1899       break;
1900     }
1901     case 'R':
1902     case 'r':
1903     {
1904       if (LocaleCompare(attribute,"read-mask") == 0)
1905         {
1906           Image
1907             *mask;
1908
1909           mask=(Image *) NULL;
1910           if (SvPOK(sval))
1911             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1912           for ( ; image; image=image->next)
1913             SetImageMask(image,ReadPixelMask,mask,exception);
1914           break;
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,"virtual-pixel") == 0)
2190         {
2191           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2192             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2193           if (sp < 0)
2194             {
2195               ThrowPerlException(exception,OptionError,
2196                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2197               break;
2198             }
2199           for ( ; image; image=image->next)
2200             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2201           break;
2202         }
2203       if (info)
2204         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2205       for ( ; image; image=image->next)
2206         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2207       break;
2208     }
2209     case 'W':
2210     case 'w':
2211     {
2212       if (LocaleCompare(attribute,"white-point") == 0)
2213         {
2214           for ( ; image; image=image->next)
2215           {
2216             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2217             image->chromaticity.white_point.x=geometry_info.rho;
2218             image->chromaticity.white_point.y=geometry_info.sigma;
2219             if ((flags & SigmaValue) == 0)
2220               image->chromaticity.white_point.y=
2221                 image->chromaticity.white_point.x;
2222           }
2223           break;
2224         }
2225       if (LocaleCompare(attribute,"write-mask") == 0)
2226         {
2227           Image
2228             *mask;
2229
2230           mask=(Image *) NULL;
2231           if (SvPOK(sval))
2232             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2233           for ( ; image; image=image->next)
2234             SetImageMask(image,WritePixelMask,mask,exception);
2235           break;
2236         }
2237       if (info)
2238         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2239       for ( ; image; image=image->next)
2240         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2241       break;
2242     }
2243     default:
2244     {
2245       if (info)
2246         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2247       for ( ; image; image=image->next)
2248         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2249       break;
2250     }
2251   }
2252 }
2253 \f
2254 /*
2255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2256 %                                                                             %
2257 %                                                                             %
2258 %                                                                             %
2259 %   S e t u p L i s t                                                         %
2260 %                                                                             %
2261 %                                                                             %
2262 %                                                                             %
2263 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264 %
2265 %  Method SetupList returns the list of all the images linked by their
2266 %  image->next and image->previous link lists for use with ImageMagick.  If
2267 %  info is non-NULL, an info structure is returned in *info.  If
2268 %  reference_vector is non-NULL,an array of SV* are returned in
2269 %  *reference_vector.  Reference_vector is used when the images are going to be
2270 %  replaced with new Image*'s.
2271 %
2272 %  The format of the SetupList routine is:
2273 %
2274 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2275 %        SV ***reference_vector,ExceptionInfo *exception)
2276 %
2277 %  A description of each parameter follows:
2278 %
2279 %    o list: a list of strings.
2280 %
2281 %    o string: a character string.
2282 %
2283 %    o exception: Return any errors or warnings in this structure.
2284 %
2285 */
2286 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2287   SV ***reference_vector,ExceptionInfo *exception)
2288 {
2289   Image
2290     *image;
2291
2292   ssize_t
2293     current,
2294     last;
2295
2296   if (reference_vector)
2297     *reference_vector=NULL;
2298   if (info)
2299     *info=NULL;
2300   current=0;
2301   last=0;
2302   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2303   if (info && (SvTYPE(reference) == SVt_PVAV))
2304     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2305       exception);
2306   return(image);
2307 }
2308 \f
2309 /*
2310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2311 %                                                                             %
2312 %                                                                             %
2313 %                                                                             %
2314 %   s t r E Q c a s e                                                         %
2315 %                                                                             %
2316 %                                                                             %
2317 %                                                                             %
2318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2319 %
2320 %  strEQcase() compares two strings and returns 0 if they are the
2321 %  same or if the second string runs out first.  The comparison is case
2322 %  insensitive.
2323 %
2324 %  The format of the strEQcase routine is:
2325 %
2326 %      ssize_t strEQcase(const char *p,const char *q)
2327 %
2328 %  A description of each parameter follows:
2329 %
2330 %    o p: a character string.
2331 %
2332 %    o q: a character string.
2333 %
2334 %
2335 */
2336 static ssize_t strEQcase(const char *p,const char *q)
2337 {
2338   char
2339     c;
2340
2341   register ssize_t
2342     i;
2343
2344   for (i=0 ; (c=(*q)) != 0; i++)
2345   {
2346     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2347         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2348       return(0);
2349     p++;
2350     q++;
2351   }
2352   return(((*q == 0) && (*p == 0)) ? i : 0);
2353 }
2354 \f
2355 /*
2356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2357 %                                                                             %
2358 %                                                                             %
2359 %                                                                             %
2360 %   I m a g e : : M a g i c k                                                 %
2361 %                                                                             %
2362 %                                                                             %
2363 %                                                                             %
2364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2365 %
2366 %
2367 */
2368 MODULE = Image::Magick PACKAGE = Image::Magick
2369
2370 PROTOTYPES: ENABLE
2371
2372 BOOT:
2373   MagickCoreGenesis("PerlMagick",MagickFalse);
2374   SetWarningHandler(NULL);
2375   SetErrorHandler(NULL);
2376   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2377     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2378
2379 void
2380 UNLOAD()
2381   PPCODE:
2382   {
2383     if (magick_registry != (SplayTreeInfo *) NULL)
2384       magick_registry=DestroySplayTree(magick_registry);
2385     MagickCoreTerminus();
2386   }
2387
2388 double
2389 constant(name,argument)
2390   char *name
2391   ssize_t argument
2392 \f
2393 #
2394 ###############################################################################
2395 #                                                                             #
2396 #                                                                             #
2397 #                                                                             #
2398 #   A n i m a t e                                                             #
2399 #                                                                             #
2400 #                                                                             #
2401 #                                                                             #
2402 ###############################################################################
2403 #
2404 #
2405 void
2406 Animate(ref,...)
2407   Image::Magick ref=NO_INIT
2408   ALIAS:
2409     AnimateImage  = 1
2410     animate       = 2
2411     animateimage  = 3
2412   PPCODE:
2413   {
2414     ExceptionInfo
2415       *exception;
2416
2417     Image
2418       *image;
2419
2420     register ssize_t
2421       i;
2422
2423     struct PackageInfo
2424       *info,
2425       *package_info;
2426
2427     SV
2428       *perl_exception,
2429       *reference;
2430
2431     PERL_UNUSED_VAR(ref);
2432     PERL_UNUSED_VAR(ix);
2433     exception=AcquireExceptionInfo();
2434     perl_exception=newSVpv("",0);
2435     package_info=(struct PackageInfo *) NULL;
2436     if (sv_isobject(ST(0)) == 0)
2437       {
2438         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2439           PackageName);
2440         goto PerlException;
2441       }
2442     reference=SvRV(ST(0));
2443     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2444     if (image == (Image *) NULL)
2445       {
2446         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2447           PackageName);
2448         goto PerlException;
2449       }
2450     package_info=ClonePackageInfo(info,exception);
2451     if (items == 2)
2452       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2453     else
2454       if (items > 2)
2455         for (i=2; i < items; i+=2)
2456           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2457             exception);
2458     (void) AnimateImages(package_info->image_info,image,exception);
2459     (void) CatchImageException(image);
2460
2461   PerlException:
2462     if (package_info != (struct PackageInfo *) NULL)
2463       DestroyPackageInfo(package_info);
2464     InheritPerlException(exception,perl_exception);
2465     exception=DestroyExceptionInfo(exception);
2466     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2467     SvPOK_on(perl_exception);
2468     ST(0)=sv_2mortal(perl_exception);
2469     XSRETURN(1);
2470   }
2471 \f
2472 #
2473 ###############################################################################
2474 #                                                                             #
2475 #                                                                             #
2476 #                                                                             #
2477 #   A p p e n d                                                               #
2478 #                                                                             #
2479 #                                                                             #
2480 #                                                                             #
2481 ###############################################################################
2482 #
2483 #
2484 void
2485 Append(ref,...)
2486   Image::Magick ref=NO_INIT
2487   ALIAS:
2488     AppendImage  = 1
2489     append       = 2
2490     appendimage  = 3
2491   PPCODE:
2492   {
2493     AV
2494       *av;
2495
2496     char
2497       *attribute;
2498
2499     ExceptionInfo
2500       *exception;
2501
2502     HV
2503       *hv;
2504
2505     Image
2506       *image;
2507
2508     register ssize_t
2509       i;
2510
2511     ssize_t
2512       stack;
2513
2514     struct PackageInfo
2515       *info;
2516
2517     SV
2518       *av_reference,
2519       *perl_exception,
2520       *reference,
2521       *rv,
2522       *sv;
2523
2524     PERL_UNUSED_VAR(ref);
2525     PERL_UNUSED_VAR(ix);
2526     exception=AcquireExceptionInfo();
2527     perl_exception=newSVpv("",0);
2528     sv=NULL;
2529     attribute=NULL;
2530     av=NULL;
2531     if (sv_isobject(ST(0)) == 0)
2532       {
2533         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2534           PackageName);
2535         goto PerlException;
2536       }
2537     reference=SvRV(ST(0));
2538     hv=SvSTASH(reference);
2539     av=newAV();
2540     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2541     SvREFCNT_dec(av);
2542     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2543     if (image == (Image *) NULL)
2544       {
2545         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2546           PackageName);
2547         goto PerlException;
2548       }
2549     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2550     /*
2551       Get options.
2552     */
2553     stack=MagickTrue;
2554     for (i=2; i < items; i+=2)
2555     {
2556       attribute=(char *) SvPV(ST(i-1),na);
2557       switch (*attribute)
2558       {
2559         case 'S':
2560         case 's':
2561         {
2562           if (LocaleCompare(attribute,"stack") == 0)
2563             {
2564               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2565                 SvPV(ST(i),na));
2566               if (stack < 0)
2567                 {
2568                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2569                     SvPV(ST(i),na));
2570                   return;
2571                 }
2572               break;
2573             }
2574           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2575             attribute);
2576           break;
2577         }
2578         default:
2579         {
2580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2581             attribute);
2582           break;
2583         }
2584       }
2585     }
2586     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2587     if (image == (Image *) NULL)
2588       goto PerlException;
2589     for ( ; image; image=image->next)
2590     {
2591       AddImageToRegistry(sv,image);
2592       rv=newRV(sv);
2593       av_push(av,sv_bless(rv,hv));
2594       SvREFCNT_dec(sv);
2595     }
2596     exception=DestroyExceptionInfo(exception);
2597     ST(0)=av_reference;
2598     SvREFCNT_dec(perl_exception);
2599     XSRETURN(1);
2600
2601   PerlException:
2602     InheritPerlException(exception,perl_exception);
2603     exception=DestroyExceptionInfo(exception);
2604     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2605     SvPOK_on(perl_exception);
2606     ST(0)=sv_2mortal(perl_exception);
2607     XSRETURN(1);
2608   }
2609 \f
2610 #
2611 ###############################################################################
2612 #                                                                             #
2613 #                                                                             #
2614 #                                                                             #
2615 #   A v e r a g e                                                             #
2616 #                                                                             #
2617 #                                                                             #
2618 #                                                                             #
2619 ###############################################################################
2620 #
2621 #
2622 void
2623 Average(ref)
2624   Image::Magick ref=NO_INIT
2625   ALIAS:
2626     AverageImage   = 1
2627     average        = 2
2628     averageimage   = 3
2629   PPCODE:
2630   {
2631     AV
2632       *av;
2633
2634     char
2635       *p;
2636
2637     ExceptionInfo
2638       *exception;
2639
2640     HV
2641       *hv;
2642
2643     Image
2644       *image;
2645
2646     struct PackageInfo
2647       *info;
2648
2649     SV
2650       *perl_exception,
2651       *reference,
2652       *rv,
2653       *sv;
2654
2655     PERL_UNUSED_VAR(ref);
2656     PERL_UNUSED_VAR(ix);
2657     exception=AcquireExceptionInfo();
2658     perl_exception=newSVpv("",0);
2659     sv=NULL;
2660     if (sv_isobject(ST(0)) == 0)
2661       {
2662         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2663           PackageName);
2664         goto PerlException;
2665       }
2666     reference=SvRV(ST(0));
2667     hv=SvSTASH(reference);
2668     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2669     if (image == (Image *) NULL)
2670       {
2671         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2672           PackageName);
2673         goto PerlException;
2674       }
2675     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2676     if (image == (Image *) NULL)
2677       goto PerlException;
2678     /*
2679       Create blessed Perl array for the returned image.
2680     */
2681     av=newAV();
2682     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2683     SvREFCNT_dec(av);
2684     AddImageToRegistry(sv,image);
2685     rv=newRV(sv);
2686     av_push(av,sv_bless(rv,hv));
2687     SvREFCNT_dec(sv);
2688     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2689     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2690       "average-%.*s",(int) (MagickPathExtent-9),
2691       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2692     (void) CopyMagickString(image->filename,info->image_info->filename,
2693       MagickPathExtent);
2694     SetImageInfo(info->image_info,0,exception);
2695     exception=DestroyExceptionInfo(exception);
2696     SvREFCNT_dec(perl_exception);
2697     XSRETURN(1);
2698
2699   PerlException:
2700     InheritPerlException(exception,perl_exception);
2701     exception=DestroyExceptionInfo(exception);
2702     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2703     SvPOK_on(perl_exception);
2704     ST(0)=sv_2mortal(perl_exception);
2705     XSRETURN(1);
2706   }
2707 \f
2708 #
2709 ###############################################################################
2710 #                                                                             #
2711 #                                                                             #
2712 #                                                                             #
2713 #   B l o b T o I m a g e                                                     #
2714 #                                                                             #
2715 #                                                                             #
2716 #                                                                             #
2717 ###############################################################################
2718 #
2719 #
2720 void
2721 BlobToImage(ref,...)
2722   Image::Magick ref=NO_INIT
2723   ALIAS:
2724     BlobToImage  = 1
2725     blobtoimage  = 2
2726     blobto       = 3
2727   PPCODE:
2728   {
2729     AV
2730       *av;
2731
2732     char
2733       **keep,
2734       **list;
2735
2736     ExceptionInfo
2737       *exception;
2738
2739     HV
2740       *hv;
2741
2742     Image
2743       *image;
2744
2745     register char
2746       **p;
2747
2748     register ssize_t
2749       i;
2750
2751     ssize_t
2752       ac,
2753       n,
2754       number_images;
2755
2756     STRLEN
2757       *length;
2758
2759     struct PackageInfo
2760       *info;
2761
2762     SV
2763       *perl_exception,
2764       *reference,
2765       *rv,
2766       *sv;
2767
2768     PERL_UNUSED_VAR(ref);
2769     PERL_UNUSED_VAR(ix);
2770     exception=AcquireExceptionInfo();
2771     perl_exception=newSVpv("",0);
2772     sv=NULL;
2773     number_images=0;
2774     ac=(items < 2) ? 1 : items-1;
2775     length=(STRLEN *) NULL;
2776     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2777     if (list == (char **) NULL)
2778       {
2779         ThrowPerlException(exception,ResourceLimitError,
2780           "MemoryAllocationFailed",PackageName);
2781         goto PerlException;
2782       }
2783     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2784     if (length == (STRLEN *) NULL)
2785       {
2786         ThrowPerlException(exception,ResourceLimitError,
2787           "MemoryAllocationFailed",PackageName);
2788         goto PerlException;
2789       }
2790     if (sv_isobject(ST(0)) == 0)
2791       {
2792         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2793           PackageName);
2794         goto PerlException;
2795       }
2796     reference=SvRV(ST(0));
2797     hv=SvSTASH(reference);
2798     if (SvTYPE(reference) != SVt_PVAV)
2799       {
2800         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2801           PackageName);
2802         goto PerlException;
2803       }
2804     av=(AV *) reference;
2805     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2806       exception);
2807     n=1;
2808     if (items <= 1)
2809       {
2810         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2811         goto PerlException;
2812       }
2813     for (n=0, i=0; i < ac; i++)
2814     {
2815       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2816       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2817         {
2818           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2819           continue;
2820         }
2821       n++;
2822     }
2823     list[n]=(char *) NULL;
2824     keep=list;
2825     for (i=number_images=0; i < n; i++)
2826     {
2827       image=BlobToImage(info->image_info,list[i],length[i],exception);
2828       if (image == (Image *) NULL)
2829         break;
2830       for ( ; image; image=image->next)
2831       {
2832         AddImageToRegistry(sv,image);
2833         rv=newRV(sv);
2834         av_push(av,sv_bless(rv,hv));
2835         SvREFCNT_dec(sv);
2836         number_images++;
2837       }
2838     }
2839     /*
2840       Free resources.
2841     */
2842     for (i=0; i < n; i++)
2843       if (list[i] != (char *) NULL)
2844         for (p=keep; list[i] != *p++; )
2845           if (*p == (char *) NULL)
2846             {
2847               list[i]=(char *) RelinquishMagickMemory(list[i]);
2848               break;
2849             }
2850
2851   PerlException:
2852     if (list)
2853       list=(char **) RelinquishMagickMemory(list);
2854     if (length)
2855       length=(STRLEN *) RelinquishMagickMemory(length);
2856     InheritPerlException(exception,perl_exception);
2857     exception=DestroyExceptionInfo(exception);
2858     sv_setiv(perl_exception,(IV) number_images);
2859     SvPOK_on(perl_exception);
2860     ST(0)=sv_2mortal(perl_exception);
2861     XSRETURN(1);
2862   }
2863 \f
2864 #
2865 ###############################################################################
2866 #                                                                             #
2867 #                                                                             #
2868 #                                                                             #
2869 #   C h a n n e l F x                                                         #
2870 #                                                                             #
2871 #                                                                             #
2872 #                                                                             #
2873 ###############################################################################
2874 #
2875 #
2876 void
2877 ChannelFx(ref,...)
2878   Image::Magick ref=NO_INIT
2879   ALIAS:
2880     ChannelFxImage  = 1
2881     channelfx       = 2
2882     channelfximage  = 3
2883   PPCODE:
2884   {
2885     AV
2886       *av;
2887
2888     char
2889       *attribute,
2890       expression[MagickPathExtent];
2891
2892     ChannelType
2893       channel,
2894       channel_mask;
2895
2896     ExceptionInfo
2897       *exception;
2898
2899     HV
2900       *hv;
2901
2902     Image
2903       *image;
2904
2905     register ssize_t
2906       i;
2907
2908     struct PackageInfo
2909       *info;
2910
2911     SV
2912       *av_reference,
2913       *perl_exception,
2914       *reference,
2915       *rv,
2916       *sv;
2917
2918     PERL_UNUSED_VAR(ref);
2919     PERL_UNUSED_VAR(ix);
2920     exception=AcquireExceptionInfo();
2921     perl_exception=newSVpv("",0);
2922     sv=NULL;
2923     attribute=NULL;
2924     av=NULL;
2925     if (sv_isobject(ST(0)) == 0)
2926       {
2927         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2928           PackageName);
2929         goto PerlException;
2930       }
2931     reference=SvRV(ST(0));
2932     hv=SvSTASH(reference);
2933     av=newAV();
2934     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2935     SvREFCNT_dec(av);
2936     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2937     if (image == (Image *) NULL)
2938       {
2939         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2940           PackageName);
2941         goto PerlException;
2942       }
2943     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2944     /*
2945       Get options.
2946     */
2947     channel=DefaultChannels;
2948     (void) CopyMagickString(expression,"u",MagickPathExtent);
2949     if (items == 2)
2950       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2951     else
2952       for (i=2; i < items; i+=2)
2953       {
2954         attribute=(char *) SvPV(ST(i-1),na);
2955         switch (*attribute)
2956         {
2957           case 'C':
2958           case 'c':
2959           {
2960             if (LocaleCompare(attribute,"channel") == 0)
2961               {
2962                 ssize_t
2963                   option;
2964
2965                 option=ParseChannelOption(SvPV(ST(i),na));
2966                 if (option < 0)
2967                   {
2968                     ThrowPerlException(exception,OptionError,
2969                       "UnrecognizedType",SvPV(ST(i),na));
2970                     return;
2971                   }
2972                 channel=(ChannelType) option;
2973                 break;
2974               }
2975             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2976               attribute);
2977             break;
2978           }
2979           case 'E':
2980           case 'e':
2981           {
2982             if (LocaleCompare(attribute,"expression") == 0)
2983               {
2984                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2985                   MagickPathExtent);
2986                 break;
2987               }
2988             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2989               attribute);
2990             break;
2991           }
2992           default:
2993           {
2994             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2995               attribute);
2996             break;
2997           }
2998         }
2999       }
3000     channel_mask=SetImageChannelMask(image,channel);
3001     image=ChannelFxImage(image,expression,exception);
3002     if (image != (Image *) NULL)
3003       (void) SetImageChannelMask(image,channel_mask);
3004     if (image == (Image *) NULL)
3005       goto PerlException;
3006     for ( ; image; image=image->next)
3007     {
3008       AddImageToRegistry(sv,image);
3009       rv=newRV(sv);
3010       av_push(av,sv_bless(rv,hv));
3011       SvREFCNT_dec(sv);
3012     }
3013     exception=DestroyExceptionInfo(exception);
3014     ST(0)=av_reference;
3015     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3016     XSRETURN(1);
3017
3018   PerlException:
3019     InheritPerlException(exception,perl_exception);
3020     exception=DestroyExceptionInfo(exception);
3021     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3022     SvPOK_on(perl_exception);
3023     ST(0)=sv_2mortal(perl_exception);
3024     XSRETURN(1);
3025   }
3026 \f
3027 #
3028 ###############################################################################
3029 #                                                                             #
3030 #                                                                             #
3031 #                                                                             #
3032 #   C l o n e                                                                 #
3033 #                                                                             #
3034 #                                                                             #
3035 #                                                                             #
3036 ###############################################################################
3037 #
3038 #
3039 void
3040 Clone(ref)
3041   Image::Magick ref=NO_INIT
3042   ALIAS:
3043     CopyImage   = 1
3044     copy        = 2
3045     copyimage   = 3
3046     CloneImage  = 4
3047     clone       = 5
3048     cloneimage  = 6
3049     Clone       = 7
3050   PPCODE:
3051   {
3052     AV
3053       *av;
3054
3055     ExceptionInfo
3056       *exception;
3057
3058     HV
3059       *hv;
3060
3061     Image
3062       *clone,
3063       *image;
3064
3065     struct PackageInfo
3066       *info;
3067
3068     SV
3069       *perl_exception,
3070       *reference,
3071       *rv,
3072       *sv;
3073
3074     PERL_UNUSED_VAR(ref);
3075     PERL_UNUSED_VAR(ix);
3076     exception=AcquireExceptionInfo();
3077     perl_exception=newSVpv("",0);
3078     sv=NULL;
3079     if (sv_isobject(ST(0)) == 0)
3080       {
3081         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3082           PackageName);
3083         goto PerlException;
3084       }
3085     reference=SvRV(ST(0));
3086     hv=SvSTASH(reference);
3087     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3088     if (image == (Image *) NULL)
3089       {
3090         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3091           PackageName);
3092         goto PerlException;
3093       }
3094     /*
3095       Create blessed Perl array for the returned image.
3096     */
3097     av=newAV();
3098     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3099     SvREFCNT_dec(av);
3100     for ( ; image; image=image->next)
3101     {
3102       clone=CloneImage(image,0,0,MagickTrue,exception);
3103       if (clone == (Image *) NULL)
3104         break;
3105       AddImageToRegistry(sv,clone);
3106       rv=newRV(sv);
3107       av_push(av,sv_bless(rv,hv));
3108       SvREFCNT_dec(sv);
3109     }
3110     exception=DestroyExceptionInfo(exception);
3111     SvREFCNT_dec(perl_exception);
3112     XSRETURN(1);
3113
3114   PerlException:
3115     InheritPerlException(exception,perl_exception);
3116     exception=DestroyExceptionInfo(exception);
3117     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3118     SvPOK_on(perl_exception);
3119     ST(0)=sv_2mortal(perl_exception);
3120     XSRETURN(1);
3121   }
3122 \f
3123 #
3124 ###############################################################################
3125 #                                                                             #
3126 #                                                                             #
3127 #                                                                             #
3128 #   C L O N E                                                                 #
3129 #                                                                             #
3130 #                                                                             #
3131 #                                                                             #
3132 ###############################################################################
3133 #
3134 #
3135 void
3136 CLONE(ref,...)
3137   SV *ref;
3138   CODE:
3139   {
3140     PERL_UNUSED_VAR(ref);
3141     if (magick_registry != (SplayTreeInfo *) NULL)
3142       {
3143         register Image
3144           *p;
3145
3146         ResetSplayTreeIterator(magick_registry);
3147         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3148         while (p != (Image *) NULL)
3149         {
3150           ReferenceImage(p);
3151           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3152         }
3153       }
3154   }
3155 \f
3156 #
3157 ###############################################################################
3158 #                                                                             #
3159 #                                                                             #
3160 #                                                                             #
3161 #   C o a l e s c e                                                           #
3162 #                                                                             #
3163 #                                                                             #
3164 #                                                                             #
3165 ###############################################################################
3166 #
3167 #
3168 void
3169 Coalesce(ref)
3170   Image::Magick ref=NO_INIT
3171   ALIAS:
3172     CoalesceImage   = 1
3173     coalesce        = 2
3174     coalesceimage   = 3
3175   PPCODE:
3176   {
3177     AV
3178       *av;
3179
3180     ExceptionInfo
3181       *exception;
3182
3183     HV
3184       *hv;
3185
3186     Image
3187       *image;
3188
3189     struct PackageInfo
3190       *info;
3191
3192     SV
3193       *av_reference,
3194       *perl_exception,
3195       *reference,
3196       *rv,
3197       *sv;
3198
3199     PERL_UNUSED_VAR(ref);
3200     PERL_UNUSED_VAR(ix);
3201     exception=AcquireExceptionInfo();
3202     perl_exception=newSVpv("",0);
3203     sv=NULL;
3204     if (sv_isobject(ST(0)) == 0)
3205       {
3206         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3207           PackageName);
3208         goto PerlException;
3209       }
3210     reference=SvRV(ST(0));
3211     hv=SvSTASH(reference);
3212     av=newAV();
3213     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3214     SvREFCNT_dec(av);
3215     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3216     if (image == (Image *) NULL)
3217       {
3218         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3219           PackageName);
3220         goto PerlException;
3221       }
3222     image=CoalesceImages(image,exception);
3223     if (image == (Image *) NULL)
3224       goto PerlException;
3225     for ( ; image; image=image->next)
3226     {
3227       AddImageToRegistry(sv,image);
3228       rv=newRV(sv);
3229       av_push(av,sv_bless(rv,hv));
3230       SvREFCNT_dec(sv);
3231     }
3232     exception=DestroyExceptionInfo(exception);
3233     ST(0)=av_reference;
3234     SvREFCNT_dec(perl_exception);
3235     XSRETURN(1);
3236
3237   PerlException:
3238     InheritPerlException(exception,perl_exception);
3239     exception=DestroyExceptionInfo(exception);
3240     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3241     SvPOK_on(perl_exception);
3242     ST(0)=sv_2mortal(perl_exception);
3243     XSRETURN(1);
3244   }
3245 \f
3246 #
3247 ###############################################################################
3248 #                                                                             #
3249 #                                                                             #
3250 #                                                                             #
3251 #   C o m p a r e                                                             #
3252 #                                                                             #
3253 #                                                                             #
3254 #                                                                             #
3255 ###############################################################################
3256 #
3257 #
3258 void
3259 Compare(ref,...)
3260   Image::Magick ref=NO_INIT
3261   ALIAS:
3262     CompareImages = 1
3263     compare      = 2
3264     compareimage = 3
3265   PPCODE:
3266   {
3267     AV
3268       *av;
3269
3270     char
3271       *attribute;
3272
3273     double
3274       distortion;
3275
3276     ExceptionInfo
3277       *exception;
3278
3279     HV
3280       *hv;
3281
3282     Image
3283       *difference_image,
3284       *image,
3285       *reconstruct_image;
3286
3287     MetricType
3288       metric;
3289
3290     register ssize_t
3291       i;
3292
3293     ssize_t
3294       option;
3295
3296     struct PackageInfo
3297       *info;
3298
3299     SV
3300       *av_reference,
3301       *perl_exception,
3302       *reference,
3303       *rv,
3304       *sv;
3305
3306     PERL_UNUSED_VAR(ref);
3307     PERL_UNUSED_VAR(ix);
3308     exception=AcquireExceptionInfo();
3309     perl_exception=newSVpv("",0);
3310     sv=NULL;
3311     av=NULL;
3312     attribute=NULL;
3313     if (sv_isobject(ST(0)) == 0)
3314       {
3315         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3316           PackageName);
3317         goto PerlException;
3318       }
3319     reference=SvRV(ST(0));
3320     hv=SvSTASH(reference);
3321     av=newAV();
3322     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3323     SvREFCNT_dec(av);
3324     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3325     if (image == (Image *) NULL)
3326       {
3327         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3328           PackageName);
3329         goto PerlException;
3330       }
3331     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3332     /*
3333       Get attribute.
3334     */
3335     reconstruct_image=image;
3336     metric=RootMeanSquaredErrorMetric;
3337     for (i=2; i < items; i+=2)
3338     {
3339       attribute=(char *) SvPV(ST(i-1),na);
3340       switch (*attribute)
3341       {
3342         case 'C':
3343         case 'c':
3344         {
3345           if (LocaleCompare(attribute,"channel") == 0)
3346             {
3347               ssize_t
3348                 option;
3349
3350               option=ParseChannelOption(SvPV(ST(i),na));
3351               if (option < 0)
3352                 {
3353                   ThrowPerlException(exception,OptionError,
3354                     "UnrecognizedType",SvPV(ST(i),na));
3355                   return;
3356                 }
3357               (void) SetPixelChannelMask(image,(ChannelType) option);
3358               break;
3359             }
3360           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3361             attribute);
3362           break;
3363         }
3364         case 'F':
3365         case 'f':
3366         {
3367           if (LocaleCompare(attribute,"fuzz") == 0)
3368             {
3369               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3370               break;
3371             }
3372           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3373             attribute);
3374           break;
3375         }
3376         case 'I':
3377         case 'i':
3378         {
3379           if (LocaleCompare(attribute,"image") == 0)
3380             {
3381               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3382                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3383               break;
3384             }
3385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386             attribute);
3387           break;
3388         }
3389         case 'M':
3390         case 'm':
3391         {
3392           if (LocaleCompare(attribute,"metric") == 0)
3393             {
3394               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3395                 SvPV(ST(i),na));
3396               if (option < 0)
3397                 {
3398                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3399                     SvPV(ST(i),na));
3400                   break;
3401                 }
3402               metric=(MetricType) option;
3403               break;
3404             }
3405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3406             attribute);
3407           break;
3408         }
3409         default:
3410         {
3411           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3412             attribute);
3413           break;
3414         }
3415       }
3416     }
3417     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3418       exception);
3419     if (difference_image != (Image *) NULL)
3420       {
3421         difference_image->error.mean_error_per_pixel=distortion;
3422         AddImageToRegistry(sv,difference_image);
3423         rv=newRV(sv);
3424         av_push(av,sv_bless(rv,hv));
3425         SvREFCNT_dec(sv);
3426       }
3427     exception=DestroyExceptionInfo(exception);
3428     ST(0)=av_reference;
3429     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3430     XSRETURN(1);
3431
3432   PerlException:
3433     InheritPerlException(exception,perl_exception);
3434     exception=DestroyExceptionInfo(exception);
3435     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3436     SvPOK_on(perl_exception);
3437     ST(0)=sv_2mortal(perl_exception);
3438     XSRETURN(1);
3439   }
3440 \f
3441 #
3442 ###############################################################################
3443 #                                                                             #
3444 #                                                                             #
3445 #                                                                             #
3446 #   C o m p l e x I m a g e s                                                 #
3447 #                                                                             #
3448 #                                                                             #
3449 #                                                                             #
3450 ###############################################################################
3451 #
3452 #
3453 void
3454 ComplexImages(ref)
3455   Image::Magick ref=NO_INIT
3456   ALIAS:
3457     ComplexImages   = 1
3458     compleximages   = 2
3459   PPCODE:
3460   {
3461     AV
3462       *av;
3463
3464     char
3465       *attribute,
3466       *p;
3467
3468     ComplexOperator
3469       op;
3470
3471     ExceptionInfo
3472       *exception;
3473
3474     HV
3475       *hv;
3476
3477     Image
3478       *image;
3479
3480     register ssize_t
3481       i;
3482
3483     struct PackageInfo
3484       *info;
3485
3486     SV
3487       *perl_exception,
3488       *reference,
3489       *rv,
3490       *sv;
3491
3492     PERL_UNUSED_VAR(ref);
3493     PERL_UNUSED_VAR(ix);
3494     exception=AcquireExceptionInfo();
3495     perl_exception=newSVpv("",0);
3496     sv=NULL;
3497     if (sv_isobject(ST(0)) == 0)
3498       {
3499         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3500           PackageName);
3501         goto PerlException;
3502       }
3503     reference=SvRV(ST(0));
3504     hv=SvSTASH(reference);
3505     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3506     if (image == (Image *) NULL)
3507       {
3508         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3509           PackageName);
3510         goto PerlException;
3511       }
3512     op=UndefinedComplexOperator;
3513     if (items == 2)
3514       {
3515         ssize_t
3516           in;
3517
3518         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3519           SvPV(ST(1),na));
3520         if (in < 0)
3521           {
3522             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3523               SvPV(ST(1),na));
3524             return;
3525           }
3526         op=(ComplexOperator) in;
3527       }
3528     else
3529       for (i=2; i < items; i+=2)
3530       {
3531         attribute=(char *) SvPV(ST(i-1),na);
3532         switch (*attribute)
3533         {
3534           case 'O':
3535           case 'o':
3536           {
3537             if (LocaleCompare(attribute,"operator") == 0)
3538               {
3539                 ssize_t
3540                   in;
3541
3542                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3543                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3544                 if (in < 0)
3545                   {
3546                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3547                       SvPV(ST(i),na));
3548                     return;
3549                   }
3550                 op=(ComplexOperator) in;
3551                 break;
3552               }
3553             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3554               attribute);
3555             break;
3556           }
3557           default:
3558           {
3559             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3560               attribute);
3561             break;
3562           }
3563         }
3564       }
3565     image=ComplexImages(image,op,exception);
3566     if (image == (Image *) NULL)
3567       goto PerlException;
3568     /*
3569       Create blessed Perl array for the returned image.
3570     */
3571     av=newAV();
3572     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3573     SvREFCNT_dec(av);
3574     AddImageToRegistry(sv,image);
3575     rv=newRV(sv);
3576     av_push(av,sv_bless(rv,hv));
3577     SvREFCNT_dec(sv);
3578     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3579     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3580       "complex-%.*s",(int) (MagickPathExtent-9),
3581       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3582     (void) CopyMagickString(image->filename,info->image_info->filename,
3583       MagickPathExtent);
3584     SetImageInfo(info->image_info,0,exception);
3585     exception=DestroyExceptionInfo(exception);
3586     SvREFCNT_dec(perl_exception);
3587     XSRETURN(1);
3588
3589   PerlException:
3590     InheritPerlException(exception,perl_exception);
3591     exception=DestroyExceptionInfo(exception);
3592     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3593     SvPOK_on(perl_exception);
3594     ST(0)=sv_2mortal(perl_exception);
3595     XSRETURN(1);
3596   }
3597 \f
3598 #
3599 ###############################################################################
3600 #                                                                             #
3601 #                                                                             #
3602 #                                                                             #
3603 #   C o m p a r e L a y e r s                                                 #
3604 #                                                                             #
3605 #                                                                             #
3606 #                                                                             #
3607 ###############################################################################
3608 #
3609 #
3610 void
3611 CompareLayers(ref)
3612   Image::Magick ref=NO_INIT
3613   ALIAS:
3614     CompareImagesLayers   = 1
3615     comparelayers        = 2
3616     compareimagelayers   = 3
3617   PPCODE:
3618   {
3619     AV
3620       *av;
3621
3622     char
3623       *attribute;
3624
3625     ExceptionInfo
3626       *exception;
3627
3628     HV
3629       *hv;
3630
3631     Image
3632       *image;
3633
3634     LayerMethod
3635       method;
3636
3637     register ssize_t
3638       i;
3639
3640     ssize_t
3641       option;
3642
3643     struct PackageInfo
3644       *info;
3645
3646     SV
3647       *av_reference,
3648       *perl_exception,
3649       *reference,
3650       *rv,
3651       *sv;
3652
3653     PERL_UNUSED_VAR(ref);
3654     PERL_UNUSED_VAR(ix);
3655     exception=AcquireExceptionInfo();
3656     perl_exception=newSVpv("",0);
3657     sv=NULL;
3658     if (sv_isobject(ST(0)) == 0)
3659       {
3660         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3661           PackageName);
3662         goto PerlException;
3663       }
3664     reference=SvRV(ST(0));
3665     hv=SvSTASH(reference);
3666     av=newAV();
3667     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3668     SvREFCNT_dec(av);
3669     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3670     if (image == (Image *) NULL)
3671       {
3672         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3673           PackageName);
3674         goto PerlException;
3675       }
3676     method=CompareAnyLayer;
3677     for (i=2; i < items; i+=2)
3678     {
3679       attribute=(char *) SvPV(ST(i-1),na);
3680       switch (*attribute)
3681       {
3682         case 'M':
3683         case 'm':
3684         {
3685           if (LocaleCompare(attribute,"method") == 0)
3686             {
3687               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3688                 SvPV(ST(i),na));
3689               if (option < 0)
3690                 {
3691                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3692                     SvPV(ST(i),na));
3693                   break;
3694                 }
3695                method=(LayerMethod) option;
3696               break;
3697             }
3698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3699             attribute);
3700           break;
3701         }
3702         default:
3703         {
3704           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3705             attribute);
3706           break;
3707         }
3708       }
3709     }
3710     image=CompareImagesLayers(image,method,exception);
3711     if (image == (Image *) NULL)
3712       goto PerlException;
3713     for ( ; image; image=image->next)
3714     {
3715       AddImageToRegistry(sv,image);
3716       rv=newRV(sv);
3717       av_push(av,sv_bless(rv,hv));
3718       SvREFCNT_dec(sv);
3719     }
3720     exception=DestroyExceptionInfo(exception);
3721     ST(0)=av_reference;
3722     SvREFCNT_dec(perl_exception);
3723     XSRETURN(1);
3724
3725   PerlException:
3726     InheritPerlException(exception,perl_exception);
3727     exception=DestroyExceptionInfo(exception);
3728     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3729     SvPOK_on(perl_exception);
3730     ST(0)=sv_2mortal(perl_exception);
3731     XSRETURN(1);
3732   }
3733 \f
3734 #
3735 ###############################################################################
3736 #                                                                             #
3737 #                                                                             #
3738 #                                                                             #
3739 #   D e s t r o y                                                             #
3740 #                                                                             #
3741 #                                                                             #
3742 #                                                                             #
3743 ###############################################################################
3744 #
3745 #
3746 void
3747 DESTROY(ref)
3748   Image::Magick ref=NO_INIT
3749   PPCODE:
3750   {
3751     SV
3752       *reference;
3753
3754     PERL_UNUSED_VAR(ref);
3755     if (sv_isobject(ST(0)) == 0)
3756       croak("ReferenceIsNotMyType");
3757     reference=SvRV(ST(0));
3758     switch (SvTYPE(reference))
3759     {
3760       case SVt_PVAV:
3761       {
3762         char
3763           message[MagickPathExtent];
3764
3765         const SV
3766           *key;
3767
3768         HV
3769           *hv;
3770
3771         GV
3772           **gvp;
3773
3774         struct PackageInfo
3775           *info;
3776
3777         SV
3778           *sv;
3779
3780         /*
3781           Array (AV *) reference
3782         */
3783         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3784           XS_VERSION,reference);
3785         hv=gv_stashpv(PackageName, FALSE);
3786         if (!hv)
3787           break;
3788         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3789         if (!gvp)
3790           break;
3791         sv=GvSV(*gvp);
3792         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3793           {
3794             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3795             DestroyPackageInfo(info);
3796           }
3797         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3798         (void) key;
3799         break;
3800       }
3801       case SVt_PVMG:
3802       {
3803         Image
3804           *image;
3805
3806         /*
3807           Blessed scalar = (Image *) SvIV(reference)
3808         */
3809         image=INT2PTR(Image *,SvIV(reference));
3810         if (image != (Image *) NULL)
3811           DeleteImageFromRegistry(reference,image);
3812         break;
3813       }
3814       default:
3815         break;
3816     }
3817   }
3818 \f
3819 #
3820 ###############################################################################
3821 #                                                                             #
3822 #                                                                             #
3823 #                                                                             #
3824 #   D i s p l a y                                                             #
3825 #                                                                             #
3826 #                                                                             #
3827 #                                                                             #
3828 ###############################################################################
3829 #
3830 #
3831 void
3832 Display(ref,...)
3833   Image::Magick ref=NO_INIT
3834   ALIAS:
3835     DisplayImage  = 1
3836     display       = 2
3837     displayimage  = 3
3838   PPCODE:
3839   {
3840     ExceptionInfo
3841       *exception;
3842
3843     Image
3844       *image;
3845
3846     register ssize_t
3847       i;
3848
3849     struct PackageInfo
3850       *info,
3851       *package_info;
3852
3853     SV
3854       *perl_exception,
3855       *reference;
3856
3857     PERL_UNUSED_VAR(ref);
3858     PERL_UNUSED_VAR(ix);
3859     exception=AcquireExceptionInfo();
3860     perl_exception=newSVpv("",0);
3861     package_info=(struct PackageInfo *) NULL;
3862     if (sv_isobject(ST(0)) == 0)
3863       {
3864         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3865           PackageName);
3866         goto PerlException;
3867       }
3868     reference=SvRV(ST(0));
3869     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3870     if (image == (Image *) NULL)
3871       {
3872         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3873           PackageName);
3874         goto PerlException;
3875       }
3876     package_info=ClonePackageInfo(info,exception);
3877     if (items == 2)
3878       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3879     else
3880       if (items > 2)
3881         for (i=2; i < items; i+=2)
3882           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3883             exception);
3884     (void) DisplayImages(package_info->image_info,image,exception);
3885     (void) CatchImageException(image);
3886
3887   PerlException:
3888     if (package_info != (struct PackageInfo *) NULL)
3889       DestroyPackageInfo(package_info);
3890     InheritPerlException(exception,perl_exception);
3891     exception=DestroyExceptionInfo(exception);
3892     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3893     SvPOK_on(perl_exception);
3894     ST(0)=sv_2mortal(perl_exception);
3895     XSRETURN(1);
3896   }
3897 \f
3898 #
3899 ###############################################################################
3900 #                                                                             #
3901 #                                                                             #
3902 #                                                                             #
3903 #   E v a l u a t e I m a g e s                                               #
3904 #                                                                             #
3905 #                                                                             #
3906 #                                                                             #
3907 ###############################################################################
3908 #
3909 #
3910 void
3911 EvaluateImages(ref)
3912   Image::Magick ref=NO_INIT
3913   ALIAS:
3914     EvaluateImages   = 1
3915     evaluateimages   = 2
3916   PPCODE:
3917   {
3918     AV
3919       *av;
3920
3921     char
3922       *attribute,
3923       *p;
3924
3925     ExceptionInfo
3926       *exception;
3927
3928     HV
3929       *hv;
3930
3931     Image
3932       *image;
3933
3934     MagickEvaluateOperator
3935       op;
3936
3937     register ssize_t
3938       i;
3939
3940     struct PackageInfo
3941       *info;
3942
3943     SV
3944       *perl_exception,
3945       *reference,
3946       *rv,
3947       *sv;
3948
3949     PERL_UNUSED_VAR(ref);
3950     PERL_UNUSED_VAR(ix);
3951     exception=AcquireExceptionInfo();
3952     perl_exception=newSVpv("",0);
3953     sv=NULL;
3954     if (sv_isobject(ST(0)) == 0)
3955       {
3956         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3957           PackageName);
3958         goto PerlException;
3959       }
3960     reference=SvRV(ST(0));
3961     hv=SvSTASH(reference);
3962     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3963     if (image == (Image *) NULL)
3964       {
3965         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3966           PackageName);
3967         goto PerlException;
3968       }
3969     op=MeanEvaluateOperator;
3970     if (items == 2)
3971       {
3972         ssize_t
3973           in;
3974
3975         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3976           SvPV(ST(1),na));
3977         if (in < 0)
3978           {
3979             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3980               SvPV(ST(1),na));
3981             return;
3982           }
3983         op=(MagickEvaluateOperator) in;
3984       }
3985     else
3986       for (i=2; i < items; i+=2)
3987       {
3988         attribute=(char *) SvPV(ST(i-1),na);
3989         switch (*attribute)
3990         {
3991           case 'O':
3992           case 'o':
3993           {
3994             if (LocaleCompare(attribute,"operator") == 0)
3995               {
3996                 ssize_t
3997                   in;
3998
3999                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4000                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4001                 if (in < 0)
4002                   {
4003                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4004                       SvPV(ST(i),na));
4005                     return;
4006                   }
4007                 op=(MagickEvaluateOperator) in;
4008                 break;
4009               }
4010             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4011               attribute);
4012             break;
4013           }
4014           default:
4015           {
4016             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4017               attribute);
4018             break;
4019           }
4020         }
4021       }
4022     image=EvaluateImages(image,op,exception);
4023     if (image == (Image *) NULL)
4024       goto PerlException;
4025     /*
4026       Create blessed Perl array for the returned image.
4027     */
4028     av=newAV();
4029     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4030     SvREFCNT_dec(av);
4031     AddImageToRegistry(sv,image);
4032     rv=newRV(sv);
4033     av_push(av,sv_bless(rv,hv));
4034     SvREFCNT_dec(sv);
4035     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4036     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4037       "evaluate-%.*s",(int) (MagickPathExtent-9),
4038       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4039     (void) CopyMagickString(image->filename,info->image_info->filename,
4040       MagickPathExtent);
4041     SetImageInfo(info->image_info,0,exception);
4042     exception=DestroyExceptionInfo(exception);
4043     SvREFCNT_dec(perl_exception);
4044     XSRETURN(1);
4045
4046   PerlException:
4047     InheritPerlException(exception,perl_exception);
4048     exception=DestroyExceptionInfo(exception);
4049     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4050     SvPOK_on(perl_exception);
4051     ST(0)=sv_2mortal(perl_exception);
4052     XSRETURN(1);
4053   }
4054 \f
4055 #
4056 ###############################################################################
4057 #                                                                             #
4058 #                                                                             #
4059 #                                                                             #
4060 #   F e a t u r e s                                                           #
4061 #                                                                             #
4062 #                                                                             #
4063 #                                                                             #
4064 ###############################################################################
4065 #
4066 #
4067 void
4068 Features(ref,...)
4069   Image::Magick ref=NO_INIT
4070   ALIAS:
4071     FeaturesImage = 1
4072     features      = 2
4073     featuresimage = 3
4074   PPCODE:
4075   {
4076 #define ChannelFeatures(channel,direction) \
4077 { \
4078   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4079     channel_features[channel].angular_second_moment[direction]); \
4080   PUSHs(sv_2mortal(newSVpv(message,0))); \
4081   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4082     channel_features[channel].contrast[direction]); \
4083   PUSHs(sv_2mortal(newSVpv(message,0))); \
4084   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4085     channel_features[channel].contrast[direction]); \
4086   PUSHs(sv_2mortal(newSVpv(message,0))); \
4087   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4088     channel_features[channel].variance_sum_of_squares[direction]); \
4089   PUSHs(sv_2mortal(newSVpv(message,0))); \
4090   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4091     channel_features[channel].inverse_difference_moment[direction]); \
4092   PUSHs(sv_2mortal(newSVpv(message,0))); \
4093   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4094     channel_features[channel].sum_average[direction]); \
4095   PUSHs(sv_2mortal(newSVpv(message,0))); \
4096   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4097     channel_features[channel].sum_variance[direction]); \
4098   PUSHs(sv_2mortal(newSVpv(message,0))); \
4099   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4100     channel_features[channel].sum_entropy[direction]); \
4101   PUSHs(sv_2mortal(newSVpv(message,0))); \
4102   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4103     channel_features[channel].entropy[direction]); \
4104   PUSHs(sv_2mortal(newSVpv(message,0))); \
4105   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4106     channel_features[channel].difference_variance[direction]); \
4107   PUSHs(sv_2mortal(newSVpv(message,0))); \
4108   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4109     channel_features[channel].difference_entropy[direction]); \
4110   PUSHs(sv_2mortal(newSVpv(message,0))); \
4111   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4112     channel_features[channel].measure_of_correlation_1[direction]); \
4113   PUSHs(sv_2mortal(newSVpv(message,0))); \
4114   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4115     channel_features[channel].measure_of_correlation_2[direction]); \
4116   PUSHs(sv_2mortal(newSVpv(message,0))); \
4117   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
4118     channel_features[channel].maximum_correlation_coefficient[direction]); \
4119   PUSHs(sv_2mortal(newSVpv(message,0))); \
4120 }
4121
4122     AV
4123       *av;
4124
4125     char
4126       *attribute,
4127       message[MagickPathExtent];
4128
4129     ChannelFeatures
4130       *channel_features;
4131
4132     double
4133       distance;
4134
4135     ExceptionInfo
4136       *exception;
4137
4138     Image
4139       *image;
4140
4141     register ssize_t
4142       i;
4143
4144     ssize_t
4145       count;
4146
4147     struct PackageInfo
4148       *info;
4149
4150     SV
4151       *perl_exception,
4152       *reference;
4153
4154     PERL_UNUSED_VAR(ref);
4155     PERL_UNUSED_VAR(ix);
4156     exception=AcquireExceptionInfo();
4157     perl_exception=newSVpv("",0);
4158     av=NULL;
4159     if (sv_isobject(ST(0)) == 0)
4160       {
4161         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4162           PackageName);
4163         goto PerlException;
4164       }
4165     reference=SvRV(ST(0));
4166     av=newAV();
4167     SvREFCNT_dec(av);
4168     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4169     if (image == (Image *) NULL)
4170       {
4171         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4172           PackageName);
4173         goto PerlException;
4174       }
4175     distance=1.0;
4176     for (i=2; i < items; i+=2)
4177     {
4178       attribute=(char *) SvPV(ST(i-1),na);
4179       switch (*attribute)
4180       {
4181         case 'D':
4182         case 'd':
4183         {
4184           if (LocaleCompare(attribute,"distance") == 0)
4185             {
4186               distance=StringToLong((char *) SvPV(ST(1),na));
4187               break;
4188             }
4189           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4190             attribute);
4191           break;
4192         }
4193         default:
4194         {
4195           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4196             attribute);
4197           break;
4198         }
4199       }
4200     }
4201     count=0;
4202     for ( ; image; image=image->next)
4203     {
4204       register ssize_t
4205         j;
4206
4207       channel_features=GetImageFeatures(image,distance,exception);
4208       if (channel_features == (ChannelFeatures *) NULL)
4209         continue;
4210       count++;
4211       for (j=0; j < 4; j++)
4212       {
4213         for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
4214         {
4215           PixelChannel channel=GetPixelChannelChannel(image,i);
4216           PixelTrait traits=GetPixelChannelTraits(image,channel);
4217           if (traits == UndefinedPixelTrait)
4218             continue;
4219           EXTEND(sp,14*(i+1)*count);
4220           ChannelFeatures(channel,j);
4221         }
4222       }
4223       channel_features=(ChannelFeatures *)
4224         RelinquishMagickMemory(channel_features);
4225     }
4226
4227   PerlException:
4228     InheritPerlException(exception,perl_exception);
4229     exception=DestroyExceptionInfo(exception);
4230     SvREFCNT_dec(perl_exception);
4231   }
4232 \f
4233 #
4234 ###############################################################################
4235 #                                                                             #
4236 #                                                                             #
4237 #                                                                             #
4238 #   F l a t t e n                                                             #
4239 #                                                                             #
4240 #                                                                             #
4241 #                                                                             #
4242 ###############################################################################
4243 #
4244 #
4245 void
4246 Flatten(ref)
4247   Image::Magick ref=NO_INIT
4248   ALIAS:
4249     FlattenImage   = 1
4250     flatten        = 2
4251     flattenimage   = 3
4252   PPCODE:
4253   {
4254     AV
4255       *av;
4256
4257     char
4258       *attribute,
4259       *p;
4260
4261     ExceptionInfo
4262       *exception;
4263
4264     HV
4265       *hv;
4266
4267     Image
4268       *image;
4269
4270     PixelInfo
4271       background_color;
4272
4273     register ssize_t
4274       i;
4275
4276     struct PackageInfo
4277       *info;
4278
4279     SV
4280       *perl_exception,
4281       *reference,
4282       *rv,
4283       *sv;
4284
4285     PERL_UNUSED_VAR(ref);
4286     PERL_UNUSED_VAR(ix);
4287     exception=AcquireExceptionInfo();
4288     perl_exception=newSVpv("",0);
4289     sv=NULL;
4290     if (sv_isobject(ST(0)) == 0)
4291       {
4292         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4293           PackageName);
4294         goto PerlException;
4295       }
4296     reference=SvRV(ST(0));
4297     hv=SvSTASH(reference);
4298     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4299     if (image == (Image *) NULL)
4300       {
4301         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4302           PackageName);
4303         goto PerlException;
4304       }
4305     background_color=image->background_color;
4306     if (items == 2)
4307       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4308         &background_color,exception);
4309     else
4310       for (i=2; i < items; i+=2)
4311       {
4312         attribute=(char *) SvPV(ST(i-1),na);
4313         switch (*attribute)
4314         {
4315           case 'B':
4316           case 'b':
4317           {
4318             if (LocaleCompare(attribute,"background") == 0)
4319               {
4320                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4321                   AllCompliance,&background_color,exception);
4322                 break;
4323               }
4324             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4325               attribute);
4326             break;
4327           }
4328           default:
4329           {
4330             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4331               attribute);
4332             break;
4333           }
4334         }
4335       }
4336     image->background_color=background_color;
4337     image=MergeImageLayers(image,FlattenLayer,exception);
4338     if (image == (Image *) NULL)
4339       goto PerlException;
4340     /*
4341       Create blessed Perl array for the returned image.
4342     */
4343     av=newAV();
4344     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4345     SvREFCNT_dec(av);
4346     AddImageToRegistry(sv,image);
4347     rv=newRV(sv);
4348     av_push(av,sv_bless(rv,hv));
4349     SvREFCNT_dec(sv);
4350     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4351     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4352       "flatten-%.*s",(int) (MagickPathExtent-9),
4353       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4354     (void) CopyMagickString(image->filename,info->image_info->filename,
4355       MagickPathExtent);
4356     SetImageInfo(info->image_info,0,exception);
4357     exception=DestroyExceptionInfo(exception);
4358     SvREFCNT_dec(perl_exception);
4359     XSRETURN(1);
4360
4361   PerlException:
4362     InheritPerlException(exception,perl_exception);
4363     exception=DestroyExceptionInfo(exception);
4364     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4365     SvPOK_on(perl_exception);  /* return messages in string context */
4366     ST(0)=sv_2mortal(perl_exception);
4367     XSRETURN(1);
4368   }
4369 \f
4370 #
4371 ###############################################################################
4372 #                                                                             #
4373 #                                                                             #
4374 #                                                                             #
4375 #   F x                                                                       #
4376 #                                                                             #
4377 #                                                                             #
4378 #                                                                             #
4379 ###############################################################################
4380 #
4381 #
4382 void
4383 Fx(ref,...)
4384   Image::Magick ref=NO_INIT
4385   ALIAS:
4386     FxImage  = 1
4387     fx       = 2
4388     fximage  = 3
4389   PPCODE:
4390   {
4391     AV
4392       *av;
4393
4394     char
4395       *attribute,
4396       expression[MagickPathExtent];
4397
4398     ChannelType
4399       channel,
4400       channel_mask;
4401
4402     ExceptionInfo
4403       *exception;
4404
4405     HV
4406       *hv;
4407
4408     Image
4409       *image;
4410
4411     register ssize_t
4412       i;
4413
4414     struct PackageInfo
4415       *info;
4416
4417     SV
4418       *av_reference,
4419       *perl_exception,
4420       *reference,
4421       *rv,
4422       *sv;
4423
4424     PERL_UNUSED_VAR(ref);
4425     PERL_UNUSED_VAR(ix);
4426     exception=AcquireExceptionInfo();
4427     perl_exception=newSVpv("",0);
4428     sv=NULL;
4429     attribute=NULL;
4430     av=NULL;
4431     if (sv_isobject(ST(0)) == 0)
4432       {
4433         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4434           PackageName);
4435         goto PerlException;
4436       }
4437     reference=SvRV(ST(0));
4438     hv=SvSTASH(reference);
4439     av=newAV();
4440     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4441     SvREFCNT_dec(av);
4442     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4443     if (image == (Image *) NULL)
4444       {
4445         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4446           PackageName);
4447         goto PerlException;
4448       }
4449     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4450     /*
4451       Get options.
4452     */
4453     channel=DefaultChannels;
4454     (void) CopyMagickString(expression,"u",MagickPathExtent);
4455     if (items == 2)
4456       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4457     else
4458       for (i=2; i < items; i+=2)
4459       {
4460         attribute=(char *) SvPV(ST(i-1),na);
4461         switch (*attribute)
4462         {
4463           case 'C':
4464           case 'c':
4465           {
4466             if (LocaleCompare(attribute,"channel") == 0)
4467               {
4468                 ssize_t
4469                   option;
4470
4471                 option=ParseChannelOption(SvPV(ST(i),na));
4472                 if (option < 0)
4473                   {
4474                     ThrowPerlException(exception,OptionError,
4475                       "UnrecognizedType",SvPV(ST(i),na));
4476                     return;
4477                   }
4478                 channel=(ChannelType) option;
4479                 break;
4480               }
4481             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4482               attribute);
4483             break;
4484           }
4485           case 'E':
4486           case 'e':
4487           {
4488             if (LocaleCompare(attribute,"expression") == 0)
4489               {
4490                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4491                   MagickPathExtent);
4492                 break;
4493               }
4494             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4495               attribute);
4496             break;
4497           }
4498           default:
4499           {
4500             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4501               attribute);
4502             break;
4503           }
4504         }
4505       }
4506     channel_mask=SetImageChannelMask(image,channel);
4507     image=FxImage(image,expression,exception);
4508     if (image != (Image *) NULL)
4509       (void) SetImageChannelMask(image,channel_mask);
4510     if (image == (Image *) NULL)
4511       goto PerlException;
4512     for ( ; image; image=image->next)
4513     {
4514       AddImageToRegistry(sv,image);
4515       rv=newRV(sv);
4516       av_push(av,sv_bless(rv,hv));
4517       SvREFCNT_dec(sv);
4518     }
4519     exception=DestroyExceptionInfo(exception);
4520     ST(0)=av_reference;
4521     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4522     XSRETURN(1);
4523
4524   PerlException:
4525     InheritPerlException(exception,perl_exception);
4526     exception=DestroyExceptionInfo(exception);
4527     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4528     SvPOK_on(perl_exception);
4529     ST(0)=sv_2mortal(perl_exception);
4530     XSRETURN(1);
4531   }
4532 \f
4533 #
4534 ###############################################################################
4535 #                                                                             #
4536 #                                                                             #
4537 #                                                                             #
4538 #   G e t                                                                     #
4539 #                                                                             #
4540 #                                                                             #
4541 #                                                                             #
4542 ###############################################################################
4543 #
4544 #
4545 void
4546 Get(ref,...)
4547   Image::Magick ref=NO_INIT
4548   ALIAS:
4549     GetAttributes = 1
4550     GetAttribute  = 2
4551     get           = 3
4552     getattributes = 4
4553     getattribute  = 5
4554   PPCODE:
4555   {
4556     char
4557       *attribute,
4558       color[MagickPathExtent];
4559
4560     const char
4561       *value;
4562
4563     ExceptionInfo
4564       *exception;
4565
4566     Image
4567       *image;
4568
4569     long
4570       j;
4571
4572     register ssize_t
4573       i;
4574
4575     struct PackageInfo
4576       *info;
4577
4578     SV
4579       *perl_exception,
4580       *reference,
4581       *s;
4582
4583     PERL_UNUSED_VAR(ref);
4584     PERL_UNUSED_VAR(ix);
4585     exception=AcquireExceptionInfo();
4586     perl_exception=newSVpv("",0);
4587     if (sv_isobject(ST(0)) == 0)
4588       {
4589         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4590           PackageName);
4591         XSRETURN_EMPTY;
4592       }
4593     reference=SvRV(ST(0));
4594     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4595     if (image == (Image *) NULL && !info)
4596       XSRETURN_EMPTY;
4597     EXTEND(sp,items);
4598     for (i=1; i < items; i++)
4599     {
4600       attribute=(char *) SvPV(ST(i),na);
4601       s=NULL;
4602       switch (*attribute)
4603       {
4604         case 'A':
4605         case 'a':
4606         {
4607           if (LocaleCompare(attribute,"adjoin") == 0)
4608             {
4609               if (info)
4610                 s=newSViv((ssize_t) info->image_info->adjoin);
4611               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4612               continue;
4613             }
4614           if (LocaleCompare(attribute,"antialias") == 0)
4615             {
4616               if (info)
4617                 s=newSViv((ssize_t) info->image_info->antialias);
4618               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4619               continue;
4620             }
4621           if (LocaleCompare(attribute,"area") == 0)
4622             {
4623               s=newSViv(GetMagickResource(AreaResource));
4624               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4625               continue;
4626             }
4627           if (LocaleCompare(attribute,"attenuate") == 0)
4628             {
4629               const char
4630                 *value;
4631
4632               value=GetImageProperty(image,attribute,exception);
4633               if (value != (const char *) NULL)
4634                 s=newSVpv(value,0);
4635               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4636               continue;
4637             }
4638           if (LocaleCompare(attribute,"authenticate") == 0)
4639             {
4640               if (info)
4641                 {
4642                   const char
4643                     *option;
4644
4645                   option=GetImageOption(info->image_info,attribute);
4646                   if (option != (const char *) NULL)
4647                     s=newSVpv(option,0);
4648                 }
4649               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4650               continue;
4651             }
4652           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4653             attribute);
4654           break;
4655         }
4656         case 'B':
4657         case 'b':
4658         {
4659           if (LocaleCompare(attribute,"background") == 0)
4660             {
4661               if (image == (Image *) NULL)
4662                 break;
4663               (void) FormatLocaleString(color,MagickPathExtent,
4664                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4665                 (double) image->background_color.green,
4666                 (double) image->background_color.blue,
4667                 (double) image->background_color.alpha);
4668               s=newSVpv(color,0);
4669               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4670               continue;
4671             }
4672           if (LocaleCompare(attribute,"base-columns") == 0)
4673             {
4674               if (image != (Image *) NULL)
4675                 s=newSViv((ssize_t) image->magick_columns);
4676               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4677               continue;
4678             }
4679           if (LocaleCompare(attribute,"base-filename") == 0)
4680             {
4681               if (image != (Image *) NULL)
4682                 s=newSVpv(image->magick_filename,0);
4683               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4684               continue;
4685             }
4686           if (LocaleCompare(attribute,"base-height") == 0)
4687             {
4688               if (image != (Image *) NULL)
4689                 s=newSViv((ssize_t) image->magick_rows);
4690               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4691               continue;
4692             }
4693           if (LocaleCompare(attribute,"base-rows") == 0)
4694             {
4695               if (image != (Image *) NULL)
4696                 s=newSViv((ssize_t) image->magick_rows);
4697               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4698               continue;
4699             }
4700           if (LocaleCompare(attribute,"base-width") == 0)
4701             {
4702               if (image != (Image *) NULL)
4703                 s=newSViv((ssize_t) image->magick_columns);
4704               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4705               continue;
4706             }
4707           if (LocaleCompare(attribute,"blue-primary") == 0)
4708             {
4709               if (image == (Image *) NULL)
4710                 break;
4711               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
4712                 image->chromaticity.blue_primary.x,
4713                 image->chromaticity.blue_primary.y);
4714               s=newSVpv(color,0);
4715               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4716               continue;
4717             }
4718           if (LocaleCompare(attribute,"bordercolor") == 0)
4719             {
4720               if (image == (Image *) NULL)
4721                 break;
4722               (void) FormatLocaleString(color,MagickPathExtent,
4723                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4724                 (double) image->border_color.green,
4725                 (double) image->border_color.blue,
4726                 (double) image->border_color.alpha);
4727               s=newSVpv(color,0);
4728               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4729               continue;
4730             }
4731           if (LocaleCompare(attribute,"bounding-box") == 0)
4732             {
4733               char
4734                 geometry[MagickPathExtent];
4735
4736               RectangleInfo
4737                 page;
4738
4739               if (image == (Image *) NULL)
4740                 break;
4741               page=GetImageBoundingBox(image,exception);
4742               (void) FormatLocaleString(geometry,MagickPathExtent,
4743                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4744                 page.height,(double) page.x,(double) page.y);
4745               s=newSVpv(geometry,0);
4746               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4747               continue;
4748             }
4749           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4750             attribute);
4751           break;
4752         }
4753         case 'C':
4754         case 'c':
4755         {
4756           if (LocaleCompare(attribute,"class") == 0)
4757             {
4758               if (image == (Image *) NULL)
4759                 break;
4760               s=newSViv(image->storage_class);
4761               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4762                 image->storage_class));
4763               SvIOK_on(s);
4764               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4765               continue;
4766             }
4767           if (LocaleCompare(attribute,"clip-mask") == 0)
4768             {
4769               if (image != (Image *) NULL)
4770                 {
4771                   Image
4772                     *mask_image;
4773
4774                   SV
4775                     *sv;
4776
4777                   sv=NULL;
4778                   if (image->read_mask == MagickFalse)
4779                     ClipImage(image,exception);
4780                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4781                   if (mask_image != (Image *) NULL)
4782                     {
4783                       AddImageToRegistry(sv,mask_image);
4784                       s=sv_bless(newRV(sv),SvSTASH(reference));
4785                     }
4786                 }
4787               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4788               continue;
4789             }
4790           if (LocaleCompare(attribute,"clip-path") == 0)
4791             {
4792               if (image != (Image *) NULL)
4793                 {
4794                   Image
4795                     *mask_image;
4796
4797                   SV
4798                     *sv;
4799
4800                   sv=NULL;
4801                   if (image->read_mask != MagickFalse)
4802                     ClipImage(image,exception);
4803                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4804                   if (mask_image != (Image *) NULL)
4805                     {
4806                       AddImageToRegistry(sv,mask_image);
4807                       s=sv_bless(newRV(sv),SvSTASH(reference));
4808                     }
4809                 }
4810               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4811               continue;
4812             }
4813           if (LocaleCompare(attribute,"compression") == 0)
4814             {
4815               j=info ? info->image_info->compression : image ?
4816                 image->compression : UndefinedCompression;
4817               if (info)
4818                 if (info->image_info->compression == UndefinedCompression)
4819                   j=image->compression;
4820               s=newSViv(j);
4821               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4822                 j));
4823               SvIOK_on(s);
4824               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4825               continue;
4826             }
4827           if (LocaleCompare(attribute,"colorspace") == 0)
4828             {
4829               j=image ? image->colorspace : RGBColorspace;
4830               s=newSViv(j);
4831               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4832                 j));
4833               SvIOK_on(s);
4834               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4835               continue;
4836             }
4837           if (LocaleCompare(attribute,"colors") == 0)
4838             {
4839               if (image != (Image *) NULL)
4840                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4841                   exception));
4842               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4843               continue;
4844             }
4845           if (LocaleNCompare(attribute,"colormap",8) == 0)
4846             {
4847               int
4848                 items;
4849
4850               if (image == (Image *) NULL || !image->colormap)
4851                 break;
4852               j=0;
4853               items=sscanf(attribute,"%*[^[][%ld",&j);
4854               (void) items;
4855               if (j > (ssize_t) image->colors)
4856                 j%=image->colors;
4857               (void) FormatLocaleString(color,MagickPathExtent,
4858                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4859                 (double) image->colormap[j].green,
4860                 (double) image->colormap[j].blue,
4861                 (double) image->colormap[j].alpha);
4862               s=newSVpv(color,0);
4863               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4864               continue;
4865             }
4866           if (LocaleCompare(attribute,"columns") == 0)
4867             {
4868               if (image != (Image *) NULL)
4869                 s=newSViv((ssize_t) image->columns);
4870               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4871               continue;
4872             }
4873           if (LocaleCompare(attribute,"comment") == 0)
4874             {
4875               const char
4876                 *value;
4877
4878               value=GetImageProperty(image,attribute,exception);
4879               if (value != (const char *) NULL)
4880                 s=newSVpv(value,0);
4881               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4882               continue;
4883             }
4884           if (LocaleCompare(attribute,"copyright") == 0)
4885             {
4886               s=newSVpv(GetMagickCopyright(),0);
4887               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4888               continue;
4889             }
4890           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4891             attribute);
4892           break;
4893         }
4894         case 'D':
4895         case 'd':
4896         {
4897           if (LocaleCompare(attribute,"density") == 0)
4898             {
4899               char
4900                 geometry[MagickPathExtent];
4901
4902               if (image == (Image *) NULL)
4903                 break;
4904               (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g",
4905                 image->resolution.x,image->resolution.y);
4906               s=newSVpv(geometry,0);
4907               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4908               continue;
4909             }
4910           if (LocaleCompare(attribute,"delay") == 0)
4911             {
4912               if (image != (Image *) NULL)
4913                 s=newSViv((ssize_t) image->delay);
4914               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4915               continue;
4916             }
4917           if (LocaleCompare(attribute,"depth") == 0)
4918             {
4919               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4920               if (image != (Image *) NULL)
4921                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4922               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4923               continue;
4924             }
4925           if (LocaleCompare(attribute,"directory") == 0)
4926             {
4927               if (image && image->directory)
4928                 s=newSVpv(image->directory,0);
4929               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4930               continue;
4931             }
4932           if (LocaleCompare(attribute,"dispose") == 0)
4933             {
4934               if (image == (Image *) NULL)
4935                 break;
4936
4937               s=newSViv(image->dispose);
4938               (void) sv_setpv(s,
4939                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4940               SvIOK_on(s);
4941               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4942               continue;
4943             }
4944           if (LocaleCompare(attribute,"disk") == 0)
4945             {
4946               s=newSViv(GetMagickResource(DiskResource));
4947               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4948               continue;
4949             }
4950           if (LocaleCompare(attribute,"dither") == 0)
4951             {
4952               if (info)
4953                 s=newSViv((ssize_t) info->image_info->dither);
4954               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4955               continue;
4956             }
4957           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4958             {
4959               if (info && info->image_info->server_name)
4960                 s=newSVpv(info->image_info->server_name,0);
4961               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4962               continue;
4963             }
4964           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4965             attribute);
4966           break;
4967         }
4968         case 'E':
4969         case 'e':
4970         {
4971           if (LocaleCompare(attribute,"elapsed-time") == 0)
4972             {
4973               if (image != (Image *) NULL)
4974                 s=newSVnv(GetElapsedTime(&image->timer));
4975               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4976               continue;
4977             }
4978           if (LocaleCompare(attribute,"endian") == 0)
4979             {
4980               j=info ? info->image_info->endian : image ? image->endian :
4981                 UndefinedEndian;
4982               s=newSViv(j);
4983               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4984               SvIOK_on(s);
4985               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4986               continue;
4987             }
4988           if (LocaleCompare(attribute,"error") == 0)
4989             {
4990               if (image != (Image *) NULL)
4991                 s=newSVnv(image->error.mean_error_per_pixel);
4992               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4993               continue;
4994             }
4995           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4996             attribute);
4997           break;
4998         }
4999         case 'F':
5000         case 'f':
5001         {
5002           if (LocaleCompare(attribute,"filesize") == 0)
5003             {
5004               if (image != (Image *) NULL)
5005                 s=newSViv((ssize_t) GetBlobSize(image));
5006               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5007               continue;
5008             }
5009           if (LocaleCompare(attribute,"filename") == 0)
5010             {
5011               if (info && info->image_info->filename &&
5012                   *info->image_info->filename)
5013                 s=newSVpv(info->image_info->filename,0);
5014               if (image != (Image *) NULL)
5015                 s=newSVpv(image->filename,0);
5016               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5017               continue;
5018             }
5019           if (LocaleCompare(attribute,"filter") == 0)
5020             {
5021               s=image ? newSViv(image->filter) : newSViv(0);
5022               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5023                 image->filter));
5024               SvIOK_on(s);
5025               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5026               continue;
5027             }
5028           if (LocaleCompare(attribute,"font") == 0)
5029             {
5030               if (info && info->image_info->font)
5031                 s=newSVpv(info->image_info->font,0);
5032               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5033               continue;
5034             }
5035           if (LocaleCompare(attribute,"foreground") == 0)
5036             continue;
5037           if (LocaleCompare(attribute,"format") == 0)
5038             {
5039               const MagickInfo
5040                 *magick_info;
5041
5042               magick_info=(const MagickInfo *) NULL;
5043               if (info && (*info->image_info->magick != '\0'))
5044                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5045               if (image != (Image *) NULL)
5046                 magick_info=GetMagickInfo(image->magick,exception);
5047               if ((magick_info != (const MagickInfo *) NULL) &&
5048                   (*magick_info->description != '\0'))
5049                 s=newSVpv((char *) magick_info->description,0);
5050               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5051               continue;
5052             }
5053           if (LocaleCompare(attribute,"fuzz") == 0)
5054             {
5055               if (info)
5056                 s=newSVnv(info->image_info->fuzz);
5057               if (image != (Image *) NULL)
5058                 s=newSVnv(image->fuzz);
5059               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5060               continue;
5061             }
5062           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5063             attribute);
5064           break;
5065         }
5066         case 'G':
5067         case 'g':
5068         {
5069           if (LocaleCompare(attribute,"gamma") == 0)
5070             {
5071               if (image != (Image *) NULL)
5072                 s=newSVnv(image->gamma);
5073               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5074               continue;
5075             }
5076           if (LocaleCompare(attribute,"geometry") == 0)
5077             {
5078               if (image && image->geometry)
5079                 s=newSVpv(image->geometry,0);
5080               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5081               continue;
5082             }
5083           if (LocaleCompare(attribute,"gravity") == 0)
5084             {
5085               s=image ? newSViv(image->gravity) : newSViv(0);
5086               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5087                 image->gravity));
5088               SvIOK_on(s);
5089               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5090               continue;
5091             }
5092           if (LocaleCompare(attribute,"green-primary") == 0)
5093             {
5094               if (image == (Image *) NULL)
5095                 break;
5096               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5097                 image->chromaticity.green_primary.x,
5098                 image->chromaticity.green_primary.y);
5099               s=newSVpv(color,0);
5100               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5101               continue;
5102             }
5103           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5104             attribute);
5105           break;
5106         }
5107         case 'H':
5108         case 'h':
5109         {
5110           if (LocaleCompare(attribute,"height") == 0)
5111             {
5112               if (image != (Image *) NULL)
5113                 s=newSViv((ssize_t) image->rows);
5114               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5115               continue;
5116             }
5117           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5118             attribute);
5119           break;
5120         }
5121         case 'I':
5122         case 'i':
5123         {
5124           if (LocaleCompare(attribute,"icc") == 0)
5125             {
5126               if (image != (Image *) NULL)
5127                 {
5128                   const StringInfo
5129                     *profile;
5130
5131                   profile=GetImageProfile(image,"icc");
5132                   if (profile != (StringInfo *) NULL)
5133                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5134                       GetStringInfoLength(profile));
5135                 }
5136               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5137               continue;
5138             }
5139           if (LocaleCompare(attribute,"icm") == 0)
5140             {
5141               if (image != (Image *) NULL)
5142                 {
5143                   const StringInfo
5144                     *profile;
5145
5146                   profile=GetImageProfile(image,"icm");
5147                   if (profile != (const StringInfo *) NULL)
5148                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5149                       GetStringInfoLength(profile));
5150                 }
5151               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5152               continue;
5153             }
5154           if (LocaleCompare(attribute,"id") == 0)
5155             {
5156               if (image != (Image *) NULL)
5157                 {
5158                   char
5159                     key[MagickPathExtent];
5160
5161                   MagickBooleanType
5162                     status;
5163
5164                   static ssize_t
5165                     id = 0;
5166
5167                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5168                     id);
5169                   status=SetImageRegistry(ImageRegistryType,key,image,
5170                     exception);
5171                   (void) status;
5172                   s=newSViv(id++);
5173                 }
5174               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5175               continue;
5176             }
5177           if (LocaleNCompare(attribute,"index",5) == 0)
5178             {
5179               char
5180                 name[MagickPathExtent];
5181
5182               int
5183                 items;
5184
5185               long
5186                 x,
5187                 y;
5188
5189               register const Quantum
5190                 *p;
5191
5192               CacheView
5193                 *image_view;
5194
5195               if (image == (Image *) NULL)
5196                 break;
5197               if (image->storage_class != PseudoClass)
5198                 break;
5199               x=0;
5200               y=0;
5201               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5202               (void) items;
5203               image_view=AcquireVirtualCacheView(image,exception);
5204               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5205               if (p != (const Quantum *) NULL)
5206                 {
5207                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5208                     GetPixelIndex(image,p));
5209                   s=newSVpv(name,0);
5210                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5211                 }
5212               image_view=DestroyCacheView(image_view);
5213               continue;
5214             }
5215           if (LocaleCompare(attribute,"iptc") == 0)
5216             {
5217               if (image != (Image *) NULL)
5218                 {
5219                   const StringInfo
5220                     *profile;
5221
5222                   profile=GetImageProfile(image,"iptc");
5223                   if (profile != (const StringInfo *) NULL)
5224                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5225                       GetStringInfoLength(profile));
5226                 }
5227               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5228               continue;
5229             }
5230           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5231             {
5232               if (image != (Image *) NULL)
5233                 s=newSViv((ssize_t) image->iterations);
5234               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5235               continue;
5236             }
5237           if (LocaleCompare(attribute,"interlace") == 0)
5238             {
5239               j=info ? info->image_info->interlace : image ? image->interlace :
5240                 UndefinedInterlace;
5241               s=newSViv(j);
5242               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5243                 j));
5244               SvIOK_on(s);
5245               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5246               continue;
5247             }
5248           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5249             attribute);
5250           break;
5251         }
5252         case 'L':
5253         case 'l':
5254         {
5255           if (LocaleCompare(attribute,"label") == 0)
5256             {
5257               const char
5258                 *value;
5259
5260               if (image == (Image *) NULL)
5261                 break;
5262               value=GetImageProperty(image,"Label",exception);
5263               if (value != (const char *) NULL)
5264                 s=newSVpv(value,0);
5265               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5266               continue;
5267             }
5268           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5269             {
5270               if (image != (Image *) NULL)
5271                 s=newSViv((ssize_t) image->iterations);
5272               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5273               continue;
5274             }
5275           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5276             attribute);
5277           break;
5278         }
5279         case 'M':
5280         case 'm':
5281         {
5282           if (LocaleCompare(attribute,"magick") == 0)
5283             {
5284               if (info && *info->image_info->magick)
5285                 s=newSVpv(info->image_info->magick,0);
5286               if (image != (Image *) NULL)
5287                 s=newSVpv(image->magick,0);
5288               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5289               continue;
5290             }
5291           if (LocaleCompare(attribute,"map") == 0)
5292             {
5293               s=newSViv(GetMagickResource(MapResource));
5294               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5295               continue;
5296             }
5297           if (LocaleCompare(attribute,"maximum-error") == 0)
5298             {
5299               if (image != (Image *) NULL)
5300                 s=newSVnv(image->error.normalized_maximum_error);
5301               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5302               continue;
5303             }
5304           if (LocaleCompare(attribute,"memory") == 0)
5305             {
5306               s=newSViv(GetMagickResource(MemoryResource));
5307               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5308               continue;
5309             }
5310           if (LocaleCompare(attribute,"mean-error") == 0)
5311             {
5312               if (image != (Image *) NULL)
5313                 s=newSVnv(image->error.normalized_mean_error);
5314               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5315               continue;
5316             }
5317           if (LocaleCompare(attribute,"mime") == 0)
5318             {
5319               if (info && *info->image_info->magick)
5320                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5321               if (image != (Image *) NULL)
5322                 s=newSVpv(MagickToMime(image->magick),0);
5323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324               continue;
5325             }
5326           if (LocaleCompare(attribute,"mattecolor") == 0)
5327             {
5328               if (image == (Image *) NULL)
5329                 break;
5330               (void) FormatLocaleString(color,MagickPathExtent,
5331                 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5332                 (double) image->alpha_color.green,
5333                 (double) image->alpha_color.blue,
5334                 (double) image->alpha_color.alpha);
5335               s=newSVpv(color,0);
5336               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5337               continue;
5338             }
5339           if (LocaleCompare(attribute,"matte") == 0)
5340             {
5341               if (image != (Image *) NULL)
5342                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5343                   1 : 0);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"mime") == 0)
5348             {
5349               const char
5350                 *magick;
5351
5352               magick=NULL;
5353               if (info && *info->image_info->magick)
5354                 magick=info->image_info->magick;
5355               if (image != (Image *) NULL)
5356                 magick=image->magick;
5357               if (magick)
5358                 {
5359                   char
5360                     *mime;
5361
5362                   mime=MagickToMime(magick);
5363                   s=newSVpv(mime,0);
5364                   mime=(char *) RelinquishMagickMemory(mime);
5365                 }
5366               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5367               continue;
5368             }
5369           if (LocaleCompare(attribute,"monochrome") == 0)
5370             {
5371               if (image == (Image *) NULL)
5372                 continue;
5373               j=info ? info->image_info->monochrome :
5374                 SetImageMonochrome(image,exception);
5375               s=newSViv(j);
5376               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5377               continue;
5378             }
5379           if (LocaleCompare(attribute,"montage") == 0)
5380             {
5381               if (image && image->montage)
5382                 s=newSVpv(image->montage,0);
5383               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5384               continue;
5385             }
5386           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5387             attribute);
5388           break;
5389         }
5390         case 'O':
5391         case 'o':
5392         {
5393           if (LocaleCompare(attribute,"orientation") == 0)
5394             {
5395               j=info ? info->image_info->orientation : image ?
5396                 image->orientation : UndefinedOrientation;
5397               s=newSViv(j);
5398               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5399                 j));
5400               SvIOK_on(s);
5401               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5402               continue;
5403             }
5404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5405             attribute);
5406           break;
5407         }
5408         case 'P':
5409         case 'p':
5410         {
5411           if (LocaleCompare(attribute,"page") == 0)
5412             {
5413               if (info && info->image_info->page)
5414                 s=newSVpv(info->image_info->page,0);
5415               if (image != (Image *) NULL)
5416                 {
5417                   char
5418                     geometry[MagickPathExtent];
5419
5420                   (void) FormatLocaleString(geometry,MagickPathExtent,
5421                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5422                     (double) image->page.height,(double) image->page.x,(double)
5423                     image->page.y);
5424                   s=newSVpv(geometry,0);
5425                 }
5426               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5427               continue;
5428             }
5429           if (LocaleCompare(attribute,"page.x") == 0)
5430             {
5431               if (image != (Image *) NULL)
5432                 s=newSViv((ssize_t) image->page.x);
5433               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5434               continue;
5435             }
5436           if (LocaleCompare(attribute,"page.y") == 0)
5437             {
5438               if (image != (Image *) NULL)
5439                 s=newSViv((ssize_t) image->page.y);
5440               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5441               continue;
5442             }
5443           if (LocaleNCompare(attribute,"pixel",5) == 0)
5444             {
5445               char
5446                 tuple[MagickPathExtent];
5447
5448               int
5449                 items;
5450
5451               long
5452                 x,
5453                 y;
5454
5455               register const Quantum
5456                 *p;
5457
5458               if (image == (Image *) NULL)
5459                 break;
5460               x=0;
5461               y=0;
5462               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5463               (void) items;
5464               p=GetVirtualPixels(image,x,y,1,1,exception);
5465               if (image->colorspace != CMYKColorspace)
5466                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5467                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5468                   GetPixelRed(image,p),GetPixelGreen(image,p),
5469                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5470               else
5471                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5472                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5473                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5474                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5475                   GetPixelAlpha(image,p));
5476               s=newSVpv(tuple,0);
5477               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5478               continue;
5479             }
5480           if (LocaleCompare(attribute,"pointsize") == 0)
5481             {
5482               if (info)
5483                 s=newSViv((ssize_t) info->image_info->pointsize);
5484               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5485               continue;
5486             }
5487           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5488             attribute);
5489           break;
5490         }
5491         case 'Q':
5492         case 'q':
5493         {
5494           if (LocaleCompare(attribute,"quality") == 0)
5495             {
5496               if (info)
5497                 s=newSViv((ssize_t) info->image_info->quality);
5498               if (image != (Image *) NULL)
5499                 s=newSViv((ssize_t) image->quality);
5500               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5501               continue;
5502             }
5503           if (LocaleCompare(attribute,"quantum") == 0)
5504             {
5505               if (info)
5506                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5507               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5508               continue;
5509             }
5510           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5511             attribute);
5512           break;
5513         }
5514         case 'R':
5515         case 'r':
5516         {
5517           if (LocaleCompare(attribute,"rendering-intent") == 0)
5518             {
5519               s=newSViv(image->rendering_intent);
5520               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5521                 image->rendering_intent));
5522               SvIOK_on(s);
5523               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5524               continue;
5525             }
5526           if (LocaleCompare(attribute,"red-primary") == 0)
5527             {
5528               if (image == (Image *) NULL)
5529                 break;
5530               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5531                 image->chromaticity.red_primary.x,
5532                 image->chromaticity.red_primary.y);
5533               s=newSVpv(color,0);
5534               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5535               continue;
5536             }
5537           if (LocaleCompare(attribute,"rows") == 0)
5538             {
5539               if (image != (Image *) NULL)
5540                 s=newSViv((ssize_t) image->rows);
5541               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5542               continue;
5543             }
5544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5545             attribute);
5546           break;
5547         }
5548         case 'S':
5549         case 's':
5550         {
5551           if (LocaleCompare(attribute,"sampling-factor") == 0)
5552             {
5553               if (info && info->image_info->sampling_factor)
5554                 s=newSVpv(info->image_info->sampling_factor,0);
5555               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5556               continue;
5557             }
5558           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5559             {
5560               if (info && info->image_info->server_name)
5561                 s=newSVpv(info->image_info->server_name,0);
5562               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5563               continue;
5564             }
5565           if (LocaleCompare(attribute,"size") == 0)
5566             {
5567               if (info && info->image_info->size)
5568                 s=newSVpv(info->image_info->size,0);
5569               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5570               continue;
5571             }
5572           if (LocaleCompare(attribute,"scene") == 0)
5573             {
5574               if (image != (Image *) NULL)
5575                 s=newSViv((ssize_t) image->scene);
5576               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5577               continue;
5578             }
5579           if (LocaleCompare(attribute,"scenes") == 0)
5580             {
5581               if (image != (Image *) NULL)
5582                 s=newSViv((ssize_t) info->image_info->number_scenes);
5583               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5584               continue;
5585             }
5586           if (LocaleCompare(attribute,"signature") == 0)
5587             {
5588               const char
5589                 *value;
5590
5591               if (image == (Image *) NULL)
5592                 break;
5593               (void) SignatureImage(image,exception);
5594               value=GetImageProperty(image,"Signature",exception);
5595               if (value != (const char *) NULL)
5596                 s=newSVpv(value,0);
5597               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5598               continue;
5599             }
5600           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5601             attribute);
5602           break;
5603         }
5604         case 'T':
5605         case 't':
5606         {
5607           if (LocaleCompare(attribute,"taint") == 0)
5608             {
5609               if (image != (Image *) NULL)
5610                 s=newSViv((ssize_t) IsTaintImage(image));
5611               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5612               continue;
5613             }
5614           if (LocaleCompare(attribute,"texture") == 0)
5615             {
5616               if (info && info->image_info->texture)
5617                 s=newSVpv(info->image_info->texture,0);
5618               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5619               continue;
5620             }
5621           if (LocaleCompare(attribute,"total-ink-density") == 0)
5622             {
5623               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5624               if (image != (Image *) NULL)
5625                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5626               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5627               continue;
5628             }
5629           if (LocaleCompare(attribute,"transparent-color") == 0)
5630             {
5631               if (image == (Image *) NULL)
5632                 break;
5633               (void) FormatLocaleString(color,MagickPathExtent,
5634                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5635                 (double) image->transparent_color.green,
5636                 (double) image->transparent_color.blue,
5637                 (double) image->transparent_color.alpha);
5638               s=newSVpv(color,0);
5639               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5640               continue;
5641             }
5642           if (LocaleCompare(attribute,"type") == 0)
5643             {
5644               if (image == (Image *) NULL)
5645                 break;
5646               j=(ssize_t) GetImageType(image);
5647               s=newSViv(j);
5648               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5649               SvIOK_on(s);
5650               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5651               continue;
5652             }
5653           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5654             attribute);
5655           break;
5656         }
5657         case 'U':
5658         case 'u':
5659         {
5660           if (LocaleCompare(attribute,"units") == 0)
5661             {
5662               j=info ? info->image_info->units : image ? image->units :
5663                 UndefinedResolution;
5664               if (info && (info->image_info->units == UndefinedResolution))
5665                 if (image)
5666                   j=image->units;
5667               if (j == UndefinedResolution)
5668                 s=newSVpv("undefined units",0);
5669               else
5670                 if (j == PixelsPerInchResolution)
5671                   s=newSVpv("pixels / inch",0);
5672                 else
5673                   s=newSVpv("pixels / centimeter",0);
5674               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5675               continue;
5676             }
5677           if (LocaleCompare(attribute,"user-time") == 0)
5678             {
5679               if (image != (Image *) NULL)
5680                 s=newSVnv(GetUserTime(&image->timer));
5681               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5682               continue;
5683             }
5684           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5685             attribute);
5686           break;
5687         }
5688         case 'V':
5689         case 'v':
5690         {
5691           if (LocaleCompare(attribute,"verbose") == 0)
5692             {
5693               if (info)
5694                 s=newSViv((ssize_t) info->image_info->verbose);
5695               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5696               continue;
5697             }
5698           if (LocaleCompare(attribute,"version") == 0)
5699             {
5700               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5701               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5702               continue;
5703             }
5704           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5705             {
5706               if (image == (Image *) NULL)
5707                 break;
5708               j=(ssize_t) GetImageVirtualPixelMethod(image);
5709               s=newSViv(j);
5710               (void) sv_setpv(s,CommandOptionToMnemonic(
5711                 MagickVirtualPixelOptions,j));
5712               SvIOK_on(s);
5713               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5714               continue;
5715             }
5716           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5717             attribute);
5718           break;
5719         }
5720         case 'W':
5721         case 'w':
5722         {
5723           if (LocaleCompare(attribute,"white-point") == 0)
5724             {
5725               if (image == (Image *) NULL)
5726                 break;
5727               (void) FormatLocaleString(color,MagickPathExtent,"%.20g,%.20g",
5728                 image->chromaticity.white_point.x,
5729                 image->chromaticity.white_point.y);
5730               s=newSVpv(color,0);
5731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5732               continue;
5733             }
5734           if (LocaleCompare(attribute,"width") == 0)
5735             {
5736               if (image != (Image *) NULL)
5737                 s=newSViv((ssize_t) image->columns);
5738               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5739               continue;
5740             }
5741           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5742              attribute);
5743           break;
5744         }
5745         case 'X':
5746         case 'x':
5747         {
5748           if (LocaleCompare(attribute,"xmp") == 0)
5749             {
5750               if (image != (Image *) NULL)
5751                 {
5752                   const StringInfo
5753                     *profile;
5754
5755                   profile=GetImageProfile(image,"xmp");
5756                   if (profile != (StringInfo *) NULL)
5757                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5758                       GetStringInfoLength(profile));
5759                 }
5760               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5761               continue;
5762             }
5763           if (LocaleCompare(attribute,"x-resolution") == 0)
5764             {
5765               if (image != (Image *) NULL)
5766                 s=newSVnv(image->resolution.x);
5767               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5768               continue;
5769             }
5770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5771             attribute);
5772           break;
5773         }
5774         case 'Y':
5775         case 'y':
5776         {
5777           if (LocaleCompare(attribute,"y-resolution") == 0)
5778             {
5779               if (image != (Image *) NULL)
5780                 s=newSVnv(image->resolution.y);
5781               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5782               continue;
5783             }
5784           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5785             attribute);
5786           break;
5787         }
5788         default:
5789           break;
5790       }
5791       if (image == (Image *) NULL)
5792         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5793           attribute)
5794       else
5795         {
5796           value=GetImageProperty(image,attribute,exception);
5797           if (value != (const char *) NULL)
5798             {
5799               s=newSVpv(value,0);
5800               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5801             }
5802           else
5803             if (*attribute != '%')
5804               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5805                 attribute)
5806             else
5807               {
5808                  char
5809                    *meta;
5810
5811                  meta=InterpretImageProperties(info ? info->image_info :
5812                    (ImageInfo *) NULL,image,attribute,exception);
5813                  s=newSVpv(meta,0);
5814                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5815                  meta=(char *) RelinquishMagickMemory(meta);
5816               }
5817         }
5818     }
5819     exception=DestroyExceptionInfo(exception);
5820     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5821   }
5822 \f
5823 #
5824 ###############################################################################
5825 #                                                                             #
5826 #                                                                             #
5827 #                                                                             #
5828 #   G e t A u t h e n t i c P i x e l s                                       #
5829 #                                                                             #
5830 #                                                                             #
5831 #                                                                             #
5832 ###############################################################################
5833 #
5834 #
5835 void *
5836 GetAuthenticPixels(ref,...)
5837   Image::Magick ref = NO_INIT
5838   ALIAS:
5839     getauthenticpixels = 1
5840     GetImagePixels = 2
5841     getimagepixels = 3
5842   CODE:
5843   {
5844     char
5845       *attribute;
5846
5847     ExceptionInfo
5848       *exception;
5849
5850     Image
5851       *image;
5852
5853     RectangleInfo
5854       region;
5855
5856     ssize_t
5857       i;
5858
5859     struct PackageInfo
5860       *info;
5861
5862     SV
5863       *perl_exception,
5864       *reference;
5865
5866     void
5867       *blob = NULL;
5868
5869     PERL_UNUSED_VAR(ref);
5870     PERL_UNUSED_VAR(ix);
5871     exception=AcquireExceptionInfo();
5872     perl_exception=newSVpv("",0);
5873     if (sv_isobject(ST(0)) == 0)
5874       {
5875         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5876           PackageName);
5877         goto PerlException;
5878       }
5879     reference=SvRV(ST(0));
5880
5881     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5882     if (image == (Image *) NULL)
5883       {
5884         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5885           PackageName);
5886         goto PerlException;
5887       }
5888
5889     region.x=0;
5890     region.y=0;
5891     region.width=image->columns;
5892     region.height=1;
5893     if (items == 1)
5894       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5895     for (i=2; i < items; i+=2)
5896     {
5897       attribute=(char *) SvPV(ST(i-1),na);
5898       switch (*attribute)
5899       {
5900         case 'g':
5901         case 'G':
5902         {
5903           if (LocaleCompare(attribute,"geometry") == 0)
5904             {
5905               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5906               break;
5907             }
5908           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5909             attribute);
5910           break;
5911         }
5912         case 'H':
5913         case 'h':
5914         {
5915           if (LocaleCompare(attribute,"height") == 0)
5916             {
5917               region.height=SvIV(ST(i));
5918               continue;
5919             }
5920           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5921             attribute);
5922           break;
5923         }
5924         case 'X':
5925         case 'x':
5926         {
5927           if (LocaleCompare(attribute,"x") == 0)
5928             {
5929               region.x=SvIV(ST(i));
5930               continue;
5931             }
5932           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5933             attribute);
5934           break;
5935         }
5936         case 'Y':
5937         case 'y':
5938         {
5939           if (LocaleCompare(attribute,"y") == 0)
5940             {
5941               region.y=SvIV(ST(i));
5942               continue;
5943             }
5944           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5945             attribute);
5946           break;
5947         }
5948         case 'W':
5949         case 'w':
5950         {
5951           if (LocaleCompare(attribute,"width") == 0)
5952             {
5953               region.width=SvIV(ST(i));
5954               continue;
5955             }
5956           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5957             attribute);
5958           break;
5959         }
5960       }
5961     }
5962     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5963       region.height,exception);
5964     if (blob != (void *) NULL)
5965       goto PerlEnd;
5966
5967   PerlException:
5968     InheritPerlException(exception,perl_exception);
5969     exception=DestroyExceptionInfo(exception);
5970     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5971
5972   PerlEnd:
5973     RETVAL = blob;
5974   }
5975   OUTPUT:
5976     RETVAL
5977 \f
5978 #
5979 ###############################################################################
5980 #                                                                             #
5981 #                                                                             #
5982 #                                                                             #
5983 #   G e t V i r t u a l P i x e l s                                           #
5984 #                                                                             #
5985 #                                                                             #
5986 #                                                                             #
5987 ###############################################################################
5988 #
5989 #
5990 void *
5991 GetVirtualPixels(ref,...)
5992   Image::Magick ref = NO_INIT
5993   ALIAS:
5994     getvirtualpixels = 1
5995     AcquireImagePixels = 2
5996     acquireimagepixels = 3
5997   CODE:
5998   {
5999     char
6000       *attribute;
6001
6002     const void
6003       *blob = NULL;
6004
6005     ExceptionInfo
6006       *exception;
6007
6008     Image
6009       *image;
6010
6011     RectangleInfo
6012       region;
6013
6014     ssize_t
6015       i;
6016
6017     struct PackageInfo
6018       *info;
6019
6020     SV
6021       *perl_exception,
6022       *reference;
6023
6024     PERL_UNUSED_VAR(ref);
6025     PERL_UNUSED_VAR(ix);
6026     exception=AcquireExceptionInfo();
6027     perl_exception=newSVpv("",0);
6028     if (sv_isobject(ST(0)) == 0)
6029       {
6030         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6031           PackageName);
6032         goto PerlException;
6033       }
6034     reference=SvRV(ST(0));
6035
6036     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6037     if (image == (Image *) NULL)
6038       {
6039         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6040           PackageName);
6041         goto PerlException;
6042       }
6043
6044     region.x=0;
6045     region.y=0;
6046     region.width=image->columns;
6047     region.height=1;
6048     if (items == 1)
6049       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6050     for (i=2; i < items; i+=2)
6051     {
6052       attribute=(char *) SvPV(ST(i-1),na);
6053       switch (*attribute)
6054       {
6055         case 'g':
6056         case 'G':
6057         {
6058           if (LocaleCompare(attribute,"geometry") == 0)
6059             {
6060               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6061               break;
6062             }
6063           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6064             attribute);
6065           break;
6066         }
6067         case 'H':
6068         case 'h':
6069         {
6070           if (LocaleCompare(attribute,"height") == 0)
6071             {
6072               region.height=SvIV(ST(i));
6073               continue;
6074             }
6075           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6076             attribute);
6077           break;
6078         }
6079         case 'X':
6080         case 'x':
6081         {
6082           if (LocaleCompare(attribute,"x") == 0)
6083             {
6084               region.x=SvIV(ST(i));
6085               continue;
6086             }
6087           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6088             attribute);
6089           break;
6090         }
6091         case 'Y':
6092         case 'y':
6093         {
6094           if (LocaleCompare(attribute,"y") == 0)
6095             {
6096               region.y=SvIV(ST(i));
6097               continue;
6098             }
6099           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6100             attribute);
6101           break;
6102         }
6103         case 'W':
6104         case 'w':
6105         {
6106           if (LocaleCompare(attribute,"width") == 0)
6107             {
6108               region.width=SvIV(ST(i));
6109               continue;
6110             }
6111           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6112             attribute);
6113           break;
6114         }
6115       }
6116     }
6117     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6118       region.height,exception);
6119     if (blob != (void *) NULL)
6120       goto PerlEnd;
6121
6122   PerlException:
6123     InheritPerlException(exception,perl_exception);
6124     exception=DestroyExceptionInfo(exception);
6125     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6126
6127   PerlEnd:
6128     RETVAL = (void *) blob;
6129   }
6130   OUTPUT:
6131     RETVAL
6132 \f
6133 #
6134 ###############################################################################
6135 #                                                                             #
6136 #                                                                             #
6137 #                                                                             #
6138 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6139 #                                                                             #
6140 #                                                                             #
6141 #                                                                             #
6142 ###############################################################################
6143 #
6144 #
6145 void *
6146 GetAuthenticMetacontent(ref,...)
6147   Image::Magick ref = NO_INIT
6148   ALIAS:
6149     getauthenticmetacontent = 1
6150     GetMetacontent = 2
6151     getmetacontent = 3
6152   CODE:
6153   {
6154     ExceptionInfo
6155       *exception;
6156
6157     Image
6158       *image;
6159
6160     struct PackageInfo
6161       *info;
6162
6163     SV
6164       *perl_exception,
6165       *reference;
6166
6167     void
6168       *blob = NULL;
6169
6170     PERL_UNUSED_VAR(ref);
6171     PERL_UNUSED_VAR(ix);
6172     exception=AcquireExceptionInfo();
6173     perl_exception=newSVpv("",0);
6174     if (sv_isobject(ST(0)) == 0)
6175       {
6176         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6177           PackageName);
6178         goto PerlException;
6179       }
6180     reference=SvRV(ST(0));
6181
6182     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6183     if (image == (Image *) NULL)
6184       {
6185         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6186           PackageName);
6187         goto PerlException;
6188       }
6189
6190     blob=(void *) GetAuthenticMetacontent(image);
6191     if (blob != (void *) NULL)
6192       goto PerlEnd;
6193
6194   PerlException:
6195     InheritPerlException(exception,perl_exception);
6196     exception=DestroyExceptionInfo(exception);
6197     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6198
6199   PerlEnd:
6200     RETVAL = blob;
6201   }
6202   OUTPUT:
6203     RETVAL
6204 \f
6205 #
6206 ###############################################################################
6207 #                                                                             #
6208 #                                                                             #
6209 #                                                                             #
6210 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6211 #                                                                             #
6212 #                                                                             #
6213 #                                                                             #
6214 ###############################################################################
6215 #
6216 #
6217 void *
6218 GetVirtualMetacontent(ref,...)
6219   Image::Magick ref = NO_INIT
6220   ALIAS:
6221     getvirtualmetacontent = 1
6222   CODE:
6223   {
6224     ExceptionInfo
6225       *exception;
6226
6227     Image
6228       *image;
6229
6230     struct PackageInfo
6231       *info;
6232
6233     SV
6234       *perl_exception,
6235       *reference;
6236
6237     void
6238       *blob = NULL;
6239
6240     PERL_UNUSED_VAR(ref);
6241     PERL_UNUSED_VAR(ix);
6242     exception=AcquireExceptionInfo();
6243     perl_exception=newSVpv("",0);
6244     if (sv_isobject(ST(0)) == 0)
6245       {
6246         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6247           PackageName);
6248         goto PerlException;
6249       }
6250     reference=SvRV(ST(0));
6251
6252     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6253     if (image == (Image *) NULL)
6254       {
6255         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6256           PackageName);
6257         goto PerlException;
6258       }
6259
6260     blob=(void *) GetVirtualMetacontent(image);
6261     if (blob != (void *) NULL)
6262       goto PerlEnd;
6263
6264   PerlException:
6265     InheritPerlException(exception,perl_exception);
6266     exception=DestroyExceptionInfo(exception);
6267     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6268
6269   PerlEnd:
6270     RETVAL = blob;
6271   }
6272   OUTPUT:
6273     RETVAL
6274 \f
6275 #
6276 ###############################################################################
6277 #                                                                             #
6278 #                                                                             #
6279 #                                                                             #
6280 #   H i s t o g r a m                                                         #
6281 #                                                                             #
6282 #                                                                             #
6283 #                                                                             #
6284 ###############################################################################
6285 #
6286 #
6287 void
6288 Histogram(ref,...)
6289   Image::Magick ref=NO_INIT
6290   ALIAS:
6291     HistogramImage = 1
6292     histogram      = 2
6293     histogramimage = 3
6294   PPCODE:
6295   {
6296     AV
6297       *av;
6298
6299     char
6300       message[MagickPathExtent];
6301
6302     PixelInfo
6303       *histogram;
6304
6305     ExceptionInfo
6306       *exception;
6307
6308     Image
6309       *image;
6310
6311     register ssize_t
6312       i;
6313
6314     ssize_t
6315       count;
6316
6317     struct PackageInfo
6318       *info;
6319
6320     SV
6321       *perl_exception,
6322       *reference;
6323
6324     size_t
6325       number_colors;
6326
6327     PERL_UNUSED_VAR(ref);
6328     PERL_UNUSED_VAR(ix);
6329     exception=AcquireExceptionInfo();
6330     perl_exception=newSVpv("",0);
6331     av=NULL;
6332     if (sv_isobject(ST(0)) == 0)
6333       {
6334         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6335           PackageName);
6336         goto PerlException;
6337       }
6338     reference=SvRV(ST(0));
6339     av=newAV();
6340     SvREFCNT_dec(av);
6341     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6342     if (image == (Image *) NULL)
6343       {
6344         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6345           PackageName);
6346         goto PerlException;
6347       }
6348     count=0;
6349     for ( ; image; image=image->next)
6350     {
6351       histogram=GetImageHistogram(image,&number_colors,exception);
6352       if (histogram == (PixelInfo *) NULL)
6353         continue;
6354       count+=(ssize_t) number_colors;
6355       EXTEND(sp,6*count);
6356       for (i=0; i < (ssize_t) number_colors; i++)
6357       {
6358         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6359           histogram[i].red);
6360         PUSHs(sv_2mortal(newSVpv(message,0)));
6361         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6362           histogram[i].green);
6363         PUSHs(sv_2mortal(newSVpv(message,0)));
6364         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6365           histogram[i].blue);
6366         PUSHs(sv_2mortal(newSVpv(message,0)));
6367         if (image->colorspace == CMYKColorspace)
6368           {
6369             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6370               histogram[i].black);
6371             PUSHs(sv_2mortal(newSVpv(message,0)));
6372           }
6373         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6374           histogram[i].alpha);
6375         PUSHs(sv_2mortal(newSVpv(message,0)));
6376         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6377           histogram[i].count);
6378         PUSHs(sv_2mortal(newSVpv(message,0)));
6379       }
6380       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6381     }
6382
6383   PerlException:
6384     InheritPerlException(exception,perl_exception);
6385     exception=DestroyExceptionInfo(exception);
6386     SvREFCNT_dec(perl_exception);
6387   }
6388 \f
6389 #
6390 ###############################################################################
6391 #                                                                             #
6392 #                                                                             #
6393 #                                                                             #
6394 #   G e t P i x e l                                                           #
6395 #                                                                             #
6396 #                                                                             #
6397 #                                                                             #
6398 ###############################################################################
6399 #
6400 #
6401 void
6402 GetPixel(ref,...)
6403   Image::Magick ref=NO_INIT
6404   ALIAS:
6405     getpixel = 1
6406     getPixel = 2
6407   PPCODE:
6408   {
6409     AV
6410       *av;
6411
6412     char
6413       *attribute;
6414
6415     ExceptionInfo
6416       *exception;
6417
6418     Image
6419       *image;
6420
6421     MagickBooleanType
6422       normalize;
6423
6424     RectangleInfo
6425       region;
6426
6427     register const Quantum
6428       *p;
6429
6430     register ssize_t
6431       i;
6432
6433     ssize_t
6434       option;
6435
6436     struct PackageInfo
6437       *info;
6438
6439     SV
6440       *perl_exception,
6441       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6442
6443     PERL_UNUSED_VAR(ref);
6444     PERL_UNUSED_VAR(ix);
6445     exception=AcquireExceptionInfo();
6446     perl_exception=newSVpv("",0);
6447     reference=SvRV(ST(0));
6448     av=(AV *) reference;
6449     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6450       exception);
6451     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6452     if (image == (Image *) NULL)
6453       {
6454         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6455           PackageName);
6456         goto PerlException;
6457       }
6458     normalize=MagickTrue;
6459     region.x=0;
6460     region.y=0;
6461     region.width=image->columns;
6462     region.height=1;
6463     if (items == 1)
6464       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6465     for (i=2; i < items; i+=2)
6466     {
6467       attribute=(char *) SvPV(ST(i-1),na);
6468       switch (*attribute)
6469       {
6470         case 'C':
6471         case 'c':
6472         {
6473           if (LocaleCompare(attribute,"channel") == 0)
6474             {
6475               ssize_t
6476                 option;
6477
6478               option=ParseChannelOption(SvPV(ST(i),na));
6479               if (option < 0)
6480                 {
6481                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6482                     SvPV(ST(i),na));
6483                   return;
6484                 }
6485               (void) SetPixelChannelMask(image,(ChannelType) option);
6486               break;
6487             }
6488           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6489             attribute);
6490           break;
6491         }
6492         case 'g':
6493         case 'G':
6494         {
6495           if (LocaleCompare(attribute,"geometry") == 0)
6496             {
6497               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6498               break;
6499             }
6500           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6501             attribute);
6502           break;
6503         }
6504         case 'N':
6505         case 'n':
6506         {
6507           if (LocaleCompare(attribute,"normalize") == 0)
6508             {
6509               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6510                 SvPV(ST(i),na));
6511               if (option < 0)
6512                 {
6513                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6514                     SvPV(ST(i),na));
6515                   break;
6516                 }
6517              normalize=option != 0 ? MagickTrue : MagickFalse;
6518              break;
6519             }
6520           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6521             attribute);
6522           break;
6523         }
6524         case 'x':
6525         case 'X':
6526         {
6527           if (LocaleCompare(attribute,"x") == 0)
6528             {
6529               region.x=SvIV(ST(i));
6530               break;
6531             }
6532           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6533             attribute);
6534           break;
6535         }
6536         case 'y':
6537         case 'Y':
6538         {
6539           if (LocaleCompare(attribute,"y") == 0)
6540             {
6541               region.y=SvIV(ST(i));
6542               break;
6543             }
6544           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6545             attribute);
6546           break;
6547         }
6548         default:
6549         {
6550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6551             attribute);
6552           break;
6553         }
6554       }
6555     }
6556     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6557     if (p == (const Quantum *) NULL)
6558       PUSHs(&sv_undef);
6559     else
6560       {
6561         double
6562           scale;
6563
6564         scale=1.0;
6565         if (normalize != MagickFalse)
6566           scale=1.0/QuantumRange;
6567         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6568           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6569         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6570           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6571         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6572           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6573         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6574             (image->colorspace == CMYKColorspace))
6575           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6576         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6577           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6578       }
6579
6580   PerlException:
6581     InheritPerlException(exception,perl_exception);
6582     exception=DestroyExceptionInfo(exception);
6583     SvREFCNT_dec(perl_exception);
6584   }
6585 \f
6586 #
6587 ###############################################################################
6588 #                                                                             #
6589 #                                                                             #
6590 #                                                                             #
6591 #   G e t P i x e l s                                                         #
6592 #                                                                             #
6593 #                                                                             #
6594 #                                                                             #
6595 ###############################################################################
6596 #
6597 #
6598 void
6599 GetPixels(ref,...)
6600   Image::Magick ref=NO_INIT
6601   ALIAS:
6602     getpixels = 1
6603     getPixels = 2
6604   PPCODE:
6605   {
6606     AV
6607       *av;
6608
6609     char
6610       *attribute;
6611
6612     const char
6613       *map;
6614
6615     ExceptionInfo
6616       *exception;
6617
6618     Image
6619       *image;
6620
6621     MagickBooleanType
6622       normalize,
6623       status;
6624
6625     RectangleInfo
6626       region;
6627
6628     register ssize_t
6629       i;
6630
6631     ssize_t
6632       option;
6633
6634     struct PackageInfo
6635       *info;
6636
6637     SV
6638       *perl_exception,
6639       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6640
6641     PERL_UNUSED_VAR(ref);
6642     PERL_UNUSED_VAR(ix);
6643     exception=AcquireExceptionInfo();
6644     perl_exception=newSVpv("",0);
6645     reference=SvRV(ST(0));
6646     av=(AV *) reference;
6647     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6648       exception);
6649     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6650     if (image == (Image *) NULL)
6651       {
6652         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6653           PackageName);
6654         goto PerlException;
6655       }
6656     map="RGB";
6657     if (image->alpha_trait != UndefinedPixelTrait)
6658       map="RGBA";
6659     if (image->colorspace == CMYKColorspace)
6660       {
6661         map="CMYK";
6662         if (image->alpha_trait != UndefinedPixelTrait)
6663           map="CMYKA";
6664       }
6665     normalize=MagickFalse;
6666     region.x=0;
6667     region.y=0;
6668     region.width=image->columns;
6669     region.height=1;
6670     if (items == 1)
6671       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6672     for (i=2; i < items; i+=2)
6673     {
6674       attribute=(char *) SvPV(ST(i-1),na);
6675       switch (*attribute)
6676       {
6677         case 'g':
6678         case 'G':
6679         {
6680           if (LocaleCompare(attribute,"geometry") == 0)
6681             {
6682               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6683               break;
6684             }
6685           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6686             attribute);
6687           break;
6688         }
6689         case 'H':
6690         case 'h':
6691         {
6692           if (LocaleCompare(attribute,"height") == 0)
6693             {
6694               region.height=SvIV(ST(i));
6695               break;
6696             }
6697           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6698             attribute);
6699           break;
6700         }
6701         case 'M':
6702         case 'm':
6703         {
6704           if (LocaleCompare(attribute,"map") == 0)
6705             {
6706               map=SvPV(ST(i),na);
6707               break;
6708             }
6709           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6710             attribute);
6711           break;
6712         }
6713         case 'N':
6714         case 'n':
6715         {
6716           if (LocaleCompare(attribute,"normalize") == 0)
6717             {
6718               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6719                 SvPV(ST(i),na));
6720               if (option < 0)
6721                 {
6722                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6723                     SvPV(ST(i),na));
6724                   break;
6725                 }
6726              normalize=option != 0 ? MagickTrue : MagickFalse;
6727              break;
6728             }
6729           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6730             attribute);
6731           break;
6732         }
6733         case 'W':
6734         case 'w':
6735         {
6736           if (LocaleCompare(attribute,"width") == 0)
6737             {
6738               region.width=SvIV(ST(i));
6739               break;
6740             }
6741           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6742             attribute);
6743           break;
6744         }
6745         case 'x':
6746         case 'X':
6747         {
6748           if (LocaleCompare(attribute,"x") == 0)
6749             {
6750               region.x=SvIV(ST(i));
6751               break;
6752             }
6753           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6754             attribute);
6755           break;
6756         }
6757         case 'y':
6758         case 'Y':
6759         {
6760           if (LocaleCompare(attribute,"y") == 0)
6761             {
6762               region.y=SvIV(ST(i));
6763               break;
6764             }
6765           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6766             attribute);
6767           break;
6768         }
6769         default:
6770         {
6771           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6772             attribute);
6773           break;
6774         }
6775       }
6776     }
6777     if (normalize != MagickFalse)
6778       {
6779         float
6780           *pixels;
6781
6782         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6783           region.height*sizeof(*pixels));
6784         if (pixels == (float *) NULL)
6785           {
6786             ThrowPerlException(exception,ResourceLimitError,
6787               "MemoryAllocationFailed",PackageName);
6788             goto PerlException;
6789           }
6790         status=ExportImagePixels(image,region.x,region.y,region.width,
6791           region.height,map,FloatPixel,pixels,exception);
6792         if (status == MagickFalse)
6793           PUSHs(&sv_undef);
6794         else
6795           {
6796             EXTEND(sp,strlen(map)*region.width*region.height);
6797             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6798               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6799           }
6800         pixels=(float *) RelinquishMagickMemory(pixels);
6801       }
6802     else
6803       {
6804         Quantum
6805           *pixels;
6806
6807         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6808           region.height*sizeof(*pixels));
6809         if (pixels == (Quantum *) NULL)
6810           {
6811             ThrowPerlException(exception,ResourceLimitError,
6812               "MemoryAllocationFailed",PackageName);
6813             goto PerlException;
6814           }
6815         status=ExportImagePixels(image,region.x,region.y,region.width,
6816           region.height,map,QuantumPixel,pixels,exception);
6817         if (status == MagickFalse)
6818           PUSHs(&sv_undef);
6819         else
6820           {
6821             EXTEND(sp,strlen(map)*region.width*region.height);
6822             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6823               PUSHs(sv_2mortal(newSViv(pixels[i])));
6824           }
6825         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6826       }
6827
6828   PerlException:
6829     InheritPerlException(exception,perl_exception);
6830     exception=DestroyExceptionInfo(exception);
6831     SvREFCNT_dec(perl_exception);
6832   }
6833 \f
6834 #
6835 ###############################################################################
6836 #                                                                             #
6837 #                                                                             #
6838 #                                                                             #
6839 #   I m a g e T o B l o b                                                     #
6840 #                                                                             #
6841 #                                                                             #
6842 #                                                                             #
6843 ###############################################################################
6844 #
6845 #
6846 void
6847 ImageToBlob(ref,...)
6848   Image::Magick ref=NO_INIT
6849   ALIAS:
6850     ImageToBlob  = 1
6851     imagetoblob  = 2
6852     toblob       = 3
6853     blob         = 4
6854   PPCODE:
6855   {
6856     char
6857       filename[MagickPathExtent];
6858
6859     ExceptionInfo
6860       *exception;
6861
6862     Image
6863       *image,
6864       *next;
6865
6866     register ssize_t
6867       i;
6868
6869     struct PackageInfo
6870       *info,
6871       *package_info;
6872
6873     size_t
6874       length;
6875
6876     ssize_t
6877       scene;
6878
6879     SV
6880       *perl_exception,
6881       *reference;
6882
6883     void
6884       *blob;
6885
6886     PERL_UNUSED_VAR(ref);
6887     PERL_UNUSED_VAR(ix);
6888     exception=AcquireExceptionInfo();
6889     perl_exception=newSVpv("",0);
6890     package_info=(struct PackageInfo *) NULL;
6891     if (sv_isobject(ST(0)) == 0)
6892       {
6893         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6894           PackageName);
6895         goto PerlException;
6896       }
6897     reference=SvRV(ST(0));
6898     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6899     if (image == (Image *) NULL)
6900       {
6901         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6902           PackageName);
6903         goto PerlException;
6904       }
6905     package_info=ClonePackageInfo(info,exception);
6906     for (i=2; i < items; i+=2)
6907       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6908     (void) CopyMagickString(filename,package_info->image_info->filename,
6909       MagickPathExtent);
6910     scene=0;
6911     for (next=image; next; next=next->next)
6912     {
6913       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6914       next->scene=scene++;
6915     }
6916     SetImageInfo(package_info->image_info,(unsigned int)
6917       GetImageListLength(image),exception);
6918     EXTEND(sp,(ssize_t) GetImageListLength(image));
6919     for ( ; image; image=image->next)
6920     {
6921       length=0;
6922       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6923       if (blob != (char *) NULL)
6924         {
6925           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6926           blob=(unsigned char *) RelinquishMagickMemory(blob);
6927         }
6928       if (package_info->image_info->adjoin)
6929         break;
6930     }
6931
6932   PerlException:
6933     if (package_info != (struct PackageInfo *) NULL)
6934       DestroyPackageInfo(package_info);
6935     InheritPerlException(exception,perl_exception);
6936     exception=DestroyExceptionInfo(exception);
6937     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6938   }
6939 \f
6940 #
6941 ###############################################################################
6942 #                                                                             #
6943 #                                                                             #
6944 #                                                                             #
6945 #   L a y e r s                                                               #
6946 #                                                                             #
6947 #                                                                             #
6948 #                                                                             #
6949 ###############################################################################
6950 #
6951 #
6952 void
6953 Layers(ref,...)
6954   Image::Magick ref=NO_INIT
6955   ALIAS:
6956     Layers                = 1
6957     layers           = 2
6958     OptimizeImageLayers   = 3
6959     optimizelayers        = 4
6960     optimizeimagelayers   = 5
6961   PPCODE:
6962   {
6963     AV
6964       *av;
6965
6966     char
6967       *attribute;
6968
6969     CompositeOperator
6970       compose;
6971
6972     ExceptionInfo
6973       *exception;
6974
6975     HV
6976       *hv;
6977
6978     Image
6979       *image,
6980       *layers;
6981
6982     LayerMethod
6983       method;
6984
6985     register ssize_t
6986       i;
6987
6988     ssize_t
6989       option,
6990       sp;
6991
6992     struct PackageInfo
6993       *info;
6994
6995     SV
6996       *av_reference,
6997       *perl_exception,
6998       *reference,
6999       *rv,
7000       *sv;
7001
7002     PERL_UNUSED_VAR(ref);
7003     PERL_UNUSED_VAR(ix);
7004     exception=AcquireExceptionInfo();
7005     perl_exception=newSVpv("",0);
7006     sv=NULL;
7007     if (sv_isobject(ST(0)) == 0)
7008       {
7009         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7010           PackageName);
7011         goto PerlException;
7012       }
7013     reference=SvRV(ST(0));
7014     hv=SvSTASH(reference);
7015     av=newAV();
7016     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7017     SvREFCNT_dec(av);
7018     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7019     if (image == (Image *) NULL)
7020       {
7021         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7022           PackageName);
7023         goto PerlException;
7024       }
7025     compose=image->compose;
7026     method=OptimizeLayer;
7027     for (i=2; i < items; i+=2)
7028     {
7029       attribute=(char *) SvPV(ST(i-1),na);
7030       switch (*attribute)
7031       {
7032         case 'C':
7033         case 'c':
7034         {
7035           if (LocaleCompare(attribute,"compose") == 0)
7036             {
7037               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7038                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7039               if (sp < 0)
7040                 {
7041                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7042                     SvPV(ST(i),na));
7043                   break;
7044                 }
7045               compose=(CompositeOperator) sp;
7046               break;
7047             }
7048           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7049             attribute);
7050           break;
7051         }
7052         case 'M':
7053         case 'm':
7054         {
7055           if (LocaleCompare(attribute,"method") == 0)
7056             {
7057               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7058                 SvPV(ST(i),na));
7059               if (option < 0)
7060                 {
7061                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7062                     SvPV(ST(i),na));
7063                   break;
7064                 }
7065               method=(LayerMethod) option;
7066               break;
7067             }
7068           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7069             attribute);
7070           break;
7071         }
7072         default:
7073         {
7074           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7075             attribute);
7076           break;
7077         }
7078       }
7079     }
7080     layers=(Image *) NULL;
7081     switch (method)
7082     {
7083       case CompareAnyLayer:
7084       case CompareClearLayer:
7085       case CompareOverlayLayer:
7086       default:
7087       {
7088         layers=CompareImagesLayers(image,method,exception);
7089         break;
7090       }
7091       case MergeLayer:
7092       case FlattenLayer:
7093       case MosaicLayer:
7094       {
7095         layers=MergeImageLayers(image,method,exception);
7096         break;
7097       }
7098       case DisposeLayer:
7099       {
7100         layers=DisposeImages(image,exception);
7101         break;
7102       }
7103       case OptimizeImageLayer:
7104       {
7105         layers=OptimizeImageLayers(image,exception);
7106         break;
7107       }
7108       case OptimizePlusLayer:
7109       {
7110         layers=OptimizePlusImageLayers(image,exception);
7111         break;
7112       }
7113       case OptimizeTransLayer:
7114       {
7115         OptimizeImageTransparency(image,exception);
7116         break;
7117       }
7118       case RemoveDupsLayer:
7119       {
7120         RemoveDuplicateLayers(&image,exception);
7121         break;
7122       }
7123       case RemoveZeroLayer:
7124       {
7125         RemoveZeroDelayLayers(&image,exception);
7126         break;
7127       }
7128       case OptimizeLayer:
7129       {
7130         QuantizeInfo
7131           *quantize_info;
7132
7133         /*
7134           General Purpose, GIF Animation Optimizer.
7135         */
7136         layers=CoalesceImages(image,exception);
7137         if (layers == (Image *) NULL)
7138           break;
7139         image=layers;
7140         layers=OptimizeImageLayers(image,exception);
7141         if (layers == (Image *) NULL)
7142           break;
7143         image=DestroyImageList(image);
7144         image=layers;
7145         layers=(Image *) NULL;
7146         OptimizeImageTransparency(image,exception);
7147         quantize_info=AcquireQuantizeInfo(info->image_info);
7148         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7149         quantize_info=DestroyQuantizeInfo(quantize_info);
7150         break;
7151       }
7152       case CompositeLayer:
7153       {
7154         Image
7155           *source;
7156
7157         RectangleInfo
7158           geometry;
7159
7160         /*
7161           Split image sequence at the first 'NULL:' image.
7162         */
7163         source=image;
7164         while (source != (Image *) NULL)
7165         {
7166           source=GetNextImageInList(source);
7167           if ((source != (Image *) NULL) &&
7168               (LocaleCompare(source->magick,"NULL") == 0))
7169             break;
7170         }
7171         if (source != (Image *) NULL)
7172           {
7173             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7174                 (GetNextImageInList(source) == (Image *) NULL))
7175               source=(Image *) NULL;
7176             else
7177               {
7178                 /*
7179                   Separate the two lists, junk the null: image.
7180                 */
7181                 source=SplitImageList(source->previous);
7182                 DeleteImageFromList(&source);
7183               }
7184           }
7185         if (source == (Image *) NULL)
7186           {
7187             (void) ThrowMagickException(exception,GetMagickModule(),
7188               OptionError,"MissingNullSeparator","layers Composite");
7189             break;
7190           }
7191         /*
7192           Adjust offset with gravity and virtual canvas.
7193         */
7194         SetGeometry(image,&geometry);
7195         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7196         geometry.width=source->page.width != 0 ? source->page.width :
7197           source->columns;
7198         geometry.height=source->page.height != 0 ? source->page.height :
7199           source->rows;
7200         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7201           image->columns,image->page.height != 0 ? image->page.height :
7202           image->rows,image->gravity,&geometry);
7203         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7204         source=DestroyImageList(source);
7205         break;
7206       }
7207     }
7208     if (layers != (Image *) NULL)
7209       image=layers;
7210     else
7211       image=CloneImage(image,0,0,MagickTrue,exception);
7212     if (image == (Image *) NULL)
7213       goto PerlException;
7214     for ( ; image; image=image->next)
7215     {
7216       AddImageToRegistry(sv,image);
7217       rv=newRV(sv);
7218       av_push(av,sv_bless(rv,hv));
7219       SvREFCNT_dec(sv);
7220     }
7221     exception=DestroyExceptionInfo(exception);
7222     ST(0)=av_reference;
7223     SvREFCNT_dec(perl_exception);
7224     XSRETURN(1);
7225
7226   PerlException:
7227     InheritPerlException(exception,perl_exception);
7228     exception=DestroyExceptionInfo(exception);
7229     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7230     SvPOK_on(perl_exception);
7231     ST(0)=sv_2mortal(perl_exception);
7232     XSRETURN(1);
7233   }
7234 \f
7235 #
7236 ###############################################################################
7237 #                                                                             #
7238 #                                                                             #
7239 #                                                                             #
7240 #   M a g i c k T o M i m e                                                   #
7241 #                                                                             #
7242 #                                                                             #
7243 #                                                                             #
7244 ###############################################################################
7245 #
7246 #
7247 SV *
7248 MagickToMime(ref,name)
7249   Image::Magick ref=NO_INIT
7250   char *name
7251   ALIAS:
7252     magicktomime = 1
7253   CODE:
7254   {
7255     char
7256       *mime;
7257
7258     PERL_UNUSED_VAR(ref);
7259     PERL_UNUSED_VAR(ix);
7260     mime=MagickToMime(name);
7261     RETVAL=newSVpv(mime,0);
7262     mime=(char *) RelinquishMagickMemory(mime);
7263   }
7264   OUTPUT:
7265     RETVAL
7266 \f
7267 #
7268 ###############################################################################
7269 #                                                                             #
7270 #                                                                             #
7271 #                                                                             #
7272 #   M o g r i f y                                                             #
7273 #                                                                             #
7274 #                                                                             #
7275 #                                                                             #
7276 ###############################################################################
7277 #
7278 #
7279 void
7280 Mogrify(ref,...)
7281   Image::Magick ref=NO_INIT
7282   ALIAS:
7283     Comment            =   1
7284     CommentImage       =   2
7285     Label              =   3
7286     LabelImage         =   4
7287     AddNoise           =   5
7288     AddNoiseImage      =   6
7289     Colorize           =   7
7290     ColorizeImage      =   8
7291     Border             =   9
7292     BorderImage        =  10
7293     Blur               =  11
7294     BlurImage          =  12
7295     Chop               =  13
7296     ChopImage          =  14
7297     Crop               =  15
7298     CropImage          =  16
7299     Despeckle          =  17
7300     DespeckleImage     =  18
7301     Edge               =  19
7302     EdgeImage          =  20
7303     Emboss             =  21
7304     EmbossImage        =  22
7305     Enhance            =  23
7306     EnhanceImage       =  24
7307     Flip               =  25
7308     FlipImage          =  26
7309     Flop               =  27
7310     FlopImage          =  28
7311     Frame              =  29
7312     FrameImage         =  30
7313     Implode            =  31
7314     ImplodeImage       =  32
7315     Magnify            =  33
7316     MagnifyImage       =  34
7317     MedianFilter       =  35
7318     MedianConvolveImage  =  36
7319     Minify             =  37
7320     MinifyImage        =  38
7321     OilPaint           =  39
7322     OilPaintImage      =  40
7323     ReduceNoise        =  41
7324     ReduceNoiseImage   =  42
7325     Roll               =  43
7326     RollImage          =  44
7327     Rotate             =  45
7328     RotateImage        =  46
7329     Sample             =  47
7330     SampleImage        =  48
7331     Scale              =  49
7332     ScaleImage         =  50
7333     Shade              =  51
7334     ShadeImage         =  52
7335     Sharpen            =  53
7336     SharpenImage       =  54
7337     Shear              =  55
7338     ShearImage         =  56
7339     Spread             =  57
7340     SpreadImage        =  58
7341     Swirl              =  59
7342     SwirlImage         =  60
7343     Resize             =  61
7344     ResizeImage        =  62
7345     Zoom               =  63
7346     ZoomImage          =  64
7347     Annotate           =  65
7348     AnnotateImage      =  66
7349     ColorFloodfill     =  67
7350     ColorFloodfillImage=  68
7351     Composite          =  69
7352     CompositeImage     =  70
7353     Contrast           =  71
7354     ContrastImage      =  72
7355     CycleColormap      =  73
7356     CycleColormapImage =  74
7357     Draw               =  75
7358     DrawImage          =  76
7359     Equalize           =  77
7360     EqualizeImage      =  78
7361     Gamma              =  79
7362     GammaImage         =  80
7363     Map                =  81
7364     MapImage           =  82
7365     MatteFloodfill     =  83
7366     MatteFloodfillImage=  84
7367     Modulate           =  85
7368     ModulateImage      =  86
7369     Negate             =  87
7370     NegateImage        =  88
7371     Normalize          =  89
7372     NormalizeImage     =  90
7373     NumberColors       =  91
7374     NumberColorsImage  =  92
7375     Opaque             =  93
7376     OpaqueImage        =  94
7377     Quantize           =  95
7378     QuantizeImage      =  96
7379     Raise              =  97
7380     RaiseImage         =  98
7381     Segment            =  99
7382     SegmentImage       = 100
7383     Signature          = 101
7384     SignatureImage     = 102
7385     Solarize           = 103
7386     SolarizeImage      = 104
7387     Sync               = 105
7388     SyncImage          = 106
7389     Texture            = 107
7390     TextureImage       = 108
7391     Evaluate           = 109
7392     EvaluateImage      = 110
7393     Transparent        = 111
7394     TransparentImage   = 112
7395     Threshold          = 113
7396     ThresholdImage     = 114
7397     Charcoal           = 115
7398     CharcoalImage      = 116
7399     Trim               = 117
7400     TrimImage          = 118
7401     Wave               = 119
7402     WaveImage          = 120
7403     Separate           = 121
7404     SeparateImage      = 122
7405     Stereo             = 125
7406     StereoImage        = 126
7407     Stegano            = 127
7408     SteganoImage       = 128
7409     Deconstruct        = 129
7410     DeconstructImage   = 130
7411     GaussianBlur       = 131
7412     GaussianBlurImage  = 132
7413     Convolve           = 133
7414     ConvolveImage      = 134
7415     Profile            = 135
7416     ProfileImage       = 136
7417     UnsharpMask        = 137
7418     UnsharpMaskImage   = 138
7419     MotionBlur         = 139
7420     MotionBlurImage    = 140
7421     OrderedDither      = 141
7422     OrderedDitherImage = 142
7423     Shave              = 143
7424     ShaveImage         = 144
7425     Level              = 145
7426     LevelImage         = 146
7427     Clip               = 147
7428     ClipImage          = 148
7429     AffineTransform    = 149
7430     AffineTransformImage = 150
7431     Difference         = 151
7432     DifferenceImage    = 152
7433     AdaptiveThreshold  = 153
7434     AdaptiveThresholdImage = 154
7435     Resample           = 155
7436     ResampleImage      = 156
7437     Describe           = 157
7438     DescribeImage      = 158
7439     BlackThreshold     = 159
7440     BlackThresholdImage= 160
7441     WhiteThreshold     = 161
7442     WhiteThresholdImage= 162
7443     RotationalBlur     = 163
7444     RotationalBlurImage= 164
7445     Thumbnail          = 165
7446     ThumbnailImage     = 166
7447     Strip              = 167
7448     StripImage         = 168
7449     Tint               = 169
7450     TintImage          = 170
7451     Channel            = 171
7452     ChannelImage       = 172
7453     Splice             = 173
7454     SpliceImage        = 174
7455     Posterize          = 175
7456     PosterizeImage     = 176
7457     Shadow             = 177
7458     ShadowImage        = 178
7459     Identify           = 179
7460     IdentifyImage      = 180
7461     SepiaTone          = 181
7462     SepiaToneImage     = 182
7463     SigmoidalContrast  = 183
7464     SigmoidalContrastImage = 184
7465     Extent             = 185
7466     ExtentImage        = 186
7467     Vignette           = 187
7468     VignetteImage      = 188
7469     ContrastStretch    = 189
7470     ContrastStretchImage = 190
7471     Sans0              = 191
7472     Sans0Image         = 192
7473     Sans1              = 193
7474     Sans1Image         = 194
7475     AdaptiveSharpen    = 195
7476     AdaptiveSharpenImage = 196
7477     Transpose          = 197
7478     TransposeImage     = 198
7479     Transverse         = 199
7480     TransverseImage    = 200
7481     AutoOrient         = 201
7482     AutoOrientImage    = 202
7483     AdaptiveBlur       = 203
7484     AdaptiveBlurImage  = 204
7485     Sketch             = 205
7486     SketchImage        = 206
7487     UniqueColors       = 207
7488     UniqueColorsImage  = 208
7489     AdaptiveResize     = 209
7490     AdaptiveResizeImage= 210
7491     ClipMask           = 211
7492     ClipMaskImage      = 212
7493     LinearStretch      = 213
7494     LinearStretchImage = 214
7495     ColorMatrix        = 215
7496     ColorMatrixImage   = 216
7497     Mask               = 217
7498     MaskImage          = 218
7499     Polaroid           = 219
7500     PolaroidImage      = 220
7501     FloodfillPaint     = 221
7502     FloodfillPaintImage= 222
7503     Distort            = 223
7504     DistortImage       = 224
7505     Clut               = 225
7506     ClutImage          = 226
7507     LiquidRescale      = 227
7508     LiquidRescaleImage = 228
7509     Encipher           = 229
7510     EncipherImage      = 230
7511     Decipher           = 231
7512     DecipherImage      = 232
7513     Deskew             = 233
7514     DeskewImage        = 234
7515     Remap              = 235
7516     RemapImage         = 236
7517     SparseColor        = 237
7518     SparseColorImage   = 238
7519     Function           = 239
7520     FunctionImage      = 240
7521     SelectiveBlur      = 241
7522     SelectiveBlurImage = 242
7523     HaldClut           = 243
7524     HaldClutImage      = 244
7525     BlueShift          = 245
7526     BlueShiftImage     = 246
7527     ForwardFourierTransform  = 247
7528     ForwardFourierTransformImage = 248
7529     InverseFourierTransform = 249
7530     InverseFourierTransformImage = 250
7531     ColorDecisionList  = 251
7532     ColorDecisionListImage = 252
7533     AutoGamma          = 253
7534     AutoGammaImage     = 254
7535     AutoLevel          = 255
7536     AutoLevelImage     = 256
7537     LevelColors        = 257
7538     LevelImageColors   = 258
7539     Clamp              = 259
7540     ClampImage         = 260
7541     BrightnessContrast = 261
7542     BrightnessContrastImage = 262
7543     Morphology         = 263
7544     MorphologyImage    = 264
7545     Mode               = 265
7546     ModeImage          = 266
7547     Statistic          = 267
7548     StatisticImage     = 268
7549     Perceptible        = 269
7550     PerceptibleImage   = 270
7551     Poly               = 271
7552     PolyImage          = 272
7553     Grayscale          = 273
7554     GrayscaleImage     = 274
7555     CannyEdge          = 275
7556     CannyEdgeImage     = 276
7557     HoughLine          = 277
7558     HoughLineImage     = 278
7559     MeanShift          = 279
7560     MeanShiftImage     = 280
7561     Kuwahara           = 281
7562     KuwaharaImage      = 282
7563     ConnectedComponent = 283
7564     ConnectedComponentImage = 284
7565     CopyPixels         = 285
7566     CopyImagePixels    = 286
7567     Color              = 287
7568     ColorImage         = 288
7569     WaveletDenoise     = 289
7570     WaveletDenoiseImage= 290
7571     Colorspace         = 291
7572     ColorspaceImage    = 292
7573     MogrifyRegion      = 666
7574   PPCODE:
7575   {
7576     AffineMatrix
7577       affine,
7578       current;
7579
7580     char
7581       attribute_flag[MaxArguments],
7582       message[MagickPathExtent];
7583
7584     ChannelType
7585       channel,
7586       channel_mask;
7587
7588     CompositeOperator
7589       compose;
7590
7591     const char
7592       *attribute,
7593       *value;
7594
7595     double
7596       angle;
7597
7598     ExceptionInfo
7599       *exception;
7600
7601     GeometryInfo
7602       geometry_info;
7603
7604     Image
7605       *image,
7606       *next,
7607       *region_image;
7608
7609     MagickBooleanType
7610       status;
7611
7612     MagickStatusType
7613       flags;
7614
7615     PixelInfo
7616       fill_color;
7617
7618     RectangleInfo
7619       geometry,
7620       region_info;
7621
7622     register ssize_t
7623       i;
7624
7625     ssize_t
7626       base,
7627       j,
7628       number_images;
7629
7630     struct Methods
7631       *rp;
7632
7633     struct PackageInfo
7634       *info;
7635
7636     SV
7637       *perl_exception,
7638       **pv,
7639       *reference,
7640       **reference_vector;
7641
7642     struct ArgumentList
7643       argument_list[MaxArguments];
7644
7645     PERL_UNUSED_VAR(ref);
7646     PERL_UNUSED_VAR(ix);
7647     exception=AcquireExceptionInfo();
7648     perl_exception=newSVpv("",0);
7649     reference_vector=NULL;
7650     region_image=NULL;
7651     number_images=0;
7652     base=2;
7653     if (sv_isobject(ST(0)) == 0)
7654       {
7655         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7656           PackageName);
7657         goto PerlException;
7658       }
7659     reference=SvRV(ST(0));
7660     region_info.width=0;
7661     region_info.height=0;
7662     region_info.x=0;
7663     region_info.y=0;
7664     region_image=(Image *) NULL;
7665     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7666     if (ix && (ix != 666))
7667       {
7668         /*
7669           Called as Method(...)
7670         */
7671         ix=(ix+1)/2;
7672         rp=(&Methods[ix-1]);
7673         attribute=rp->name;
7674       }
7675     else
7676       {
7677         /*
7678           Called as Mogrify("Method",...)
7679         */
7680         attribute=(char *) SvPV(ST(1),na);
7681         if (ix)
7682           {
7683             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7684             attribute=(char *) SvPV(ST(2),na);
7685             base++;
7686           }
7687         for (rp=Methods; ; rp++)
7688         {
7689           if (rp >= EndOf(Methods))
7690             {
7691               ThrowPerlException(exception,OptionError,
7692                 "UnrecognizedPerlMagickMethod",attribute);
7693               goto PerlException;
7694             }
7695           if (strEQcase(attribute,rp->name))
7696             break;
7697         }
7698         ix=rp-Methods+1;
7699         base++;
7700       }
7701     if (image == (Image *) NULL)
7702       {
7703         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7704         goto PerlException;
7705       }
7706     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7707     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7708     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7709     {
7710       Arguments
7711         *pp,
7712         *qq;
7713
7714       ssize_t
7715         ssize_test;
7716
7717       struct ArgumentList
7718         *al;
7719
7720       SV
7721         *sv;
7722
7723       sv=NULL;
7724       ssize_test=0;
7725       pp=(Arguments *) NULL;
7726       qq=rp->arguments;
7727       if (i == items)
7728         {
7729           pp=rp->arguments,
7730           sv=ST(i-1);
7731         }
7732       else
7733         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7734         {
7735           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7736             break;
7737           if (strEQcase(attribute,qq->method) > ssize_test)
7738             {
7739               pp=qq;
7740               ssize_test=strEQcase(attribute,qq->method);
7741             }
7742         }
7743       if (pp == (Arguments *) NULL)
7744         {
7745           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7746             attribute);
7747           goto continue_outer_loop;
7748         }
7749       al=(&argument_list[pp-rp->arguments]);
7750       switch (pp->type)
7751       {
7752         case ArrayReference:
7753         {
7754           if (SvTYPE(sv) != SVt_RV)
7755             {
7756               (void) FormatLocaleString(message,MagickPathExtent,
7757                 "invalid %.60s value",pp->method);
7758               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7759               goto continue_outer_loop;
7760             }
7761           al->array_reference=SvRV(sv);
7762           break;
7763         }
7764         case RealReference:
7765         {
7766           al->real_reference=SvNV(sv);
7767           break;
7768         }
7769         case FileReference:
7770         {
7771           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7772           break;
7773         }
7774         case ImageReference:
7775         {
7776           if (!sv_isobject(sv) ||
7777               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7778                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7779             {
7780               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7781                 PackageName);
7782               goto PerlException;
7783             }
7784           break;
7785         }
7786         case IntegerReference:
7787         {
7788           al->integer_reference=SvIV(sv);
7789           break;
7790         }
7791         case StringReference:
7792         {
7793           al->string_reference=(char *) SvPV(sv,al->length);
7794           if (sv_isobject(sv))
7795             al->image_reference=SetupList(aTHX_ SvRV(sv),
7796               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7797           break;
7798         }
7799         default:
7800         {
7801           /*
7802             Is a string; look up name.
7803           */
7804           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7805             {
7806               al->string_reference=(char *) SvPV(sv,al->length);
7807               al->integer_reference=(-1);
7808               break;
7809             }
7810           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7811             MagickFalse,SvPV(sv,na));
7812           if (pp->type == MagickChannelOptions)
7813             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7814           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7815             {
7816               (void) FormatLocaleString(message,MagickPathExtent,
7817                 "invalid %.60s value",pp->method);
7818               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7819               goto continue_outer_loop;
7820             }
7821           break;
7822         }
7823       }
7824       attribute_flag[pp-rp->arguments]++;
7825       continue_outer_loop: ;
7826     }
7827     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7828     pv=reference_vector;
7829     SetGeometryInfo(&geometry_info);
7830     channel=DefaultChannels;
7831     for (next=image; next; next=next->next)
7832     {
7833       image=next;
7834       SetGeometry(image,&geometry);
7835       if ((region_info.width*region_info.height) != 0)
7836         {
7837           region_image=image;
7838           image=CropImage(image,&region_info,exception);
7839         }
7840       switch (ix)
7841       {
7842         default:
7843         {
7844           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7845           ThrowPerlException(exception,OptionError,
7846             "UnrecognizedPerlMagickMethod",message);
7847           goto PerlException;
7848         }
7849         case 1:  /* Comment */
7850         {
7851           if (attribute_flag[0] == 0)
7852             argument_list[0].string_reference=(char *) NULL;
7853           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7854             info ? info->image_info : (ImageInfo *) NULL,image,
7855             argument_list[0].string_reference,exception),exception);
7856           break;
7857         }
7858         case 2:  /* Label */
7859         {
7860           if (attribute_flag[0] == 0)
7861             argument_list[0].string_reference=(char *) NULL;
7862           (void) SetImageProperty(image,"label",InterpretImageProperties(
7863             info ? info->image_info : (ImageInfo *) NULL,image,
7864             argument_list[0].string_reference,exception),exception);
7865           break;
7866         }
7867         case 3:  /* AddNoise */
7868         {
7869           double
7870             attenuate;
7871
7872           if (attribute_flag[0] == 0)
7873             argument_list[0].integer_reference=UniformNoise;
7874           attenuate=1.0;
7875           if (attribute_flag[1] != 0)
7876             attenuate=argument_list[1].real_reference;
7877           if (attribute_flag[2] != 0)
7878             channel=(ChannelType) argument_list[2].integer_reference;
7879           channel_mask=SetImageChannelMask(image,channel);
7880           image=AddNoiseImage(image,(NoiseType)
7881             argument_list[0].integer_reference,attenuate,exception);
7882           if (image != (Image *) NULL)
7883             (void) SetImageChannelMask(image,channel_mask);
7884           break;
7885         }
7886         case 4:  /* Colorize */
7887         {
7888           PixelInfo
7889             target;
7890
7891           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7892             0,0,&target,exception);
7893           if (attribute_flag[0] != 0)
7894             (void) QueryColorCompliance(argument_list[0].string_reference,
7895               AllCompliance,&target,exception);
7896           if (attribute_flag[1] == 0)
7897             argument_list[1].string_reference="100%";
7898           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7899             exception);
7900           break;
7901         }
7902         case 5:  /* Border */
7903         {
7904           CompositeOperator
7905             compose;
7906
7907           geometry.width=0;
7908           geometry.height=0;
7909           if (attribute_flag[0] != 0)
7910             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7911               &geometry,exception);
7912           if (attribute_flag[1] != 0)
7913             geometry.width=argument_list[1].integer_reference;
7914           if (attribute_flag[2] != 0)
7915             geometry.height=argument_list[2].integer_reference;
7916           if (attribute_flag[3] != 0)
7917             QueryColorCompliance(argument_list[3].string_reference,
7918               AllCompliance,&image->border_color,exception);
7919           if (attribute_flag[4] != 0)
7920             QueryColorCompliance(argument_list[4].string_reference,
7921               AllCompliance,&image->border_color,exception);
7922           if (attribute_flag[5] != 0)
7923             QueryColorCompliance(argument_list[5].string_reference,
7924               AllCompliance,&image->border_color,exception);
7925           compose=image->compose;
7926           if (attribute_flag[6] != 0)
7927             compose=(CompositeOperator) argument_list[6].integer_reference;
7928           image=BorderImage(image,&geometry,compose,exception);
7929           break;
7930         }
7931         case 6:  /* Blur */
7932         {
7933           if (attribute_flag[0] != 0)
7934             {
7935               flags=ParseGeometry(argument_list[0].string_reference,
7936                 &geometry_info);
7937               if ((flags & SigmaValue) == 0)
7938                 geometry_info.sigma=1.0;
7939             }
7940           if (attribute_flag[1] != 0)
7941             geometry_info.rho=argument_list[1].real_reference;
7942           if (attribute_flag[2] != 0)
7943             geometry_info.sigma=argument_list[2].real_reference;
7944           if (attribute_flag[3] != 0)
7945             channel=(ChannelType) argument_list[3].integer_reference;
7946           channel_mask=SetImageChannelMask(image,channel);
7947           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7948             exception);
7949           if (image != (Image *) NULL)
7950             (void) SetImageChannelMask(image,channel_mask);
7951           break;
7952         }
7953         case 7:  /* Chop */
7954         {
7955           if (attribute_flag[5] != 0)
7956             image->gravity=(GravityType) argument_list[5].integer_reference;
7957           if (attribute_flag[0] != 0)
7958             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7959               &geometry,exception);
7960           if (attribute_flag[1] != 0)
7961             geometry.width=argument_list[1].integer_reference;
7962           if (attribute_flag[2] != 0)
7963             geometry.height=argument_list[2].integer_reference;
7964           if (attribute_flag[3] != 0)
7965             geometry.x=argument_list[3].integer_reference;
7966           if (attribute_flag[4] != 0)
7967             geometry.y=argument_list[4].integer_reference;
7968           image=ChopImage(image,&geometry,exception);
7969           break;
7970         }
7971         case 8:  /* Crop */
7972         {
7973           if (attribute_flag[6] != 0)
7974             image->gravity=(GravityType) argument_list[6].integer_reference;
7975           if (attribute_flag[0] != 0)
7976             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7977               &geometry,exception);
7978           if (attribute_flag[1] != 0)
7979             geometry.width=argument_list[1].integer_reference;
7980           if (attribute_flag[2] != 0)
7981             geometry.height=argument_list[2].integer_reference;
7982           if (attribute_flag[3] != 0)
7983             geometry.x=argument_list[3].integer_reference;
7984           if (attribute_flag[4] != 0)
7985             geometry.y=argument_list[4].integer_reference;
7986           if (attribute_flag[5] != 0)
7987             image->fuzz=StringToDoubleInterval(
7988               argument_list[5].string_reference,(double) QuantumRange+1.0);
7989           image=CropImage(image,&geometry,exception);
7990           break;
7991         }
7992         case 9:  /* Despeckle */
7993         {
7994           image=DespeckleImage(image,exception);
7995           break;
7996         }
7997         case 10:  /* Edge */
7998         {
7999           if (attribute_flag[0] != 0)
8000             geometry_info.rho=argument_list[0].real_reference;
8001           image=EdgeImage(image,geometry_info.rho,exception);
8002           break;
8003         }
8004         case 11:  /* Emboss */
8005         {
8006           if (attribute_flag[0] != 0)
8007             {
8008               flags=ParseGeometry(argument_list[0].string_reference,
8009                 &geometry_info);
8010               if ((flags & SigmaValue) == 0)
8011                 geometry_info.sigma=1.0;
8012             }
8013           if (attribute_flag[1] != 0)
8014             geometry_info.rho=argument_list[1].real_reference;
8015           if (attribute_flag[2] != 0)
8016             geometry_info.sigma=argument_list[2].real_reference;
8017           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8018             exception);
8019           break;
8020         }
8021         case 12:  /* Enhance */
8022         {
8023           image=EnhanceImage(image,exception);
8024           break;
8025         }
8026         case 13:  /* Flip */
8027         {
8028           image=FlipImage(image,exception);
8029           break;
8030         }
8031         case 14:  /* Flop */
8032         {
8033           image=FlopImage(image,exception);
8034           break;
8035         }
8036         case 15:  /* Frame */
8037         {
8038           CompositeOperator
8039             compose;
8040
8041           FrameInfo
8042             frame_info;
8043
8044           if (attribute_flag[0] != 0)
8045             {
8046               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8047                 &geometry,exception);
8048               frame_info.width=geometry.width;
8049               frame_info.height=geometry.height;
8050               frame_info.outer_bevel=geometry.x;
8051               frame_info.inner_bevel=geometry.y;
8052             }
8053           if (attribute_flag[1] != 0)
8054             frame_info.width=argument_list[1].integer_reference;
8055           if (attribute_flag[2] != 0)
8056             frame_info.height=argument_list[2].integer_reference;
8057           if (attribute_flag[3] != 0)
8058             frame_info.inner_bevel=argument_list[3].integer_reference;
8059           if (attribute_flag[4] != 0)
8060             frame_info.outer_bevel=argument_list[4].integer_reference;
8061           if (attribute_flag[5] != 0)
8062             QueryColorCompliance(argument_list[5].string_reference,
8063               AllCompliance,&fill_color,exception);
8064           if (attribute_flag[6] != 0)
8065             QueryColorCompliance(argument_list[6].string_reference,
8066               AllCompliance,&fill_color,exception);
8067           frame_info.x=(ssize_t) frame_info.width;
8068           frame_info.y=(ssize_t) frame_info.height;
8069           frame_info.width=image->columns+2*frame_info.x;
8070           frame_info.height=image->rows+2*frame_info.y;
8071           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8072             image->alpha_color=fill_color;
8073           compose=image->compose;
8074           if (attribute_flag[7] != 0)
8075             compose=(CompositeOperator) argument_list[7].integer_reference;
8076           image=FrameImage(image,&frame_info,compose,exception);
8077           break;
8078         }
8079         case 16:  /* Implode */
8080         {
8081           PixelInterpolateMethod
8082             method;
8083
8084           if (attribute_flag[0] == 0)
8085             argument_list[0].real_reference=0.5;
8086           method=UndefinedInterpolatePixel;
8087           if (attribute_flag[1] != 0)
8088             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8089           image=ImplodeImage(image,argument_list[0].real_reference,
8090             method,exception);
8091           break;
8092         }
8093         case 17:  /* Magnify */
8094         {
8095           image=MagnifyImage(image,exception);
8096           break;
8097         }
8098         case 18:  /* MedianFilter */
8099         {
8100           if (attribute_flag[0] != 0)
8101             {
8102               flags=ParseGeometry(argument_list[0].string_reference,
8103                 &geometry_info);
8104               if ((flags & SigmaValue) == 0)
8105                 geometry_info.sigma=geometry_info.rho;
8106             }
8107           if (attribute_flag[1] != 0)
8108             geometry_info.rho=argument_list[1].real_reference;
8109           if (attribute_flag[2] != 0)
8110             geometry_info.sigma=argument_list[2].real_reference;
8111           if (attribute_flag[3] != 0)
8112             channel=(ChannelType) argument_list[3].integer_reference;
8113           channel_mask=SetImageChannelMask(image,channel);
8114           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8115             (size_t) geometry_info.sigma,exception);
8116           if (image != (Image *) NULL)
8117             (void) SetImageChannelMask(image,channel_mask);
8118           break;
8119         }
8120         case 19:  /* Minify */
8121         {
8122           image=MinifyImage(image,exception);
8123           break;
8124         }
8125         case 20:  /* OilPaint */
8126         {
8127           if (attribute_flag[0] == 0)
8128             argument_list[0].real_reference=0.0;
8129           if (attribute_flag[1] == 0)
8130             argument_list[1].real_reference=1.0;
8131           image=OilPaintImage(image,argument_list[0].real_reference,
8132             argument_list[1].real_reference,exception);
8133           break;
8134         }
8135         case 21:  /* ReduceNoise */
8136         {
8137           if (attribute_flag[0] != 0)
8138             {
8139               flags=ParseGeometry(argument_list[0].string_reference,
8140                 &geometry_info);
8141               if ((flags & SigmaValue) == 0)
8142                 geometry_info.sigma=1.0;
8143             }
8144           if (attribute_flag[1] != 0)
8145             geometry_info.rho=argument_list[1].real_reference;
8146           if (attribute_flag[2] != 0)
8147             geometry_info.sigma=argument_list[2].real_reference;
8148           if (attribute_flag[3] != 0)
8149             channel=(ChannelType) argument_list[3].integer_reference;
8150           channel_mask=SetImageChannelMask(image,channel);
8151           image=StatisticImage(image,NonpeakStatistic,(size_t)
8152             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8153           if (image != (Image *) NULL)
8154             (void) SetImageChannelMask(image,channel_mask);
8155           break;
8156         }
8157         case 22:  /* Roll */
8158         {
8159           if (attribute_flag[0] != 0)
8160             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8161               &geometry,exception);
8162           if (attribute_flag[1] != 0)
8163             geometry.x=argument_list[1].integer_reference;
8164           if (attribute_flag[2] != 0)
8165             geometry.y=argument_list[2].integer_reference;
8166           image=RollImage(image,geometry.x,geometry.y,exception);
8167           break;
8168         }
8169         case 23:  /* Rotate */
8170         {
8171           if (attribute_flag[0] == 0)
8172             argument_list[0].real_reference=90.0;
8173           if (attribute_flag[1] != 0)
8174             {
8175               QueryColorCompliance(argument_list[1].string_reference,
8176                 AllCompliance,&image->background_color,exception);
8177               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8178                   (image->alpha_trait == UndefinedPixelTrait))
8179                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8180             }
8181           image=RotateImage(image,argument_list[0].real_reference,exception);
8182           break;
8183         }
8184         case 24:  /* Sample */
8185         {
8186           if (attribute_flag[0] != 0)
8187             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8188               &geometry,exception);
8189           if (attribute_flag[1] != 0)
8190             geometry.width=argument_list[1].integer_reference;
8191           if (attribute_flag[2] != 0)
8192             geometry.height=argument_list[2].integer_reference;
8193           image=SampleImage(image,geometry.width,geometry.height,exception);
8194           break;
8195         }
8196         case 25:  /* Scale */
8197         {
8198           if (attribute_flag[0] != 0)
8199             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8200               &geometry,exception);
8201           if (attribute_flag[1] != 0)
8202             geometry.width=argument_list[1].integer_reference;
8203           if (attribute_flag[2] != 0)
8204             geometry.height=argument_list[2].integer_reference;
8205           image=ScaleImage(image,geometry.width,geometry.height,exception);
8206           break;
8207         }
8208         case 26:  /* Shade */
8209         {
8210           if (attribute_flag[0] != 0)
8211             {
8212               flags=ParseGeometry(argument_list[0].string_reference,
8213                 &geometry_info);
8214               if ((flags & SigmaValue) == 0)
8215                 geometry_info.sigma=0.0;
8216             }
8217           if (attribute_flag[1] != 0)
8218             geometry_info.rho=argument_list[1].real_reference;
8219           if (attribute_flag[2] != 0)
8220             geometry_info.sigma=argument_list[2].real_reference;
8221           image=ShadeImage(image,
8222             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8223             geometry_info.rho,geometry_info.sigma,exception);
8224           break;
8225         }
8226         case 27:  /* Sharpen */
8227         {
8228           if (attribute_flag[0] != 0)
8229             {
8230               flags=ParseGeometry(argument_list[0].string_reference,
8231                 &geometry_info);
8232               if ((flags & SigmaValue) == 0)
8233                 geometry_info.sigma=1.0;
8234             }
8235           if (attribute_flag[1] != 0)
8236             geometry_info.rho=argument_list[1].real_reference;
8237           if (attribute_flag[2] != 0)
8238             geometry_info.sigma=argument_list[2].real_reference;
8239           if (attribute_flag[3] != 0)
8240             channel=(ChannelType) argument_list[3].integer_reference;
8241           channel_mask=SetImageChannelMask(image,channel);
8242           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8243             exception);
8244           if (image != (Image *) NULL)
8245             (void) SetImageChannelMask(image,channel_mask);
8246           break;
8247         }
8248         case 28:  /* Shear */
8249         {
8250           if (attribute_flag[0] != 0)
8251             {
8252               flags=ParseGeometry(argument_list[0].string_reference,
8253                 &geometry_info);
8254               if ((flags & SigmaValue) == 0)
8255                 geometry_info.sigma=geometry_info.rho;
8256             }
8257           if (attribute_flag[1] != 0)
8258             geometry_info.rho=argument_list[1].real_reference;
8259           if (attribute_flag[2] != 0)
8260             geometry_info.sigma=argument_list[2].real_reference;
8261           if (attribute_flag[3] != 0)
8262             QueryColorCompliance(argument_list[3].string_reference,
8263               AllCompliance,&image->background_color,exception);
8264           if (attribute_flag[4] != 0)
8265             QueryColorCompliance(argument_list[4].string_reference,
8266               AllCompliance,&image->background_color,exception);
8267           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8268             exception);
8269           break;
8270         }
8271         case 29:  /* Spread */
8272         {
8273           PixelInterpolateMethod
8274             method;
8275
8276           if (attribute_flag[0] == 0)
8277             argument_list[0].real_reference=1.0;
8278           method=UndefinedInterpolatePixel;
8279           if (attribute_flag[1] != 0)
8280             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8281           image=SpreadImage(image,method,argument_list[0].real_reference,
8282             exception);
8283           break;
8284         }
8285         case 30:  /* Swirl */
8286         {
8287           PixelInterpolateMethod
8288             method;
8289
8290           if (attribute_flag[0] == 0)
8291             argument_list[0].real_reference=50.0;
8292           method=UndefinedInterpolatePixel;
8293           if (attribute_flag[1] != 0)
8294             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8295           image=SwirlImage(image,argument_list[0].real_reference,
8296             method,exception);
8297           break;
8298         }
8299         case 31:  /* Resize */
8300         case 32:  /* Zoom */
8301         {
8302           if (attribute_flag[0] != 0)
8303             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8304               &geometry,exception);
8305           if (attribute_flag[1] != 0)
8306             geometry.width=argument_list[1].integer_reference;
8307           if (attribute_flag[2] != 0)
8308             geometry.height=argument_list[2].integer_reference;
8309           if (attribute_flag[3] == 0)
8310             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8311           if (attribute_flag[4] != 0)
8312             SetImageArtifact(image,"filter:support",
8313               argument_list[4].string_reference);
8314           image=ResizeImage(image,geometry.width,geometry.height,
8315             (FilterType) argument_list[3].integer_reference,
8316             exception);
8317           break;
8318         }
8319         case 33:  /* Annotate */
8320         {
8321           DrawInfo
8322             *draw_info;
8323
8324           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8325             (DrawInfo *) NULL);
8326           if (attribute_flag[0] != 0)
8327             {
8328               char
8329                 *text;
8330
8331               text=InterpretImageProperties(info ? info->image_info :
8332                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8333                 exception);
8334               (void) CloneString(&draw_info->text,text);
8335               text=DestroyString(text);
8336             }
8337           if (attribute_flag[1] != 0)
8338             (void) CloneString(&draw_info->font,
8339               argument_list[1].string_reference);
8340           if (attribute_flag[2] != 0)
8341             draw_info->pointsize=argument_list[2].real_reference;
8342           if (attribute_flag[3] != 0)
8343             (void) CloneString(&draw_info->density,
8344               argument_list[3].string_reference);
8345           if (attribute_flag[4] != 0)
8346             (void) QueryColorCompliance(argument_list[4].string_reference,
8347               AllCompliance,&draw_info->undercolor,exception);
8348           if (attribute_flag[5] != 0)
8349             {
8350               (void) QueryColorCompliance(argument_list[5].string_reference,
8351                 AllCompliance,&draw_info->stroke,exception);
8352               if (argument_list[5].image_reference != (Image *) NULL)
8353                 draw_info->stroke_pattern=CloneImage(
8354                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8355             }
8356           if (attribute_flag[6] != 0)
8357             {
8358               (void) QueryColorCompliance(argument_list[6].string_reference,
8359                 AllCompliance,&draw_info->fill,exception);
8360               if (argument_list[6].image_reference != (Image *) NULL)
8361                 draw_info->fill_pattern=CloneImage(
8362                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8363             }
8364           if (attribute_flag[7] != 0)
8365             {
8366               (void) CloneString(&draw_info->geometry,
8367                 argument_list[7].string_reference);
8368               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8369                 &geometry,exception);
8370               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8371                 geometry_info.sigma=geometry_info.xi;
8372             }
8373           if (attribute_flag[8] != 0)
8374             (void) QueryColorCompliance(argument_list[8].string_reference,
8375               AllCompliance,&draw_info->fill,exception);
8376           if (attribute_flag[11] != 0)
8377             draw_info->gravity=(GravityType)
8378               argument_list[11].integer_reference;
8379           if (attribute_flag[25] != 0)
8380             {
8381               AV
8382                 *av;
8383
8384               av=(AV *) argument_list[25].array_reference;
8385               if ((av_len(av) != 3) && (av_len(av) != 5))
8386                 {
8387                   ThrowPerlException(exception,OptionError,
8388                     "affine matrix must have 4 or 6 elements",PackageName);
8389                   goto PerlException;
8390                 }
8391               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8392               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8393               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8394               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8395               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8396                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8397                 {
8398                   ThrowPerlException(exception,OptionError,
8399                     "affine matrix is singular",PackageName);
8400                    goto PerlException;
8401                 }
8402               if (av_len(av) == 5)
8403                 {
8404                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8405                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8406                 }
8407             }
8408           for (j=12; j < 17; j++)
8409           {
8410             if (attribute_flag[j] == 0)
8411               continue;
8412             value=argument_list[j].string_reference;
8413             angle=argument_list[j].real_reference;
8414             current=draw_info->affine;
8415             GetAffineMatrix(&affine);
8416             switch (j)
8417             {
8418               case 12:
8419               {
8420                 /*
8421                   Translate.
8422                 */
8423                 flags=ParseGeometry(value,&geometry_info);
8424                 affine.tx=geometry_info.xi;
8425                 affine.ty=geometry_info.psi;
8426                 if ((flags & PsiValue) == 0)
8427                   affine.ty=affine.tx;
8428                 break;
8429               }
8430               case 13:
8431               {
8432                 /*
8433                   Scale.
8434                 */
8435                 flags=ParseGeometry(value,&geometry_info);
8436                 affine.sx=geometry_info.rho;
8437                 affine.sy=geometry_info.sigma;
8438                 if ((flags & SigmaValue) == 0)
8439                   affine.sy=affine.sx;
8440                 break;
8441               }
8442               case 14:
8443               {
8444                 /*
8445                   Rotate.
8446                 */
8447                 if (angle == 0.0)
8448                   break;
8449                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8450                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8451                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8452                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8453                 break;
8454               }
8455               case 15:
8456               {
8457                 /*
8458                   SkewX.
8459                 */
8460                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8461                 break;
8462               }
8463               case 16:
8464               {
8465                 /*
8466                   SkewY.
8467                 */
8468                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8469                 break;
8470               }
8471             }
8472             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8473             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8474             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8475             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8476             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8477               current.tx;
8478             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8479               current.ty;
8480           }
8481           if (attribute_flag[9] == 0)
8482             argument_list[9].real_reference=0.0;
8483           if (attribute_flag[10] == 0)
8484             argument_list[10].real_reference=0.0;
8485           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8486             {
8487               char
8488                 geometry[MagickPathExtent];
8489
8490               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8491                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8492                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8493               (void) CloneString(&draw_info->geometry,geometry);
8494             }
8495           if (attribute_flag[17] != 0)
8496             draw_info->stroke_width=argument_list[17].real_reference;
8497           if (attribute_flag[18] != 0)
8498             {
8499               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8500                 MagickTrue : MagickFalse;
8501               draw_info->stroke_antialias=draw_info->text_antialias;
8502             }
8503           if (attribute_flag[19] != 0)
8504             (void) CloneString(&draw_info->family,
8505               argument_list[19].string_reference);
8506           if (attribute_flag[20] != 0)
8507             draw_info->style=(StyleType) argument_list[20].integer_reference;
8508           if (attribute_flag[21] != 0)
8509             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8510           if (attribute_flag[22] != 0)
8511             draw_info->weight=argument_list[22].integer_reference;
8512           if (attribute_flag[23] != 0)
8513             draw_info->align=(AlignType) argument_list[23].integer_reference;
8514           if (attribute_flag[24] != 0)
8515             (void) CloneString(&draw_info->encoding,
8516               argument_list[24].string_reference);
8517           if (attribute_flag[25] != 0)
8518             draw_info->fill_pattern=CloneImage(
8519               argument_list[25].image_reference,0,0,MagickTrue,exception);
8520           if (attribute_flag[26] != 0)
8521             draw_info->fill_pattern=CloneImage(
8522               argument_list[26].image_reference,0,0,MagickTrue,exception);
8523           if (attribute_flag[27] != 0)
8524             draw_info->stroke_pattern=CloneImage(
8525               argument_list[27].image_reference,0,0,MagickTrue,exception);
8526           if (attribute_flag[29] != 0)
8527             draw_info->kerning=argument_list[29].real_reference;
8528           if (attribute_flag[30] != 0)
8529             draw_info->interline_spacing=argument_list[30].real_reference;
8530           if (attribute_flag[31] != 0)
8531             draw_info->interword_spacing=argument_list[31].real_reference;
8532           if (attribute_flag[32] != 0)
8533             draw_info->direction=(DirectionType)
8534               argument_list[32].integer_reference;
8535           (void) AnnotateImage(image,draw_info,exception);
8536           draw_info=DestroyDrawInfo(draw_info);
8537           break;
8538         }
8539         case 34:  /* ColorFloodfill */
8540         {
8541           DrawInfo
8542             *draw_info;
8543
8544           MagickBooleanType
8545             invert;
8546
8547           PixelInfo
8548             target;
8549
8550           draw_info=CloneDrawInfo(info ? info->image_info :
8551             (ImageInfo *) NULL,(DrawInfo *) NULL);
8552           if (attribute_flag[0] != 0)
8553             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8554               &geometry,exception);
8555           if (attribute_flag[1] != 0)
8556             geometry.x=argument_list[1].integer_reference;
8557           if (attribute_flag[2] != 0)
8558             geometry.y=argument_list[2].integer_reference;
8559           if (attribute_flag[3] != 0)
8560             (void) QueryColorCompliance(argument_list[3].string_reference,
8561               AllCompliance,&draw_info->fill,exception);
8562           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8563             geometry.x,geometry.y,&target,exception);
8564           invert=MagickFalse;
8565           if (attribute_flag[4] != 0)
8566             {
8567               QueryColorCompliance(argument_list[4].string_reference,
8568                 AllCompliance,&target,exception);
8569               invert=MagickTrue;
8570             }
8571           if (attribute_flag[5] != 0)
8572             image->fuzz=StringToDoubleInterval(
8573               argument_list[5].string_reference,(double) QuantumRange+1.0);
8574           if (attribute_flag[6] != 0)
8575             invert=(MagickBooleanType) argument_list[6].integer_reference;
8576           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8577             geometry.y,invert,exception);
8578           draw_info=DestroyDrawInfo(draw_info);
8579           break;
8580         }
8581         case 35:  /* Composite */
8582         {
8583           char
8584             composite_geometry[MagickPathExtent];
8585
8586           Image
8587             *composite_image,
8588             *rotate_image;
8589
8590           MagickBooleanType
8591             clip_to_self;
8592
8593           compose=OverCompositeOp;
8594           if (attribute_flag[0] != 0)
8595             composite_image=argument_list[0].image_reference;
8596           else
8597             {
8598               ThrowPerlException(exception,OptionError,
8599                 "CompositeImageRequired",PackageName);
8600               goto PerlException;
8601             }
8602           /*
8603             Parameter Handling used for BOTH normal and tiled composition.
8604           */
8605           if (attribute_flag[1] != 0) /* compose */
8606             compose=(CompositeOperator) argument_list[1].integer_reference;
8607           if (attribute_flag[6] != 0) /* opacity  */
8608             {
8609               if (compose != DissolveCompositeOp)
8610                 (void) SetImageAlpha(composite_image,(Quantum)
8611                   StringToDoubleInterval(argument_list[6].string_reference,
8612                   (double) QuantumRange+1.0),exception);
8613               else
8614                 {
8615                   CacheView
8616                     *composite_view;
8617
8618                   double
8619                     opacity;
8620
8621                   MagickBooleanType
8622                     sync;
8623
8624                   register ssize_t
8625                     x;
8626
8627                   register Quantum
8628                     *q;
8629
8630                   ssize_t
8631                     y;
8632
8633                   /*
8634                     Handle dissolve composite operator (patch by
8635                     Kevin A. McGrail).
8636                   */
8637                   (void) CloneString(&image->geometry,
8638                     argument_list[6].string_reference);
8639                   opacity=(Quantum) StringToDoubleInterval(
8640                     argument_list[6].string_reference,(double) QuantumRange+
8641                     1.0);
8642                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8643                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8644                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8645                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8646                   {
8647                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8648                       composite_image->columns,1,exception);
8649                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8650                     {
8651                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8652                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8653                           q);
8654                       q+=GetPixelChannels(composite_image);
8655                     }
8656                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8657                     if (sync == MagickFalse)
8658                       break;
8659                   }
8660                   composite_view=DestroyCacheView(composite_view);
8661                 }
8662             }
8663           if (attribute_flag[9] != 0)    /* "color=>" */
8664             QueryColorCompliance(argument_list[9].string_reference,
8665               AllCompliance,&composite_image->background_color,exception);
8666           if (attribute_flag[12] != 0) /* "interpolate=>" */
8667             image->interpolate=(PixelInterpolateMethod)
8668               argument_list[12].integer_reference;
8669           if (attribute_flag[13] != 0)   /* "args=>" */
8670             (void) SetImageArtifact(composite_image,"compose:args",
8671               argument_list[13].string_reference);
8672           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8673             (void) SetImageArtifact(composite_image,"compose:args",
8674               argument_list[14].string_reference);
8675           clip_to_self=MagickTrue;
8676           if (attribute_flag[15] != 0)
8677             clip_to_self=(MagickBooleanType)
8678               argument_list[15].integer_reference;
8679           /*
8680             Tiling Composition (with orthogonal rotate).
8681           */
8682           rotate_image=(Image *) NULL;
8683           if (attribute_flag[8] != 0)   /* "rotate=>" */
8684             {
8685                /*
8686                  Rotate image.
8687                */
8688                rotate_image=RotateImage(composite_image,
8689                  argument_list[8].real_reference,exception);
8690                if (rotate_image == (Image *) NULL)
8691                  break;
8692             }
8693           if ((attribute_flag[7] != 0) &&
8694               (argument_list[7].integer_reference != 0)) /* tile */
8695             {
8696               ssize_t
8697                 x,
8698                 y;
8699
8700               /*
8701                 Tile the composite image.
8702               */
8703              if (attribute_flag[8] != 0)   /* "tile=>" */
8704                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8705                  "false");
8706              else
8707                (void) SetImageArtifact(composite_image,
8708                  "compose:outside-overlay","false");
8709              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8710                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8711                 {
8712                   if (attribute_flag[8] != 0) /* rotate */
8713                     (void) CompositeImage(image,rotate_image,compose,
8714                       MagickTrue,x,y,exception);
8715                   else
8716                     (void) CompositeImage(image,composite_image,compose,
8717                       MagickTrue,x,y,exception);
8718                 }
8719               if (attribute_flag[8] != 0) /* rotate */
8720                 rotate_image=DestroyImage(rotate_image);
8721               break;
8722             }
8723           /*
8724             Parameter Handling used used ONLY for normal composition.
8725           */
8726           if (attribute_flag[5] != 0) /* gravity */
8727             image->gravity=(GravityType) argument_list[5].integer_reference;
8728           if (attribute_flag[2] != 0) /* geometry offset */
8729             {
8730               SetGeometry(image,&geometry);
8731               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8732                 &geometry);
8733               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8734                 &geometry);
8735             }
8736           if (attribute_flag[3] != 0) /* x offset */
8737             geometry.x=argument_list[3].integer_reference;
8738           if (attribute_flag[4] != 0) /* y offset */
8739             geometry.y=argument_list[4].integer_reference;
8740           if (attribute_flag[10] != 0) /* mask */
8741             {
8742               if ((image->compose == DisplaceCompositeOp) ||
8743                   (image->compose == DistortCompositeOp))
8744                 {
8745                   /*
8746                     Merge Y displacement into X displacement image.
8747                   */
8748                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8749                     exception);
8750                   (void) CompositeImage(composite_image,
8751                     argument_list[10].image_reference,CopyGreenCompositeOp,
8752                     MagickTrue,0,0,exception);
8753                 }
8754               else
8755                 {
8756                   Image
8757                     *mask_image;
8758
8759                   /*
8760                     Set a blending mask for the composition.
8761                   */
8762                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8763                     MagickTrue,exception);
8764                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8765                     exception);
8766                   mask_image=DestroyImage(mask_image);
8767                 }
8768             }
8769           if (attribute_flag[11] != 0) /* channel */
8770             channel=(ChannelType) argument_list[11].integer_reference;
8771           /*
8772             Composite two images (normal composition).
8773           */
8774           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8775             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8776             (double) composite_image->rows,(double) geometry.x,(double)
8777             geometry.y);
8778           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8779             exception);
8780           channel_mask=SetImageChannelMask(image,channel);
8781           if (attribute_flag[8] == 0) /* no rotate */
8782             CompositeImage(image,composite_image,compose,clip_to_self,
8783               geometry.x,geometry.y,exception);
8784           else
8785             {
8786               /*
8787                 Position adjust rotated image then composite.
8788               */
8789               geometry.x-=(ssize_t) (rotate_image->columns-
8790                 composite_image->columns)/2;
8791               geometry.y-=(ssize_t) (rotate_image->rows-
8792                 composite_image->rows)/2;
8793               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8794                 geometry.y,exception);
8795               rotate_image=DestroyImage(rotate_image);
8796             }
8797           if (attribute_flag[10] != 0) /* mask */
8798             {
8799               if ((image->compose == DisplaceCompositeOp) ||
8800                   (image->compose == DistortCompositeOp))
8801                 composite_image=DestroyImage(composite_image);
8802               else
8803                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8804                   exception);
8805             }
8806           (void) SetImageChannelMask(image,channel_mask);
8807           break;
8808         }
8809         case 36:  /* Contrast */
8810         {
8811           if (attribute_flag[0] == 0)
8812             argument_list[0].integer_reference=0;
8813           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8814             MagickTrue : MagickFalse,exception);
8815           break;
8816         }
8817         case 37:  /* CycleColormap */
8818         {
8819           if (attribute_flag[0] == 0)
8820             argument_list[0].integer_reference=6;
8821           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8822             exception);
8823           break;
8824         }
8825         case 38:  /* Draw */
8826         {
8827           DrawInfo
8828             *draw_info;
8829
8830           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8831             (DrawInfo *) NULL);
8832           (void) CloneString(&draw_info->primitive,"point");
8833           if (attribute_flag[0] != 0)
8834             {
8835               if (argument_list[0].integer_reference < 0)
8836                 (void) CloneString(&draw_info->primitive,
8837                   argument_list[0].string_reference);
8838               else
8839                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8840                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8841             }
8842           if (attribute_flag[1] != 0)
8843             {
8844               if (LocaleCompare(draw_info->primitive,"path") == 0)
8845                 {
8846                   (void) ConcatenateString(&draw_info->primitive," '");
8847                   ConcatenateString(&draw_info->primitive,
8848                     argument_list[1].string_reference);
8849                   (void) ConcatenateString(&draw_info->primitive,"'");
8850                 }
8851               else
8852                 {
8853                   (void) ConcatenateString(&draw_info->primitive," ");
8854                   ConcatenateString(&draw_info->primitive,
8855                     argument_list[1].string_reference);
8856                 }
8857             }
8858           if (attribute_flag[2] != 0)
8859             {
8860               (void) ConcatenateString(&draw_info->primitive," ");
8861               (void) ConcatenateString(&draw_info->primitive,
8862                 CommandOptionToMnemonic(MagickMethodOptions,
8863                 argument_list[2].integer_reference));
8864             }
8865           if (attribute_flag[3] != 0)
8866             {
8867               (void) QueryColorCompliance(argument_list[3].string_reference,
8868                 AllCompliance,&draw_info->stroke,exception);
8869               if (argument_list[3].image_reference != (Image *) NULL)
8870                 draw_info->stroke_pattern=CloneImage(
8871                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8872             }
8873           if (attribute_flag[4] != 0)
8874             {
8875               (void) QueryColorCompliance(argument_list[4].string_reference,
8876                 AllCompliance,&draw_info->fill,exception);
8877               if (argument_list[4].image_reference != (Image *) NULL)
8878                 draw_info->fill_pattern=CloneImage(
8879                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8880             }
8881           if (attribute_flag[5] != 0)
8882             draw_info->stroke_width=argument_list[5].real_reference;
8883           if (attribute_flag[6] != 0)
8884             (void) CloneString(&draw_info->font,
8885               argument_list[6].string_reference);
8886           if (attribute_flag[7] != 0)
8887             (void) QueryColorCompliance(argument_list[7].string_reference,
8888               AllCompliance,&draw_info->border_color,exception);
8889           if (attribute_flag[8] != 0)
8890             draw_info->affine.tx=argument_list[8].real_reference;
8891           if (attribute_flag[9] != 0)
8892             draw_info->affine.ty=argument_list[9].real_reference;
8893           if (attribute_flag[20] != 0)
8894             {
8895               AV
8896                 *av;
8897
8898               av=(AV *) argument_list[20].array_reference;
8899               if ((av_len(av) != 3) && (av_len(av) != 5))
8900                 {
8901                   ThrowPerlException(exception,OptionError,
8902                     "affine matrix must have 4 or 6 elements",PackageName);
8903                   goto PerlException;
8904                 }
8905               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8906               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8907               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8908               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8909               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8910                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8911                 {
8912                   ThrowPerlException(exception,OptionError,
8913                     "affine matrix is singular",PackageName);
8914                    goto PerlException;
8915                 }
8916               if (av_len(av) == 5)
8917                 {
8918                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8919                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8920                 }
8921             }
8922           for (j=10; j < 15; j++)
8923           {
8924             if (attribute_flag[j] == 0)
8925               continue;
8926             value=argument_list[j].string_reference;
8927             angle=argument_list[j].real_reference;
8928             current=draw_info->affine;
8929             GetAffineMatrix(&affine);
8930             switch (j)
8931             {
8932               case 10:
8933               {
8934                 /*
8935                   Translate.
8936                 */
8937                 flags=ParseGeometry(value,&geometry_info);
8938                 affine.tx=geometry_info.xi;
8939                 affine.ty=geometry_info.psi;
8940                 if ((flags & PsiValue) == 0)
8941                   affine.ty=affine.tx;
8942                 break;
8943               }
8944               case 11:
8945               {
8946                 /*
8947                   Scale.
8948                 */
8949                 flags=ParseGeometry(value,&geometry_info);
8950                 affine.sx=geometry_info.rho;
8951                 affine.sy=geometry_info.sigma;
8952                 if ((flags & SigmaValue) == 0)
8953                   affine.sy=affine.sx;
8954                 break;
8955               }
8956               case 12:
8957               {
8958                 /*
8959                   Rotate.
8960                 */
8961                 if (angle == 0.0)
8962                   break;
8963                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8964                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8965                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8966                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8967                 break;
8968               }
8969               case 13:
8970               {
8971                 /*
8972                   SkewX.
8973                 */
8974                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8975                 break;
8976               }
8977               case 14:
8978               {
8979                 /*
8980                   SkewY.
8981                 */
8982                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8983                 break;
8984               }
8985             }
8986             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8987             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8988             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8989             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8990             draw_info->affine.tx=
8991               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8992             draw_info->affine.ty=
8993               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8994           }
8995           if (attribute_flag[15] != 0)
8996             draw_info->fill_pattern=CloneImage(
8997               argument_list[15].image_reference,0,0,MagickTrue,exception);
8998           if (attribute_flag[16] != 0)
8999             draw_info->pointsize=argument_list[16].real_reference;
9000           if (attribute_flag[17] != 0)
9001             {
9002               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9003                 ? MagickTrue : MagickFalse;
9004               draw_info->text_antialias=draw_info->stroke_antialias;
9005             }
9006           if (attribute_flag[18] != 0)
9007             (void) CloneString(&draw_info->density,
9008               argument_list[18].string_reference);
9009           if (attribute_flag[19] != 0)
9010             draw_info->stroke_width=argument_list[19].real_reference;
9011           if (attribute_flag[21] != 0)
9012             draw_info->dash_offset=argument_list[21].real_reference;
9013           if (attribute_flag[22] != 0)
9014             {
9015               AV
9016                 *av;
9017
9018               av=(AV *) argument_list[22].array_reference;
9019               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9020                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9021               if (draw_info->dash_pattern != (double *) NULL)
9022                 {
9023                   for (i=0; i <= av_len(av); i++)
9024                     draw_info->dash_pattern[i]=(double)
9025                       SvNV(*(av_fetch(av,i,0)));
9026                   draw_info->dash_pattern[i]=0.0;
9027                 }
9028             }
9029           if (attribute_flag[23] != 0)
9030             image->interpolate=(PixelInterpolateMethod)
9031               argument_list[23].integer_reference;
9032           if ((attribute_flag[24] != 0) &&
9033               (draw_info->fill_pattern != (Image *) NULL))
9034             flags=ParsePageGeometry(draw_info->fill_pattern,
9035               argument_list[24].string_reference,
9036               &draw_info->fill_pattern->tile_offset,exception);
9037           if (attribute_flag[25] != 0)
9038             {
9039               (void) ConcatenateString(&draw_info->primitive," '");
9040               (void) ConcatenateString(&draw_info->primitive,
9041                 argument_list[25].string_reference);
9042               (void) ConcatenateString(&draw_info->primitive,"'");
9043             }
9044           if (attribute_flag[26] != 0)
9045             draw_info->fill_pattern=CloneImage(
9046               argument_list[26].image_reference,0,0,MagickTrue,exception);
9047           if (attribute_flag[27] != 0)
9048             draw_info->stroke_pattern=CloneImage(
9049               argument_list[27].image_reference,0,0,MagickTrue,exception);
9050           if (attribute_flag[28] != 0)
9051             (void) CloneString(&draw_info->primitive,
9052               argument_list[28].string_reference);
9053           if (attribute_flag[29] != 0)
9054             draw_info->kerning=argument_list[29].real_reference;
9055           if (attribute_flag[30] != 0)
9056             draw_info->interline_spacing=argument_list[30].real_reference;
9057           if (attribute_flag[31] != 0)
9058             draw_info->interword_spacing=argument_list[31].real_reference;
9059           if (attribute_flag[32] != 0)
9060             draw_info->direction=(DirectionType)
9061               argument_list[32].integer_reference;
9062           DrawImage(image,draw_info,exception);
9063           draw_info=DestroyDrawInfo(draw_info);
9064           break;
9065         }
9066         case 39:  /* Equalize */
9067         {
9068           if (attribute_flag[0] != 0)
9069             channel=(ChannelType) argument_list[0].integer_reference;
9070           channel_mask=SetImageChannelMask(image,channel);
9071           EqualizeImage(image,exception);
9072           (void) SetImageChannelMask(image,channel_mask);
9073           break;
9074         }
9075         case 40:  /* Gamma */
9076         {
9077           if (attribute_flag[1] != 0)
9078             channel=(ChannelType) argument_list[1].integer_reference;
9079           if (attribute_flag[2] == 0)
9080             argument_list[2].real_reference=1.0;
9081           if (attribute_flag[3] == 0)
9082             argument_list[3].real_reference=1.0;
9083           if (attribute_flag[4] == 0)
9084             argument_list[4].real_reference=1.0;
9085           if (attribute_flag[0] == 0)
9086             {
9087               (void) FormatLocaleString(message,MagickPathExtent,
9088                 "%.20g,%.20g,%.20g",(double) argument_list[2].real_reference,
9089                 (double) argument_list[3].real_reference,
9090                 (double) argument_list[4].real_reference);
9091               argument_list[0].string_reference=message;
9092             }
9093           (void) GammaImage(image,StringToDouble(
9094             argument_list[0].string_reference,(char **) NULL),exception);
9095           break;
9096         }
9097         case 41:  /* Map */
9098         {
9099           QuantizeInfo
9100             *quantize_info;
9101
9102           if (attribute_flag[0] == 0)
9103             {
9104               ThrowPerlException(exception,OptionError,"MapImageRequired",
9105                 PackageName);
9106               goto PerlException;
9107             }
9108           quantize_info=AcquireQuantizeInfo(info->image_info);
9109           if (attribute_flag[1] != 0)
9110             quantize_info->dither_method=(DitherMethod)
9111               argument_list[1].integer_reference;
9112           (void) RemapImages(quantize_info,image,
9113             argument_list[0].image_reference,exception);
9114           quantize_info=DestroyQuantizeInfo(quantize_info);
9115           break;
9116         }
9117         case 42:  /* MatteFloodfill */
9118         {
9119           DrawInfo
9120             *draw_info;
9121
9122           MagickBooleanType
9123             invert;
9124
9125           PixelInfo
9126             target;
9127
9128           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9129             (DrawInfo *) NULL);
9130           if (attribute_flag[0] != 0)
9131             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9132               &geometry,exception);
9133           if (attribute_flag[1] != 0)
9134             geometry.x=argument_list[1].integer_reference;
9135           if (attribute_flag[2] != 0)
9136             geometry.y=argument_list[2].integer_reference;
9137           if (image->alpha_trait == UndefinedPixelTrait)
9138             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9139           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9140             geometry.x,geometry.y,&target,exception);
9141           if (attribute_flag[4] != 0)
9142             QueryColorCompliance(argument_list[4].string_reference,
9143               AllCompliance,&target,exception);
9144           if (attribute_flag[3] != 0)
9145             target.alpha=StringToDoubleInterval(
9146               argument_list[3].string_reference,(double) (double) QuantumRange+
9147               1.0);
9148           if (attribute_flag[5] != 0)
9149             image->fuzz=StringToDoubleInterval(
9150               argument_list[5].string_reference,(double) QuantumRange+1.0);
9151           invert=MagickFalse;
9152           if (attribute_flag[6] != 0)
9153             invert=(MagickBooleanType) argument_list[6].integer_reference;
9154           channel_mask=SetImageChannelMask(image,AlphaChannel);
9155           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9156             geometry.y,invert,exception);
9157           (void) SetImageChannelMask(image,channel_mask);
9158           draw_info=DestroyDrawInfo(draw_info);
9159           break;
9160         }
9161         case 43:  /* Modulate */
9162         {
9163           char
9164             modulate[MagickPathExtent];
9165
9166           geometry_info.rho=100.0;
9167           geometry_info.sigma=100.0;
9168           geometry_info.xi=100.0;
9169           if (attribute_flag[0] != 0)
9170             (void)ParseGeometry(argument_list[0].string_reference,
9171               &geometry_info);
9172           if (attribute_flag[1] != 0)
9173             geometry_info.xi=argument_list[1].real_reference;
9174           if (attribute_flag[2] != 0)
9175             geometry_info.sigma=argument_list[2].real_reference;
9176           if (attribute_flag[3] != 0)
9177             {
9178               geometry_info.sigma=argument_list[3].real_reference;
9179               SetImageArtifact(image,"modulate:colorspace","HWB");
9180             }
9181           if (attribute_flag[4] != 0)
9182             {
9183               geometry_info.rho=argument_list[4].real_reference;
9184               SetImageArtifact(image,"modulate:colorspace","HSB");
9185             }
9186           if (attribute_flag[5] != 0)
9187             {
9188               geometry_info.sigma=argument_list[5].real_reference;
9189               SetImageArtifact(image,"modulate:colorspace","HSL");
9190             }
9191           if (attribute_flag[6] != 0)
9192             {
9193               geometry_info.rho=argument_list[6].real_reference;
9194               SetImageArtifact(image,"modulate:colorspace","HWB");
9195             }
9196           (void) FormatLocaleString(modulate,MagickPathExtent,"%.20g,%.20g,%.20g",
9197             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9198           (void) ModulateImage(image,modulate,exception);
9199           break;
9200         }
9201         case 44:  /* Negate */
9202         {
9203           if (attribute_flag[0] == 0)
9204             argument_list[0].integer_reference=0;
9205           if (attribute_flag[1] != 0)
9206             channel=(ChannelType) argument_list[1].integer_reference;
9207           channel_mask=SetImageChannelMask(image,channel);
9208           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9209             MagickTrue : MagickFalse,exception);
9210           (void) SetImageChannelMask(image,channel_mask);
9211           break;
9212         }
9213         case 45:  /* Normalize */
9214         {
9215           if (attribute_flag[0] != 0)
9216             channel=(ChannelType) argument_list[0].integer_reference;
9217           channel_mask=SetImageChannelMask(image,channel);
9218           NormalizeImage(image,exception);
9219           (void) SetImageChannelMask(image,channel_mask);
9220           break;
9221         }
9222         case 46:  /* NumberColors */
9223           break;
9224         case 47:  /* Opaque */
9225         {
9226           MagickBooleanType
9227             invert;
9228
9229           PixelInfo
9230             fill_color,
9231             target;
9232
9233           (void) QueryColorCompliance("none",AllCompliance,&target,
9234              exception);
9235           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9236             exception);
9237           if (attribute_flag[0] != 0)
9238             (void) QueryColorCompliance(argument_list[0].string_reference,
9239               AllCompliance,&target,exception);
9240           if (attribute_flag[1] != 0)
9241             (void) QueryColorCompliance(argument_list[1].string_reference,
9242               AllCompliance,&fill_color,exception);
9243           if (attribute_flag[2] != 0)
9244             image->fuzz=StringToDoubleInterval(
9245               argument_list[2].string_reference,(double) QuantumRange+1.0);
9246           if (attribute_flag[3] != 0)
9247             channel=(ChannelType) argument_list[3].integer_reference;
9248           invert=MagickFalse;
9249           if (attribute_flag[4] != 0)
9250             invert=(MagickBooleanType) argument_list[4].integer_reference;
9251           channel_mask=SetImageChannelMask(image,channel);
9252           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9253           (void) SetImageChannelMask(image,channel_mask);
9254           break;
9255         }
9256         case 48:  /* Quantize */
9257         {
9258           QuantizeInfo
9259             *quantize_info;
9260
9261           quantize_info=AcquireQuantizeInfo(info->image_info);
9262           if (attribute_flag[0] != 0)
9263             quantize_info->number_colors=(size_t)
9264               argument_list[0].integer_reference;
9265           if (attribute_flag[1] != 0)
9266             quantize_info->tree_depth=(size_t)
9267               argument_list[1].integer_reference;
9268           if (attribute_flag[2] != 0)
9269             quantize_info->colorspace=(ColorspaceType)
9270               argument_list[2].integer_reference;
9271           if (attribute_flag[3] != 0)
9272             quantize_info->dither_method=(DitherMethod)
9273               argument_list[3].integer_reference;
9274           if (attribute_flag[4] != 0)
9275             quantize_info->measure_error=
9276               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9277           if (attribute_flag[6] != 0)
9278             (void) QueryColorCompliance(argument_list[6].string_reference,
9279               AllCompliance,&image->transparent_color,exception);
9280           if (attribute_flag[7] != 0)
9281             quantize_info->dither_method=(DitherMethod)
9282               argument_list[7].integer_reference;
9283           if (attribute_flag[5] && argument_list[5].integer_reference)
9284             (void) QuantizeImages(quantize_info,image,exception);
9285           else
9286             if ((image->storage_class == DirectClass) ||
9287                (image->colors > quantize_info->number_colors) ||
9288                (quantize_info->colorspace == GRAYColorspace))
9289              (void) QuantizeImage(quantize_info,image,exception);
9290            else
9291              CompressImageColormap(image,exception);
9292           quantize_info=DestroyQuantizeInfo(quantize_info);
9293           break;
9294         }
9295         case 49:  /* Raise */
9296         {
9297           if (attribute_flag[0] != 0)
9298             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9299               &geometry,exception);
9300           if (attribute_flag[1] != 0)
9301             geometry.width=argument_list[1].integer_reference;
9302           if (attribute_flag[2] != 0)
9303             geometry.height=argument_list[2].integer_reference;
9304           if (attribute_flag[3] == 0)
9305             argument_list[3].integer_reference=1;
9306           (void) RaiseImage(image,&geometry,
9307             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9308             exception);
9309           break;
9310         }
9311         case 50:  /* Segment */
9312         {
9313           ColorspaceType
9314             colorspace;
9315
9316           double
9317             cluster_threshold,
9318             smoothing_threshold;
9319
9320           MagickBooleanType
9321             verbose;
9322
9323           cluster_threshold=1.0;
9324           smoothing_threshold=1.5;
9325           colorspace=sRGBColorspace;
9326           verbose=MagickFalse;
9327           if (attribute_flag[0] != 0)
9328             {
9329               flags=ParseGeometry(argument_list[0].string_reference,
9330                 &geometry_info);
9331               cluster_threshold=geometry_info.rho;
9332               if (flags & SigmaValue)
9333                 smoothing_threshold=geometry_info.sigma;
9334             }
9335           if (attribute_flag[1] != 0)
9336             cluster_threshold=argument_list[1].real_reference;
9337           if (attribute_flag[2] != 0)
9338             smoothing_threshold=argument_list[2].real_reference;
9339           if (attribute_flag[3] != 0)
9340             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9341           if (attribute_flag[4] != 0)
9342             verbose=argument_list[4].integer_reference != 0 ?
9343               MagickTrue : MagickFalse;
9344           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9345             smoothing_threshold,exception);
9346           break;
9347         }
9348         case 51:  /* Signature */
9349         {
9350           (void) SignatureImage(image,exception);
9351           break;
9352         }
9353         case 52:  /* Solarize */
9354         {
9355           geometry_info.rho=QuantumRange/2.0;
9356           if (attribute_flag[0] != 0)
9357             flags=ParseGeometry(argument_list[0].string_reference,
9358               &geometry_info);
9359           if (attribute_flag[1] != 0)
9360             geometry_info.rho=StringToDoubleInterval(
9361               argument_list[1].string_reference,(double) QuantumRange+1.0);
9362           (void) SolarizeImage(image,geometry_info.rho,exception);
9363           break;
9364         }
9365         case 53:  /* Sync */
9366         {
9367           (void) SyncImage(image,exception);
9368           break;
9369         }
9370         case 54:  /* Texture */
9371         {
9372           if (attribute_flag[0] == 0)
9373             break;
9374           TextureImage(image,argument_list[0].image_reference,exception);
9375           break;
9376         }
9377         case 55:  /* Evalute */
9378         {
9379           MagickEvaluateOperator
9380             op;
9381
9382           op=SetEvaluateOperator;
9383           if (attribute_flag[0] == MagickFalse)
9384             argument_list[0].real_reference=0.0;
9385           if (attribute_flag[1] != MagickFalse)
9386             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9387           if (attribute_flag[2] != MagickFalse)
9388             channel=(ChannelType) argument_list[2].integer_reference;
9389           channel_mask=SetImageChannelMask(image,channel);
9390           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9391             exception);
9392           (void) SetImageChannelMask(image,channel_mask);
9393           break;
9394         }
9395         case 56:  /* Transparent */
9396         {
9397           double
9398             opacity;
9399
9400           MagickBooleanType
9401             invert;
9402
9403           PixelInfo
9404             target;
9405
9406           (void) QueryColorCompliance("none",AllCompliance,&target,
9407             exception);
9408           if (attribute_flag[0] != 0)
9409             (void) QueryColorCompliance(argument_list[0].string_reference,
9410               AllCompliance,&target,exception);
9411           opacity=TransparentAlpha;
9412           if (attribute_flag[1] != 0)
9413             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9414               (double) QuantumRange+1.0);
9415           if (attribute_flag[2] != 0)
9416             image->fuzz=StringToDoubleInterval(
9417               argument_list[2].string_reference,(double) QuantumRange+1.0);
9418           if (attribute_flag[3] == 0)
9419             argument_list[3].integer_reference=0;
9420           invert=MagickFalse;
9421           if (attribute_flag[3] != 0)
9422             invert=(MagickBooleanType) argument_list[3].integer_reference;
9423           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9424             invert,exception);
9425           break;
9426         }
9427         case 57:  /* Threshold */
9428         {
9429           double
9430             threshold;
9431
9432           if (attribute_flag[0] == 0)
9433             argument_list[0].string_reference="50%";
9434           if (attribute_flag[1] != 0)
9435             channel=(ChannelType) argument_list[1].integer_reference;
9436           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9437             (double) QuantumRange+1.0);
9438           channel_mask=SetImageChannelMask(image,channel);
9439           (void) BilevelImage(image,threshold,exception);
9440           (void) SetImageChannelMask(image,channel_mask);
9441           break;
9442         }
9443         case 58:  /* Charcoal */
9444         {
9445           if (attribute_flag[0] != 0)
9446             {
9447               flags=ParseGeometry(argument_list[0].string_reference,
9448                 &geometry_info);
9449               if ((flags & SigmaValue) == 0)
9450                 geometry_info.sigma=1.0;
9451             }
9452           if (attribute_flag[1] != 0)
9453             geometry_info.rho=argument_list[1].real_reference;
9454           if (attribute_flag[2] != 0)
9455             geometry_info.sigma=argument_list[2].real_reference;
9456           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9457             exception);
9458           break;
9459         }
9460         case 59:  /* Trim */
9461         {
9462           if (attribute_flag[0] != 0)
9463             image->fuzz=StringToDoubleInterval(
9464               argument_list[0].string_reference,(double) QuantumRange+1.0);
9465           image=TrimImage(image,exception);
9466           break;
9467         }
9468         case 60:  /* Wave */
9469         {
9470           PixelInterpolateMethod
9471             method;
9472
9473           if (attribute_flag[0] != 0)
9474             {
9475               flags=ParseGeometry(argument_list[0].string_reference,
9476                 &geometry_info);
9477               if ((flags & SigmaValue) == 0)
9478                 geometry_info.sigma=1.0;
9479             }
9480           if (attribute_flag[1] != 0)
9481             geometry_info.rho=argument_list[1].real_reference;
9482           if (attribute_flag[2] != 0)
9483             geometry_info.sigma=argument_list[2].real_reference;
9484           method=UndefinedInterpolatePixel;
9485           if (attribute_flag[3] != 0)
9486             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9487           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9488             method,exception);
9489           break;
9490         }
9491         case 61:  /* Separate */
9492         {
9493           if (attribute_flag[0] != 0)
9494             channel=(ChannelType) argument_list[0].integer_reference;
9495           image=SeparateImage(image,channel,exception);
9496           break;
9497         }
9498         case 63:  /* Stereo */
9499         {
9500           if (attribute_flag[0] == 0)
9501             {
9502               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9503                 PackageName);
9504               goto PerlException;
9505             }
9506           if (attribute_flag[1] != 0)
9507             geometry.x=argument_list[1].integer_reference;
9508           if (attribute_flag[2] != 0)
9509             geometry.y=argument_list[2].integer_reference;
9510           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9511             geometry.x,geometry.y,exception);
9512           break;
9513         }
9514         case 64:  /* Stegano */
9515         {
9516           if (attribute_flag[0] == 0)
9517             {
9518               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9519                 PackageName);
9520               goto PerlException;
9521             }
9522           if (attribute_flag[1] == 0)
9523             argument_list[1].integer_reference=0;
9524           image->offset=argument_list[1].integer_reference;
9525           image=SteganoImage(image,argument_list[0].image_reference,exception);
9526           break;
9527         }
9528         case 65:  /* Deconstruct */
9529         {
9530           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9531           break;
9532         }
9533         case 66:  /* GaussianBlur */
9534         {
9535           if (attribute_flag[0] != 0)
9536             {
9537               flags=ParseGeometry(argument_list[0].string_reference,
9538                 &geometry_info);
9539               if ((flags & SigmaValue) == 0)
9540                 geometry_info.sigma=1.0;
9541             }
9542           if (attribute_flag[1] != 0)
9543             geometry_info.rho=argument_list[1].real_reference;
9544           if (attribute_flag[2] != 0)
9545             geometry_info.sigma=argument_list[2].real_reference;
9546           if (attribute_flag[3] != 0)
9547             channel=(ChannelType) argument_list[3].integer_reference;
9548           channel_mask=SetImageChannelMask(image,channel);
9549           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9550             exception);
9551           if (image != (Image *) NULL)
9552             (void) SetImageChannelMask(image,channel_mask);
9553           break;
9554         }
9555         case 67:  /* Convolve */
9556         {
9557           KernelInfo
9558             *kernel;
9559
9560           kernel=(KernelInfo *) NULL;
9561           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9562             break;
9563           if (attribute_flag[0] != 0)
9564             {
9565               AV
9566                 *av;
9567
9568               size_t
9569                 order;
9570
9571               kernel=AcquireKernelInfo((const char *) NULL,exception);
9572               if (kernel == (KernelInfo *) NULL)
9573                 break;
9574               av=(AV *) argument_list[0].array_reference;
9575               order=(size_t) sqrt(av_len(av)+1);
9576               kernel->width=order;
9577               kernel->height=order;
9578               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9579                 order*sizeof(*kernel->values));
9580               if (kernel->values == (MagickRealType *) NULL)
9581                 {
9582                   kernel=DestroyKernelInfo(kernel);
9583                   ThrowPerlException(exception,ResourceLimitFatalError,
9584                     "MemoryAllocationFailed",PackageName);
9585                   goto PerlException;
9586                 }
9587               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9588                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9589               for ( ; j < (ssize_t) (order*order); j++)
9590                 kernel->values[j]=0.0;
9591             }
9592           if (attribute_flag[1] != 0)
9593             channel=(ChannelType) argument_list[1].integer_reference;
9594           if (attribute_flag[2] != 0)
9595             SetImageArtifact(image,"filter:blur",
9596               argument_list[2].string_reference);
9597           if (attribute_flag[3] != 0)
9598             {
9599               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9600                 exception);
9601               if (kernel == (KernelInfo *) NULL)
9602                 break;
9603             }
9604           channel_mask=SetImageChannelMask(image,channel);
9605           image=ConvolveImage(image,kernel,exception);
9606           if (image != (Image *) NULL)
9607             (void) SetImageChannelMask(image,channel_mask);
9608           kernel=DestroyKernelInfo(kernel);
9609           break;
9610         }
9611         case 68:  /* Profile */
9612         {
9613           const char
9614             *name;
9615
9616           Image
9617             *profile_image;
9618
9619           ImageInfo
9620             *profile_info;
9621
9622           StringInfo
9623             *profile;
9624
9625           name="*";
9626           if (attribute_flag[0] != 0)
9627             name=argument_list[0].string_reference;
9628           if (attribute_flag[2] != 0)
9629             image->rendering_intent=(RenderingIntent)
9630               argument_list[2].integer_reference;
9631           if (attribute_flag[3] != 0)
9632             image->black_point_compensation=
9633               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9634           if (attribute_flag[1] != 0)
9635             {
9636               if (argument_list[1].length == 0)
9637                 {
9638                   /*
9639                     Remove a profile from the image.
9640                   */
9641                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9642                     exception);
9643                   break;
9644                 }
9645               /*
9646                 Associate user supplied profile with the image.
9647               */
9648               profile=AcquireStringInfo(argument_list[1].length);
9649               SetStringInfoDatum(profile,(const unsigned char *)
9650                 argument_list[1].string_reference);
9651               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9652                 (size_t) GetStringInfoLength(profile),exception);
9653               profile=DestroyStringInfo(profile);
9654               break;
9655             }
9656           /*
9657             Associate a profile with the image.
9658           */
9659           profile_info=CloneImageInfo(info ? info->image_info :
9660             (ImageInfo *) NULL);
9661           profile_image=ReadImages(profile_info,name,exception);
9662           if (profile_image == (Image *) NULL)
9663             break;
9664           ResetImageProfileIterator(profile_image);
9665           name=GetNextImageProfile(profile_image);
9666           while (name != (const char *) NULL)
9667           {
9668             const StringInfo
9669               *profile;
9670
9671             profile=GetImageProfile(profile_image,name);
9672             if (profile != (const StringInfo *) NULL)
9673               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9674                 (size_t) GetStringInfoLength(profile),exception);
9675             name=GetNextImageProfile(profile_image);
9676           }
9677           profile_image=DestroyImage(profile_image);
9678           profile_info=DestroyImageInfo(profile_info);
9679           break;
9680         }
9681         case 69:  /* UnsharpMask */
9682         {
9683           if (attribute_flag[0] != 0)
9684             {
9685               flags=ParseGeometry(argument_list[0].string_reference,
9686                 &geometry_info);
9687               if ((flags & SigmaValue) == 0)
9688                 geometry_info.sigma=1.0;
9689               if ((flags & XiValue) == 0)
9690                 geometry_info.xi=1.0;
9691               if ((flags & PsiValue) == 0)
9692                 geometry_info.psi=0.5;
9693             }
9694           if (attribute_flag[1] != 0)
9695             geometry_info.rho=argument_list[1].real_reference;
9696           if (attribute_flag[2] != 0)
9697             geometry_info.sigma=argument_list[2].real_reference;
9698           if (attribute_flag[3] != 0)
9699             geometry_info.xi=argument_list[3].real_reference;
9700           if (attribute_flag[4] != 0)
9701             geometry_info.psi=argument_list[4].real_reference;
9702           if (attribute_flag[5] != 0)
9703             channel=(ChannelType) argument_list[5].integer_reference;
9704           channel_mask=SetImageChannelMask(image,channel);
9705           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9706             geometry_info.xi,geometry_info.psi,exception);
9707           if (image != (Image *) NULL)
9708             (void) SetImageChannelMask(image,channel_mask);
9709           break;
9710         }
9711         case 70:  /* MotionBlur */
9712         {
9713           if (attribute_flag[0] != 0)
9714             {
9715               flags=ParseGeometry(argument_list[0].string_reference,
9716                 &geometry_info);
9717               if ((flags & SigmaValue) == 0)
9718                 geometry_info.sigma=1.0;
9719               if ((flags & XiValue) == 0)
9720                 geometry_info.xi=1.0;
9721             }
9722           if (attribute_flag[1] != 0)
9723             geometry_info.rho=argument_list[1].real_reference;
9724           if (attribute_flag[2] != 0)
9725             geometry_info.sigma=argument_list[2].real_reference;
9726           if (attribute_flag[3] != 0)
9727             geometry_info.xi=argument_list[3].real_reference;
9728           if (attribute_flag[4] != 0)
9729             channel=(ChannelType) argument_list[4].integer_reference;
9730           channel_mask=SetImageChannelMask(image,channel);
9731           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9732             geometry_info.xi,exception);
9733           if (image != (Image *) NULL)
9734             (void) SetImageChannelMask(image,channel_mask);
9735           break;
9736         }
9737         case 71:  /* OrderedDither */
9738         {
9739           if (attribute_flag[0] == 0)
9740             argument_list[0].string_reference="o8x8";
9741           if (attribute_flag[1] != 0)
9742             channel=(ChannelType) argument_list[1].integer_reference;
9743           channel_mask=SetImageChannelMask(image,channel);
9744           (void) OrderedDitherImage(image,argument_list[0].string_reference,
9745             exception);
9746           (void) SetImageChannelMask(image,channel_mask);
9747           break;
9748         }
9749         case 72:  /* Shave */
9750         {
9751           if (attribute_flag[0] != 0)
9752             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9753               &geometry,exception);
9754           if (attribute_flag[1] != 0)
9755             geometry.width=argument_list[1].integer_reference;
9756           if (attribute_flag[2] != 0)
9757             geometry.height=argument_list[2].integer_reference;
9758           image=ShaveImage(image,&geometry,exception);
9759           break;
9760         }
9761         case 73:  /* Level */
9762         {
9763           double
9764             black_point,
9765             gamma,
9766             white_point;
9767
9768           black_point=0.0;
9769           white_point=(double) image->columns*image->rows;
9770           gamma=1.0;
9771           if (attribute_flag[0] != 0)
9772             {
9773               flags=ParseGeometry(argument_list[0].string_reference,
9774                 &geometry_info);
9775               black_point=geometry_info.rho;
9776               if ((flags & SigmaValue) != 0)
9777                 white_point=geometry_info.sigma;
9778               if ((flags & XiValue) != 0)
9779                 gamma=geometry_info.xi;
9780               if ((flags & PercentValue) != 0)
9781                 {
9782                   black_point*=(double) (QuantumRange/100.0);
9783                   white_point*=(double) (QuantumRange/100.0);
9784                 }
9785               if ((flags & SigmaValue) == 0)
9786                 white_point=(double) QuantumRange-black_point;
9787             }
9788           if (attribute_flag[1] != 0)
9789             black_point=argument_list[1].real_reference;
9790           if (attribute_flag[2] != 0)
9791             white_point=argument_list[2].real_reference;
9792           if (attribute_flag[3] != 0)
9793             gamma=argument_list[3].real_reference;
9794           if (attribute_flag[4] != 0)
9795             channel=(ChannelType) argument_list[4].integer_reference;
9796           if (attribute_flag[5] != 0)
9797             {
9798               argument_list[0].real_reference=argument_list[5].real_reference;
9799               attribute_flag[0]=attribute_flag[5];
9800             }
9801           channel_mask=SetImageChannelMask(image,channel);
9802           (void) LevelImage(image,black_point,white_point,gamma,exception);
9803           (void) SetImageChannelMask(image,channel_mask);
9804           break;
9805         }
9806         case 74:  /* Clip */
9807         {
9808           if (attribute_flag[0] == 0)
9809             argument_list[0].string_reference="#1";
9810           if (attribute_flag[1] == 0)
9811             argument_list[1].integer_reference=MagickTrue;
9812           (void) ClipImagePath(image,argument_list[0].string_reference,
9813             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9814             exception);
9815           break;
9816         }
9817         case 75:  /* AffineTransform */
9818         {
9819           DrawInfo
9820             *draw_info;
9821
9822           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9823             (DrawInfo *) NULL);
9824           if (attribute_flag[0] != 0)
9825             {
9826               AV
9827                 *av;
9828
9829               av=(AV *) argument_list[0].array_reference;
9830               if ((av_len(av) != 3) && (av_len(av) != 5))
9831                 {
9832                   ThrowPerlException(exception,OptionError,
9833                     "affine matrix must have 4 or 6 elements",PackageName);
9834                   goto PerlException;
9835                 }
9836               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9837               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9838               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9839               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9840               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9841                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9842                 {
9843                   ThrowPerlException(exception,OptionError,
9844                     "affine matrix is singular",PackageName);
9845                    goto PerlException;
9846                 }
9847               if (av_len(av) == 5)
9848                 {
9849                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9850                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9851                 }
9852             }
9853           for (j=1; j < 6; j++)
9854           {
9855             if (attribute_flag[j] == 0)
9856               continue;
9857             value=argument_list[j].string_reference;
9858             angle=argument_list[j].real_reference;
9859             current=draw_info->affine;
9860             GetAffineMatrix(&affine);
9861             switch (j)
9862             {
9863               case 1:
9864               {
9865                 /*
9866                   Translate.
9867                 */
9868                 flags=ParseGeometry(value,&geometry_info);
9869                 affine.tx=geometry_info.xi;
9870                 affine.ty=geometry_info.psi;
9871                 if ((flags & PsiValue) == 0)
9872                   affine.ty=affine.tx;
9873                 break;
9874               }
9875               case 2:
9876               {
9877                 /*
9878                   Scale.
9879                 */
9880                 flags=ParseGeometry(value,&geometry_info);
9881                 affine.sx=geometry_info.rho;
9882                 affine.sy=geometry_info.sigma;
9883                 if ((flags & SigmaValue) == 0)
9884                   affine.sy=affine.sx;
9885                 break;
9886               }
9887               case 3:
9888               {
9889                 /*
9890                   Rotate.
9891                 */
9892                 if (angle == 0.0)
9893                   break;
9894                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9895                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9896                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9897                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9898                 break;
9899               }
9900               case 4:
9901               {
9902                 /*
9903                   SkewX.
9904                 */
9905                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9906                 break;
9907               }
9908               case 5:
9909               {
9910                 /*
9911                   SkewY.
9912                 */
9913                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9914                 break;
9915               }
9916             }
9917             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9918             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9919             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9920             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9921             draw_info->affine.tx=
9922               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9923             draw_info->affine.ty=
9924               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9925           }
9926           if (attribute_flag[6] != 0)
9927             image->interpolate=(PixelInterpolateMethod)
9928               argument_list[6].integer_reference;
9929           if (attribute_flag[7] != 0)
9930             QueryColorCompliance(argument_list[7].string_reference,
9931               AllCompliance,&image->background_color,exception);
9932           image=AffineTransformImage(image,&draw_info->affine,exception);
9933           draw_info=DestroyDrawInfo(draw_info);
9934           break;
9935         }
9936         case 76:  /* Difference */
9937         {
9938           if (attribute_flag[0] == 0)
9939             {
9940               ThrowPerlException(exception,OptionError,
9941                 "ReferenceImageRequired",PackageName);
9942               goto PerlException;
9943             }
9944           if (attribute_flag[1] != 0)
9945             image->fuzz=StringToDoubleInterval(
9946               argument_list[1].string_reference,(double) QuantumRange+1.0);
9947           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9948             exception);
9949           break;
9950         }
9951         case 77:  /* AdaptiveThreshold */
9952         {
9953           if (attribute_flag[0] != 0)
9954             {
9955               flags=ParseGeometry(argument_list[0].string_reference,
9956                 &geometry_info);
9957               if ((flags & PercentValue) != 0)
9958                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9959             }
9960           if (attribute_flag[1] != 0)
9961             geometry_info.rho=argument_list[1].integer_reference;
9962           if (attribute_flag[2] != 0)
9963             geometry_info.sigma=argument_list[2].integer_reference;
9964           if (attribute_flag[3] != 0)
9965             geometry_info.xi=argument_list[3].integer_reference;;
9966           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9967             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9968           break;
9969         }
9970         case 78:  /* Resample */
9971         {
9972           size_t
9973             height,
9974             width;
9975
9976           if (attribute_flag[0] != 0)
9977             {
9978               flags=ParseGeometry(argument_list[0].string_reference,
9979                 &geometry_info);
9980               if ((flags & SigmaValue) == 0)
9981                 geometry_info.sigma=geometry_info.rho;
9982             }
9983           if (attribute_flag[1] != 0)
9984             geometry_info.rho=argument_list[1].real_reference;
9985           if (attribute_flag[2] != 0)
9986             geometry_info.sigma=argument_list[2].real_reference;
9987           if (attribute_flag[3] == 0)
9988             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9989           if (attribute_flag[4] == 0)
9990             SetImageArtifact(image,"filter:support",
9991               argument_list[4].string_reference);
9992           width=(size_t) (geometry_info.rho*image->columns/
9993             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9994           height=(size_t) (geometry_info.sigma*image->rows/
9995             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9996           image=ResizeImage(image,width,height,(FilterType)
9997             argument_list[3].integer_reference,exception);
9998           if (image != (Image *) NULL)
9999             {
10000               image->resolution.x=geometry_info.rho;
10001               image->resolution.y=geometry_info.sigma;
10002             }
10003           break;
10004         }
10005         case 79:  /* Describe */
10006         {
10007           if (attribute_flag[0] == 0)
10008             argument_list[0].file_reference=(FILE *) NULL;
10009           if (attribute_flag[1] != 0)
10010             (void) SetImageArtifact(image,"identify:features",
10011               argument_list[1].string_reference);
10012           (void) IdentifyImage(image,argument_list[0].file_reference,
10013             MagickTrue,exception);
10014           break;
10015         }
10016         case 80:  /* BlackThreshold */
10017         {
10018           if (attribute_flag[0] == 0)
10019             argument_list[0].string_reference="50%";
10020           if (attribute_flag[2] != 0)
10021             channel=(ChannelType) argument_list[2].integer_reference;
10022           channel_mask=SetImageChannelMask(image,channel);
10023           BlackThresholdImage(image,argument_list[0].string_reference,
10024             exception);
10025           (void) SetImageChannelMask(image,channel_mask);
10026           break;
10027         }
10028         case 81:  /* WhiteThreshold */
10029         {
10030           if (attribute_flag[0] == 0)
10031             argument_list[0].string_reference="50%";
10032           if (attribute_flag[2] != 0)
10033             channel=(ChannelType) argument_list[2].integer_reference;
10034           channel_mask=SetImageChannelMask(image,channel);
10035           WhiteThresholdImage(image,argument_list[0].string_reference,
10036             exception);
10037           (void) SetImageChannelMask(image,channel_mask);
10038           break;
10039         }
10040         case 82:  /* RotationalBlur */
10041         {
10042           if (attribute_flag[0] != 0)
10043             {
10044               flags=ParseGeometry(argument_list[0].string_reference,
10045                 &geometry_info);
10046             }
10047           if (attribute_flag[1] != 0)
10048             geometry_info.rho=argument_list[1].real_reference;
10049           if (attribute_flag[2] != 0)
10050             channel=(ChannelType) argument_list[2].integer_reference;
10051           channel_mask=SetImageChannelMask(image,channel);
10052           image=RotationalBlurImage(image,geometry_info.rho,exception);
10053           if (image != (Image *) NULL)
10054             (void) SetImageChannelMask(image,channel_mask);
10055           break;
10056         }
10057         case 83:  /* Thumbnail */
10058         {
10059           if (attribute_flag[0] != 0)
10060             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10061               &geometry,exception);
10062           if (attribute_flag[1] != 0)
10063             geometry.width=argument_list[1].integer_reference;
10064           if (attribute_flag[2] != 0)
10065             geometry.height=argument_list[2].integer_reference;
10066           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10067           break;
10068         }
10069         case 84:  /* Strip */
10070         {
10071           (void) StripImage(image,exception);
10072           break;
10073         }
10074         case 85:  /* Tint */
10075         {
10076           PixelInfo
10077             tint;
10078
10079           GetPixelInfo(image,&tint);
10080           if (attribute_flag[0] != 0)
10081             (void) QueryColorCompliance(argument_list[0].string_reference,
10082               AllCompliance,&tint,exception);
10083           if (attribute_flag[1] == 0)
10084             argument_list[1].string_reference="100";
10085           image=TintImage(image,argument_list[1].string_reference,&tint,
10086             exception);
10087           break;
10088         }
10089         case 86:  /* Channel */
10090         {
10091           if (attribute_flag[0] != 0)
10092             channel=(ChannelType) argument_list[0].integer_reference;
10093           image=SeparateImage(image,channel,exception);
10094           break;
10095         }
10096         case 87:  /* Splice */
10097         {
10098           if (attribute_flag[7] != 0)
10099             image->gravity=(GravityType) argument_list[7].integer_reference;
10100           if (attribute_flag[0] != 0)
10101             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10102               &geometry,exception);
10103           if (attribute_flag[1] != 0)
10104             geometry.width=argument_list[1].integer_reference;
10105           if (attribute_flag[2] != 0)
10106             geometry.height=argument_list[2].integer_reference;
10107           if (attribute_flag[3] != 0)
10108             geometry.x=argument_list[3].integer_reference;
10109           if (attribute_flag[4] != 0)
10110             geometry.y=argument_list[4].integer_reference;
10111           if (attribute_flag[5] != 0)
10112             image->fuzz=StringToDoubleInterval(
10113               argument_list[5].string_reference,(double) QuantumRange+1.0);
10114           if (attribute_flag[6] != 0)
10115             (void) QueryColorCompliance(argument_list[6].string_reference,
10116               AllCompliance,&image->background_color,exception);
10117           image=SpliceImage(image,&geometry,exception);
10118           break;
10119         }
10120         case 88:  /* Posterize */
10121         {
10122           if (attribute_flag[0] == 0)
10123             argument_list[0].integer_reference=3;
10124           if (attribute_flag[1] == 0)
10125             argument_list[1].integer_reference=0;
10126           (void) PosterizeImage(image,argument_list[0].integer_reference,
10127             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10128             NoDitherMethod,exception);
10129           break;
10130         }
10131         case 89:  /* Shadow */
10132         {
10133           if (attribute_flag[0] != 0)
10134             {
10135               flags=ParseGeometry(argument_list[0].string_reference,
10136                 &geometry_info);
10137               if ((flags & SigmaValue) == 0)
10138                 geometry_info.sigma=1.0;
10139               if ((flags & XiValue) == 0)
10140                 geometry_info.xi=4.0;
10141               if ((flags & PsiValue) == 0)
10142                 geometry_info.psi=4.0;
10143             }
10144           if (attribute_flag[1] != 0)
10145             geometry_info.rho=argument_list[1].real_reference;
10146           if (attribute_flag[2] != 0)
10147             geometry_info.sigma=argument_list[2].real_reference;
10148           if (attribute_flag[3] != 0)
10149             geometry_info.xi=argument_list[3].integer_reference;
10150           if (attribute_flag[4] != 0)
10151             geometry_info.psi=argument_list[4].integer_reference;
10152           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10153             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10154             ceil(geometry_info.psi-0.5),exception);
10155           break;
10156         }
10157         case 90:  /* Identify */
10158         {
10159           if (attribute_flag[0] == 0)
10160             argument_list[0].file_reference=(FILE *) NULL;
10161           if (attribute_flag[1] != 0)
10162             (void) SetImageArtifact(image,"identify:features",
10163               argument_list[1].string_reference);
10164           if ((attribute_flag[2] != 0) &&
10165               (argument_list[2].integer_reference != 0))
10166             (void) SetImageArtifact(image,"identify:unique","true");
10167           (void) IdentifyImage(image,argument_list[0].file_reference,
10168             MagickTrue,exception);
10169           break;
10170         }
10171         case 91:  /* SepiaTone */
10172         {
10173           if (attribute_flag[0] == 0)
10174             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10175           image=SepiaToneImage(image,argument_list[0].real_reference,
10176             exception);
10177           break;
10178         }
10179         case 92:  /* SigmoidalContrast */
10180         {
10181           MagickBooleanType
10182             sharpen;
10183
10184           if (attribute_flag[0] != 0)
10185             {
10186               flags=ParseGeometry(argument_list[0].string_reference,
10187                 &geometry_info);
10188               if ((flags & SigmaValue) == 0)
10189                 geometry_info.sigma=QuantumRange/2.0;
10190               if ((flags & PercentValue) != 0)
10191                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10192             }
10193           if (attribute_flag[1] != 0)
10194             geometry_info.rho=argument_list[1].real_reference;
10195           if (attribute_flag[2] != 0)
10196             geometry_info.sigma=argument_list[2].real_reference;
10197           if (attribute_flag[3] != 0)
10198             channel=(ChannelType) argument_list[3].integer_reference;
10199           sharpen=MagickTrue;
10200           if (attribute_flag[4] != 0)
10201             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10202               MagickFalse;
10203           channel_mask=SetImageChannelMask(image,channel);
10204           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10205             geometry_info.sigma,exception);
10206           (void) SetImageChannelMask(image,channel_mask);
10207           break;
10208         }
10209         case 93:  /* Extent */
10210         {
10211           if (attribute_flag[7] != 0)
10212             image->gravity=(GravityType) argument_list[7].integer_reference;
10213           if (attribute_flag[0] != 0)
10214             {
10215               int
10216                 flags;
10217
10218               flags=ParseGravityGeometry(image,
10219                 argument_list[0].string_reference,&geometry,exception);
10220               (void) flags;
10221               if (geometry.width == 0)
10222                 geometry.width=image->columns;
10223               if (geometry.height == 0)
10224                 geometry.height=image->rows;
10225             }
10226           if (attribute_flag[1] != 0)
10227             geometry.width=argument_list[1].integer_reference;
10228           if (attribute_flag[2] != 0)
10229             geometry.height=argument_list[2].integer_reference;
10230           if (attribute_flag[3] != 0)
10231             geometry.x=argument_list[3].integer_reference;
10232           if (attribute_flag[4] != 0)
10233             geometry.y=argument_list[4].integer_reference;
10234           if (attribute_flag[5] != 0)
10235             image->fuzz=StringToDoubleInterval(
10236               argument_list[5].string_reference,(double) QuantumRange+1.0);
10237           if (attribute_flag[6] != 0)
10238             (void) QueryColorCompliance(argument_list[6].string_reference,
10239               AllCompliance,&image->background_color,exception);
10240           image=ExtentImage(image,&geometry,exception);
10241           break;
10242         }
10243         case 94:  /* Vignette */
10244         {
10245           if (attribute_flag[0] != 0)
10246             {
10247               flags=ParseGeometry(argument_list[0].string_reference,
10248                 &geometry_info);
10249               if ((flags & SigmaValue) == 0)
10250                 geometry_info.sigma=1.0;
10251               if ((flags & XiValue) == 0)
10252                 geometry_info.xi=0.1*image->columns;
10253               if ((flags & PsiValue) == 0)
10254                 geometry_info.psi=0.1*image->rows;
10255             }
10256           if (attribute_flag[1] != 0)
10257             geometry_info.rho=argument_list[1].real_reference;
10258           if (attribute_flag[2] != 0)
10259             geometry_info.sigma=argument_list[2].real_reference;
10260           if (attribute_flag[3] != 0)
10261             geometry_info.xi=argument_list[3].integer_reference;
10262           if (attribute_flag[4] != 0)
10263             geometry_info.psi=argument_list[4].integer_reference;
10264           if (attribute_flag[5] != 0)
10265             (void) QueryColorCompliance(argument_list[5].string_reference,
10266               AllCompliance,&image->background_color,exception);
10267           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10268             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10269             ceil(geometry_info.psi-0.5),exception);
10270           break;
10271         }
10272         case 95:  /* ContrastStretch */
10273         {
10274           double
10275             black_point,
10276             white_point;
10277
10278           black_point=0.0;
10279           white_point=(double) image->columns*image->rows;
10280           if (attribute_flag[0] != 0)
10281             {
10282               flags=ParseGeometry(argument_list[0].string_reference,
10283                 &geometry_info);
10284               black_point=geometry_info.rho;
10285               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10286                 black_point;
10287               if ((flags & PercentValue) != 0)
10288                 {
10289                   black_point*=(double) image->columns*image->rows/100.0;
10290                   white_point*=(double) image->columns*image->rows/100.0;
10291                 }
10292               white_point=(double) image->columns*image->rows-
10293                 white_point;
10294             }
10295           if (attribute_flag[1] != 0)
10296             black_point=argument_list[1].real_reference;
10297           if (attribute_flag[2] != 0)
10298             white_point=argument_list[2].real_reference;
10299           if (attribute_flag[4] != 0)
10300             channel=(ChannelType) argument_list[4].integer_reference;
10301           channel_mask=SetImageChannelMask(image,channel);
10302           (void) ContrastStretchImage(image,black_point,white_point,exception);
10303           (void) SetImageChannelMask(image,channel_mask);
10304           break;
10305         }
10306         case 96:  /* Sans0 */
10307         {
10308           break;
10309         }
10310         case 97:  /* Sans1 */
10311         {
10312           break;
10313         }
10314         case 98:  /* AdaptiveSharpen */
10315         {
10316           if (attribute_flag[0] != 0)
10317             {
10318               flags=ParseGeometry(argument_list[0].string_reference,
10319                 &geometry_info);
10320               if ((flags & SigmaValue) == 0)
10321                 geometry_info.sigma=1.0;
10322               if ((flags & XiValue) == 0)
10323                 geometry_info.xi=0.0;
10324             }
10325           if (attribute_flag[1] != 0)
10326             geometry_info.rho=argument_list[1].real_reference;
10327           if (attribute_flag[2] != 0)
10328             geometry_info.sigma=argument_list[2].real_reference;
10329           if (attribute_flag[3] != 0)
10330             geometry_info.xi=argument_list[3].real_reference;
10331           if (attribute_flag[4] != 0)
10332             channel=(ChannelType) argument_list[4].integer_reference;
10333           channel_mask=SetImageChannelMask(image,channel);
10334           image=AdaptiveSharpenImage(image,geometry_info.rho,
10335             geometry_info.sigma,exception);
10336           if (image != (Image *) NULL)
10337             (void) SetImageChannelMask(image,channel_mask);
10338           break;
10339         }
10340         case 99:  /* Transpose */
10341         {
10342           image=TransposeImage(image,exception);
10343           break;
10344         }
10345         case 100:  /* Tranverse */
10346         {
10347           image=TransverseImage(image,exception);
10348           break;
10349         }
10350         case 101:  /* AutoOrient */
10351         {
10352           image=AutoOrientImage(image,image->orientation,exception);
10353           break;
10354         }
10355         case 102:  /* AdaptiveBlur */
10356         {
10357           if (attribute_flag[0] != 0)
10358             {
10359               flags=ParseGeometry(argument_list[0].string_reference,
10360                 &geometry_info);
10361               if ((flags & SigmaValue) == 0)
10362                 geometry_info.sigma=1.0;
10363               if ((flags & XiValue) == 0)
10364                 geometry_info.xi=0.0;
10365             }
10366           if (attribute_flag[1] != 0)
10367             geometry_info.rho=argument_list[1].real_reference;
10368           if (attribute_flag[2] != 0)
10369             geometry_info.sigma=argument_list[2].real_reference;
10370           if (attribute_flag[3] != 0)
10371             channel=(ChannelType) argument_list[3].integer_reference;
10372           channel_mask=SetImageChannelMask(image,channel);
10373           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10374             exception);
10375           if (image != (Image *) NULL)
10376             (void) SetImageChannelMask(image,channel_mask);
10377           break;
10378         }
10379         case 103:  /* Sketch */
10380         {
10381           if (attribute_flag[0] != 0)
10382             {
10383               flags=ParseGeometry(argument_list[0].string_reference,
10384                 &geometry_info);
10385               if ((flags & SigmaValue) == 0)
10386                 geometry_info.sigma=1.0;
10387               if ((flags & XiValue) == 0)
10388                 geometry_info.xi=1.0;
10389             }
10390           if (attribute_flag[1] != 0)
10391             geometry_info.rho=argument_list[1].real_reference;
10392           if (attribute_flag[2] != 0)
10393             geometry_info.sigma=argument_list[2].real_reference;
10394           if (attribute_flag[3] != 0)
10395             geometry_info.xi=argument_list[3].real_reference;
10396           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10397             geometry_info.xi,exception);
10398           break;
10399         }
10400         case 104:  /* UniqueColors */
10401         {
10402           image=UniqueImageColors(image,exception);
10403           break;
10404         }
10405         case 105:  /* AdaptiveResize */
10406         {
10407           if (attribute_flag[0] != 0)
10408             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10409               &geometry,exception);
10410           if (attribute_flag[1] != 0)
10411             geometry.width=argument_list[1].integer_reference;
10412           if (attribute_flag[2] != 0)
10413             geometry.height=argument_list[2].integer_reference;
10414           if (attribute_flag[3] != 0)
10415             image->filter=(FilterType) argument_list[4].integer_reference;
10416           if (attribute_flag[4] != 0)
10417             SetImageArtifact(image,"filter:support",
10418               argument_list[4].string_reference);
10419           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10420             exception);
10421           break;
10422         }
10423         case 106:  /* ClipMask */
10424         {
10425           Image
10426             *mask_image;
10427
10428           if (attribute_flag[0] == 0)
10429             {
10430               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10431                 PackageName);
10432               goto PerlException;
10433             }
10434           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10435             exception);
10436           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10437           mask_image=DestroyImage(mask_image);
10438           break;
10439         }
10440         case 107:  /* LinearStretch */
10441         {
10442            double
10443              black_point,
10444              white_point;
10445
10446            black_point=0.0;
10447            white_point=(double) image->columns*image->rows;
10448            if (attribute_flag[0] != 0)
10449              {
10450                flags=ParseGeometry(argument_list[0].string_reference,
10451                  &geometry_info);
10452                if ((flags & SigmaValue) != 0)
10453                   white_point=geometry_info.sigma;
10454                if ((flags & PercentValue) != 0)
10455                  {
10456                    black_point*=(double) image->columns*image->rows/100.0;
10457                    white_point*=(double) image->columns*image->rows/100.0;
10458                  }
10459                if ((flags & SigmaValue) == 0)
10460                  white_point=(double) image->columns*image->rows-black_point;
10461              }
10462           if (attribute_flag[1] != 0)
10463             black_point=argument_list[1].real_reference;
10464           if (attribute_flag[2] != 0)
10465             white_point=argument_list[2].real_reference;
10466           (void) LinearStretchImage(image,black_point,white_point,exception);
10467           break;
10468         }
10469         case 108:  /* ColorMatrix */
10470         {
10471           AV
10472             *av;
10473
10474           double
10475             *color_matrix;
10476
10477           KernelInfo
10478             *kernel_info;
10479
10480           size_t
10481             order;
10482
10483           if (attribute_flag[0] == 0)
10484             break;
10485           av=(AV *) argument_list[0].array_reference;
10486           order=(size_t) sqrt(av_len(av)+1);
10487           color_matrix=(double *) AcquireQuantumMemory(order,order*
10488             sizeof(*color_matrix));
10489           if (color_matrix == (double *) NULL)
10490             {
10491               ThrowPerlException(exception,ResourceLimitFatalError,
10492                 "MemoryAllocationFailed",PackageName);
10493               goto PerlException;
10494            }
10495           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10496             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10497           for ( ; j < (ssize_t) (order*order); j++)
10498             color_matrix[j]=0.0;
10499           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10500           if (kernel_info == (KernelInfo *) NULL)
10501             break;
10502           kernel_info->width=order;
10503           kernel_info->height=order;
10504           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10505             order*sizeof(*kernel_info->values));
10506           if (kernel_info->values != (MagickRealType *) NULL)
10507             {
10508               for (i=0; i < (ssize_t) (order*order); i++)
10509                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10510               image=ColorMatrixImage(image,kernel_info,exception);
10511             }
10512           kernel_info=DestroyKernelInfo(kernel_info);
10513           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10514           break;
10515         }
10516         case 109:  /* Mask */
10517         {
10518           Image
10519             *mask_image;
10520
10521           if (attribute_flag[0] == 0)
10522             {
10523               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10524                 PackageName);
10525               goto PerlException;
10526             }
10527           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10528             MagickTrue,exception);
10529           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10530           mask_image=DestroyImage(mask_image);
10531           break;
10532         }
10533         case 110:  /* Polaroid */
10534         {
10535           char
10536             *caption;
10537
10538           DrawInfo
10539             *draw_info;
10540
10541           double
10542             angle;
10543
10544           PixelInterpolateMethod
10545             method;
10546
10547           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10548             (DrawInfo *) NULL);
10549           caption=(char *) NULL;
10550           if (attribute_flag[0] != 0)
10551             caption=InterpretImageProperties(info ? info->image_info :
10552               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10553               exception);
10554           angle=0.0;
10555           if (attribute_flag[1] != 0)
10556             angle=argument_list[1].real_reference;
10557           if (attribute_flag[2] != 0)
10558             (void) CloneString(&draw_info->font,
10559               argument_list[2].string_reference);
10560           if (attribute_flag[3] != 0)
10561             (void) QueryColorCompliance(argument_list[3].string_reference,
10562               AllCompliance,&draw_info->stroke,exception);
10563           if (attribute_flag[4] != 0)
10564             (void) QueryColorCompliance(argument_list[4].string_reference,
10565               AllCompliance,&draw_info->fill,exception);
10566           if (attribute_flag[5] != 0)
10567             draw_info->stroke_width=argument_list[5].real_reference;
10568           if (attribute_flag[6] != 0)
10569             draw_info->pointsize=argument_list[6].real_reference;
10570           if (attribute_flag[7] != 0)
10571             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10572           if (attribute_flag[8] != 0)
10573             (void) QueryColorCompliance(argument_list[8].string_reference,
10574               AllCompliance,&image->background_color,exception);
10575           method=UndefinedInterpolatePixel;
10576           if (attribute_flag[9] != 0)
10577             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10578           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10579           draw_info=DestroyDrawInfo(draw_info);
10580           if (caption != (char *) NULL)
10581             caption=DestroyString(caption);
10582           break;
10583         }
10584         case 111:  /* FloodfillPaint */
10585         {
10586           DrawInfo
10587             *draw_info;
10588
10589           MagickBooleanType
10590             invert;
10591
10592           PixelInfo
10593             target;
10594
10595           draw_info=CloneDrawInfo(info ? info->image_info :
10596             (ImageInfo *) NULL,(DrawInfo *) NULL);
10597           if (attribute_flag[0] != 0)
10598             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10599               &geometry,exception);
10600           if (attribute_flag[1] != 0)
10601             geometry.x=argument_list[1].integer_reference;
10602           if (attribute_flag[2] != 0)
10603             geometry.y=argument_list[2].integer_reference;
10604           if (attribute_flag[3] != 0)
10605             (void) QueryColorCompliance(argument_list[3].string_reference,
10606               AllCompliance,&draw_info->fill,exception);
10607           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10608             geometry.x,geometry.y,&target,exception);
10609           if (attribute_flag[4] != 0)
10610             QueryColorCompliance(argument_list[4].string_reference,
10611               AllCompliance,&target,exception);
10612           if (attribute_flag[5] != 0)
10613             image->fuzz=StringToDoubleInterval(
10614               argument_list[5].string_reference,(double) QuantumRange+1.0);
10615           if (attribute_flag[6] != 0)
10616             channel=(ChannelType) argument_list[6].integer_reference;
10617           invert=MagickFalse;
10618           if (attribute_flag[7] != 0)
10619             invert=(MagickBooleanType) argument_list[7].integer_reference;
10620           channel_mask=SetImageChannelMask(image,channel);
10621           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10622             geometry.y,invert,exception);
10623           (void) SetImageChannelMask(image,channel_mask);
10624           draw_info=DestroyDrawInfo(draw_info);
10625           break;
10626         }
10627         case 112:  /* Distort */
10628         {
10629           AV
10630             *av;
10631
10632           double
10633             *coordinates;
10634
10635           DistortMethod
10636             method;
10637
10638           size_t
10639             number_coordinates;
10640
10641           VirtualPixelMethod
10642             virtual_pixel;
10643
10644           if (attribute_flag[0] == 0)
10645             break;
10646           method=UndefinedDistortion;
10647           if (attribute_flag[1] != 0)
10648             method=(DistortMethod) argument_list[1].integer_reference;
10649           av=(AV *) argument_list[0].array_reference;
10650           number_coordinates=(size_t) av_len(av)+1;
10651           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10652             sizeof(*coordinates));
10653           if (coordinates == (double *) NULL)
10654             {
10655               ThrowPerlException(exception,ResourceLimitFatalError,
10656                 "MemoryAllocationFailed",PackageName);
10657               goto PerlException;
10658             }
10659           for (j=0; j < (ssize_t) number_coordinates; j++)
10660             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10661           virtual_pixel=UndefinedVirtualPixelMethod;
10662           if (attribute_flag[2] != 0)
10663             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10664               argument_list[2].integer_reference,exception);
10665           image=DistortImage(image,method,number_coordinates,coordinates,
10666             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10667             exception);
10668           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10669             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10670               exception);
10671           coordinates=(double *) RelinquishMagickMemory(coordinates);
10672           break;
10673         }
10674         case 113:  /* Clut */
10675         {
10676           PixelInterpolateMethod
10677             method;
10678
10679           if (attribute_flag[0] == 0)
10680             {
10681               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10682                 PackageName);
10683               goto PerlException;
10684             }
10685           method=UndefinedInterpolatePixel;
10686           if (attribute_flag[1] != 0)
10687             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10688           if (attribute_flag[2] != 0)
10689             channel=(ChannelType) argument_list[2].integer_reference;
10690           channel_mask=SetImageChannelMask(image,channel);
10691           (void) ClutImage(image,argument_list[0].image_reference,method,
10692             exception);
10693           (void) SetImageChannelMask(image,channel_mask);
10694           break;
10695         }
10696         case 114:  /* LiquidRescale */
10697         {
10698           if (attribute_flag[0] != 0)
10699             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10700               &geometry,exception);
10701           if (attribute_flag[1] != 0)
10702             geometry.width=argument_list[1].integer_reference;
10703           if (attribute_flag[2] != 0)
10704             geometry.height=argument_list[2].integer_reference;
10705           if (attribute_flag[3] == 0)
10706             argument_list[3].real_reference=1.0;
10707           if (attribute_flag[4] == 0)
10708             argument_list[4].real_reference=0.0;
10709           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10710             argument_list[3].real_reference,argument_list[4].real_reference,
10711             exception);
10712           break;
10713         }
10714         case 115:  /* EncipherImage */
10715         {
10716           (void) EncipherImage(image,argument_list[0].string_reference,
10717             exception);
10718           break;
10719         }
10720         case 116:  /* DecipherImage */
10721         {
10722           (void) DecipherImage(image,argument_list[0].string_reference,
10723             exception);
10724           break;
10725         }
10726         case 117:  /* Deskew */
10727         {
10728           geometry_info.rho=QuantumRange/2.0;
10729           if (attribute_flag[0] != 0)
10730             flags=ParseGeometry(argument_list[0].string_reference,
10731               &geometry_info);
10732           if (attribute_flag[1] != 0)
10733             geometry_info.rho=StringToDoubleInterval(
10734               argument_list[1].string_reference,(double) QuantumRange+1.0);
10735           image=DeskewImage(image,geometry_info.rho,exception);
10736           break;
10737         }
10738         case 118:  /* Remap */
10739         {
10740           QuantizeInfo
10741             *quantize_info;
10742
10743           if (attribute_flag[0] == 0)
10744             {
10745               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10746                 PackageName);
10747               goto PerlException;
10748             }
10749           quantize_info=AcquireQuantizeInfo(info->image_info);
10750           if (attribute_flag[1] != 0)
10751             quantize_info->dither_method=(DitherMethod)
10752               argument_list[1].integer_reference;
10753           (void) RemapImages(quantize_info,image,
10754             argument_list[0].image_reference,exception);
10755           quantize_info=DestroyQuantizeInfo(quantize_info);
10756           break;
10757         }
10758         case 119:  /* SparseColor */
10759         {
10760           AV
10761             *av;
10762
10763           double
10764             *coordinates;
10765
10766           SparseColorMethod
10767             method;
10768
10769           size_t
10770             number_coordinates;
10771
10772           VirtualPixelMethod
10773             virtual_pixel;
10774
10775           if (attribute_flag[0] == 0)
10776             break;
10777           method=UndefinedColorInterpolate;
10778           if (attribute_flag[1] != 0)
10779             method=(SparseColorMethod) argument_list[1].integer_reference;
10780           av=(AV *) argument_list[0].array_reference;
10781           number_coordinates=(size_t) av_len(av)+1;
10782           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10783             sizeof(*coordinates));
10784           if (coordinates == (double *) NULL)
10785             {
10786               ThrowPerlException(exception,ResourceLimitFatalError,
10787                 "MemoryAllocationFailed",PackageName);
10788               goto PerlException;
10789             }
10790           for (j=0; j < (ssize_t) number_coordinates; j++)
10791             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10792           virtual_pixel=UndefinedVirtualPixelMethod;
10793           if (attribute_flag[2] != 0)
10794             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10795               argument_list[2].integer_reference,exception);
10796           if (attribute_flag[3] != 0)
10797             channel=(ChannelType) argument_list[3].integer_reference;
10798           channel_mask=SetImageChannelMask(image,channel);
10799           image=SparseColorImage(image,method,number_coordinates,coordinates,
10800             exception);
10801           if (image != (Image *) NULL)
10802             (void) SetImageChannelMask(image,channel_mask);
10803           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10804             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10805               exception);
10806           coordinates=(double *) RelinquishMagickMemory(coordinates);
10807           break;
10808         }
10809         case 120:  /* Function */
10810         {
10811           AV
10812             *av;
10813
10814           double
10815             *parameters;
10816
10817           MagickFunction
10818             function;
10819
10820           size_t
10821             number_parameters;
10822
10823           VirtualPixelMethod
10824             virtual_pixel;
10825
10826           if (attribute_flag[0] == 0)
10827             break;
10828           function=UndefinedFunction;
10829           if (attribute_flag[1] != 0)
10830             function=(MagickFunction) argument_list[1].integer_reference;
10831           av=(AV *) argument_list[0].array_reference;
10832           number_parameters=(size_t) av_len(av)+1;
10833           parameters=(double *) AcquireQuantumMemory(number_parameters,
10834             sizeof(*parameters));
10835           if (parameters == (double *) NULL)
10836             {
10837               ThrowPerlException(exception,ResourceLimitFatalError,
10838                 "MemoryAllocationFailed",PackageName);
10839               goto PerlException;
10840             }
10841           for (j=0; j < (ssize_t) number_parameters; j++)
10842             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10843           virtual_pixel=UndefinedVirtualPixelMethod;
10844           if (attribute_flag[2] != 0)
10845             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10846               argument_list[2].integer_reference,exception);
10847           (void) FunctionImage(image,function,number_parameters,parameters,
10848             exception);
10849           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10850             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10851               exception);
10852           parameters=(double *) RelinquishMagickMemory(parameters);
10853           break;
10854         }
10855         case 121:  /* SelectiveBlur */
10856         {
10857           if (attribute_flag[0] != 0)
10858             {
10859               flags=ParseGeometry(argument_list[0].string_reference,
10860                 &geometry_info);
10861               if ((flags & SigmaValue) == 0)
10862                 geometry_info.sigma=1.0;
10863               if ((flags & PercentValue) != 0)
10864                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10865             }
10866           if (attribute_flag[1] != 0)
10867             geometry_info.rho=argument_list[1].real_reference;
10868           if (attribute_flag[2] != 0)
10869             geometry_info.sigma=argument_list[2].real_reference;
10870           if (attribute_flag[3] != 0)
10871             geometry_info.xi=argument_list[3].integer_reference;;
10872           if (attribute_flag[5] != 0)
10873             channel=(ChannelType) argument_list[5].integer_reference;
10874           channel_mask=SetImageChannelMask(image,channel);
10875           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10876             geometry_info.xi,exception);
10877           if (image != (Image *) NULL)
10878             (void) SetImageChannelMask(image,channel_mask);
10879           break;
10880         }
10881         case 122:  /* HaldClut */
10882         {
10883           if (attribute_flag[0] == 0)
10884             {
10885               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10886                 PackageName);
10887               goto PerlException;
10888             }
10889           if (attribute_flag[1] != 0)
10890             channel=(ChannelType) argument_list[1].integer_reference;
10891           channel_mask=SetImageChannelMask(image,channel);
10892           (void) HaldClutImage(image,argument_list[0].image_reference,
10893             exception);
10894           (void) SetImageChannelMask(image,channel_mask);
10895           break;
10896         }
10897         case 123:  /* BlueShift */
10898         {
10899           if (attribute_flag[0] != 0)
10900             (void) ParseGeometry(argument_list[0].string_reference,
10901               &geometry_info);
10902           image=BlueShiftImage(image,geometry_info.rho,exception);
10903           break;
10904         }
10905         case 124:  /* ForwardFourierTransformImage */
10906         {
10907           image=ForwardFourierTransformImage(image,
10908             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10909             exception);
10910           break;
10911         }
10912         case 125:  /* InverseFourierTransformImage */
10913         {
10914           image=InverseFourierTransformImage(image,image->next,
10915             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10916             exception);
10917           break;
10918         }
10919         case 126:  /* ColorDecisionList */
10920         {
10921           if (attribute_flag[0] == 0)
10922             argument_list[0].string_reference=(char *) NULL;
10923           (void) ColorDecisionListImage(image,
10924             argument_list[0].string_reference,exception);
10925           break;
10926         }
10927         case 127:  /* AutoGamma */
10928         {
10929           if (attribute_flag[0] != 0)
10930             channel=(ChannelType) argument_list[0].integer_reference;
10931           channel_mask=SetImageChannelMask(image,channel);
10932           (void) AutoGammaImage(image,exception);
10933           (void) SetImageChannelMask(image,channel_mask);
10934           break;
10935         }
10936         case 128:  /* AutoLevel */
10937         {
10938           if (attribute_flag[0] != 0)
10939             channel=(ChannelType) argument_list[0].integer_reference;
10940           channel_mask=SetImageChannelMask(image,channel);
10941           (void) AutoLevelImage(image,exception);
10942           (void) SetImageChannelMask(image,channel_mask);
10943           break;
10944         }
10945         case 129:  /* LevelColors */
10946         {
10947           PixelInfo
10948             black_point,
10949             white_point;
10950
10951           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10952             exception);
10953           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10954             exception);
10955           if (attribute_flag[1] != 0)
10956              (void) QueryColorCompliance(
10957                argument_list[1].string_reference,AllCompliance,&black_point,
10958                exception);
10959           if (attribute_flag[2] != 0)
10960              (void) QueryColorCompliance(
10961                argument_list[2].string_reference,AllCompliance,&white_point,
10962                exception);
10963           if (attribute_flag[3] != 0)
10964             channel=(ChannelType) argument_list[3].integer_reference;
10965           channel_mask=SetImageChannelMask(image,channel);
10966           (void) LevelImageColors(image,&black_point,&white_point,
10967             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10968             exception);
10969           (void) SetImageChannelMask(image,channel_mask);
10970           break;
10971         }
10972         case 130:  /* Clamp */
10973         {
10974           if (attribute_flag[0] != 0)
10975             channel=(ChannelType) argument_list[0].integer_reference;
10976           channel_mask=SetImageChannelMask(image,channel);
10977           (void) ClampImage(image,exception);
10978           (void) SetImageChannelMask(image,channel_mask);
10979           break;
10980         }
10981         case 131:  /* BrightnessContrast */
10982         {
10983           double
10984             brightness,
10985             contrast;
10986
10987           brightness=0.0;
10988           contrast=0.0;
10989           if (attribute_flag[0] != 0)
10990             {
10991               flags=ParseGeometry(argument_list[0].string_reference,
10992                 &geometry_info);
10993               brightness=geometry_info.rho;
10994               if ((flags & SigmaValue) == 0)
10995                 contrast=geometry_info.sigma;
10996             }
10997           if (attribute_flag[1] != 0)
10998             brightness=argument_list[1].real_reference;
10999           if (attribute_flag[2] != 0)
11000             contrast=argument_list[2].real_reference;
11001           if (attribute_flag[4] != 0)
11002             channel=(ChannelType) argument_list[4].integer_reference;
11003           channel_mask=SetImageChannelMask(image,channel);
11004           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11005           (void) SetImageChannelMask(image,channel_mask);
11006           break;
11007         }
11008         case 132:  /* Morphology */
11009         {
11010           KernelInfo
11011             *kernel;
11012
11013           MorphologyMethod
11014             method;
11015
11016           ssize_t
11017             iterations;
11018
11019           if (attribute_flag[0] == 0)
11020             break;
11021           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11022           if (kernel == (KernelInfo *) NULL)
11023             break;
11024           if (attribute_flag[1] != 0)
11025             channel=(ChannelType) argument_list[1].integer_reference;
11026           method=UndefinedMorphology;
11027           if (attribute_flag[2] != 0)
11028             method=argument_list[2].integer_reference;
11029           iterations=1;
11030           if (attribute_flag[3] != 0)
11031             iterations=argument_list[3].integer_reference;
11032           channel_mask=SetImageChannelMask(image,channel);
11033           image=MorphologyImage(image,method,iterations,kernel,exception);
11034           if (image != (Image *) NULL)
11035             (void) SetImageChannelMask(image,channel_mask);
11036           kernel=DestroyKernelInfo(kernel);
11037           break;
11038         }
11039         case 133:  /* Mode */
11040         {
11041           if (attribute_flag[0] != 0)
11042             {
11043               flags=ParseGeometry(argument_list[0].string_reference,
11044                 &geometry_info);
11045               if ((flags & SigmaValue) == 0)
11046                 geometry_info.sigma=1.0;
11047             }
11048           if (attribute_flag[1] != 0)
11049             geometry_info.rho=argument_list[1].real_reference;
11050           if (attribute_flag[2] != 0)
11051             geometry_info.sigma=argument_list[2].real_reference;
11052           if (attribute_flag[3] != 0)
11053             channel=(ChannelType) argument_list[3].integer_reference;
11054           channel_mask=SetImageChannelMask(image,channel);
11055           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11056             (size_t) geometry_info.sigma,exception);
11057           if (image != (Image *) NULL)
11058             (void) SetImageChannelMask(image,channel_mask);
11059           break;
11060         }
11061         case 134:  /* Statistic */
11062         {
11063           StatisticType
11064             statistic;
11065
11066           statistic=UndefinedStatistic;
11067           if (attribute_flag[0] != 0)
11068             {
11069               flags=ParseGeometry(argument_list[0].string_reference,
11070                 &geometry_info);
11071               if ((flags & SigmaValue) == 0)
11072                 geometry_info.sigma=1.0;
11073             }
11074           if (attribute_flag[1] != 0)
11075             geometry_info.rho=argument_list[1].real_reference;
11076           if (attribute_flag[2] != 0)
11077             geometry_info.sigma=argument_list[2].real_reference;
11078           if (attribute_flag[3] != 0)
11079             channel=(ChannelType) argument_list[3].integer_reference;
11080           if (attribute_flag[4] != 0)
11081             statistic=(StatisticType) argument_list[4].integer_reference;
11082           channel_mask=SetImageChannelMask(image,channel);
11083           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11084             (size_t) geometry_info.sigma,exception);
11085           if (image != (Image *) NULL)
11086             (void) SetImageChannelMask(image,channel_mask);
11087           break;
11088         }
11089         case 135:  /* Perceptible */
11090         {
11091           double
11092             epsilon;
11093
11094           epsilon=MagickEpsilon;
11095           if (attribute_flag[0] != 0)
11096             epsilon=argument_list[0].real_reference;
11097           if (attribute_flag[1] != 0)
11098             channel=(ChannelType) argument_list[1].integer_reference;
11099           channel_mask=SetImageChannelMask(image,channel);
11100           (void) PerceptibleImage(image,epsilon,exception);
11101           (void) SetImageChannelMask(image,channel_mask);
11102           break;
11103         }
11104         case 136:  /* Poly */
11105         {
11106           AV
11107             *av;
11108
11109           double
11110             *terms;
11111
11112           size_t
11113             number_terms;
11114
11115           if (attribute_flag[0] == 0)
11116             break;
11117           if (attribute_flag[1] != 0)
11118             channel=(ChannelType) argument_list[1].integer_reference;
11119           av=(AV *) argument_list[0].array_reference;
11120           number_terms=(size_t) av_len(av);
11121           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11122           if (terms == (double *) NULL)
11123             {
11124               ThrowPerlException(exception,ResourceLimitFatalError,
11125                 "MemoryAllocationFailed",PackageName);
11126               goto PerlException;
11127             }
11128           for (j=0; j < av_len(av); j++)
11129             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11130           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11131           terms=(double *) RelinquishMagickMemory(terms);
11132           break;
11133         }
11134         case 137:  /* Grayscale */
11135         {
11136           PixelIntensityMethod
11137             method;
11138
11139           method=UndefinedPixelIntensityMethod;
11140           if (attribute_flag[0] != 0)
11141             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11142           (void) GrayscaleImage(image,method,exception);
11143           break;
11144         }
11145         case 138:  /* Canny */
11146         {
11147           if (attribute_flag[0] != 0)
11148             {
11149               flags=ParseGeometry(argument_list[0].string_reference,
11150                 &geometry_info);
11151               if ((flags & SigmaValue) == 0)
11152                 geometry_info.sigma=1.0;
11153               if ((flags & XiValue) == 0)
11154                 geometry_info.xi=0.10;
11155               if ((flags & PsiValue) == 0)
11156                 geometry_info.psi=0.30;
11157               if ((flags & PercentValue) != 0)
11158                 {
11159                   geometry_info.xi/=100.0;
11160                   geometry_info.psi/=100.0;
11161                 }
11162             }
11163           if (attribute_flag[1] != 0)
11164             geometry_info.rho=argument_list[1].real_reference;
11165           if (attribute_flag[2] != 0)
11166             geometry_info.sigma=argument_list[2].real_reference;
11167           if (attribute_flag[3] != 0)
11168             geometry_info.xi=argument_list[3].real_reference;
11169           if (attribute_flag[4] != 0)
11170             geometry_info.psi=argument_list[4].real_reference;
11171           if (attribute_flag[5] != 0)
11172             channel=(ChannelType) argument_list[5].integer_reference;
11173           channel_mask=SetImageChannelMask(image,channel);
11174           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11175             geometry_info.xi,geometry_info.psi,exception);
11176           if (image != (Image *) NULL)
11177             (void) SetImageChannelMask(image,channel_mask);
11178           break;
11179         }
11180         case 139:  /* HoughLine */
11181         {
11182           if (attribute_flag[0] != 0)
11183             {
11184               flags=ParseGeometry(argument_list[0].string_reference,
11185                 &geometry_info);
11186               if ((flags & SigmaValue) == 0)
11187                 geometry_info.sigma=geometry_info.rho;
11188               if ((flags & XiValue) == 0)
11189                 geometry_info.xi=40;
11190             }
11191           if (attribute_flag[1] != 0)
11192             geometry_info.rho=(double) argument_list[1].integer_reference;
11193           if (attribute_flag[2] != 0)
11194             geometry_info.sigma=(double) argument_list[2].integer_reference;
11195           if (attribute_flag[3] != 0)
11196             geometry_info.xi=(double) argument_list[3].integer_reference;
11197           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11198             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11199           break;
11200         }
11201         case 140:  /* MeanShift */
11202         {
11203           if (attribute_flag[0] != 0)
11204             {
11205               flags=ParseGeometry(argument_list[0].string_reference,
11206                 &geometry_info);
11207               if ((flags & SigmaValue) == 0)
11208                 geometry_info.sigma=geometry_info.rho;
11209               if ((flags & XiValue) == 0)
11210                 geometry_info.xi=0.10*QuantumRange;
11211               if ((flags & PercentValue) != 0)
11212                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11213             }
11214           if (attribute_flag[1] != 0)
11215             geometry_info.rho=(double) argument_list[1].integer_reference;
11216           if (attribute_flag[2] != 0)
11217             geometry_info.sigma=(double) argument_list[2].integer_reference;
11218           if (attribute_flag[3] != 0)
11219             geometry_info.xi=(double) argument_list[3].integer_reference;
11220           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11221             geometry_info.sigma,geometry_info.xi,exception);
11222           break;
11223         }
11224         case 141:  /* Kuwahara */
11225         {
11226           if (attribute_flag[0] != 0)
11227             {
11228               flags=ParseGeometry(argument_list[0].string_reference,
11229                 &geometry_info);
11230               if ((flags & SigmaValue) == 0)
11231                 geometry_info.sigma=geometry_info.rho-0.5;
11232             }
11233           if (attribute_flag[1] != 0)
11234             geometry_info.rho=argument_list[1].real_reference;
11235           if (attribute_flag[2] != 0)
11236             geometry_info.sigma=argument_list[2].real_reference;
11237           if (attribute_flag[3] != 0)
11238             channel=(ChannelType) argument_list[3].integer_reference;
11239           channel_mask=SetImageChannelMask(image,channel);
11240           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11241             exception);
11242           if (image != (Image *) NULL)
11243             (void) SetImageChannelMask(image,channel_mask);
11244           break;
11245         }
11246         case 142:  /* ConnectedComponent */
11247         {
11248           size_t
11249             connectivity;
11250
11251           connectivity=4;
11252           if (attribute_flag[0] != 0)
11253             connectivity=argument_list[0].integer_reference;
11254           image=ConnectedComponentsImage(image,connectivity,
11255             (CCObjectInfo **) NULL,exception);
11256           break;
11257         }
11258         case 143:  /* Copy */
11259         {
11260           Image
11261             *source_image;
11262
11263           OffsetInfo
11264             offset;
11265
11266           RectangleInfo
11267             offset_geometry;
11268
11269           source_image=image;
11270           if (attribute_flag[0] != 0)
11271             source_image=argument_list[0].image_reference;
11272           SetGeometry(source_image,&geometry);
11273           if (attribute_flag[1] != 0)
11274             flags=ParseGravityGeometry(source_image,
11275               argument_list[1].string_reference,&geometry,exception);
11276           if (attribute_flag[2] != 0)
11277             geometry.width=argument_list[2].integer_reference;
11278           if (attribute_flag[3] != 0)
11279             geometry.height=argument_list[3].integer_reference;
11280           if (attribute_flag[4] != 0)
11281             geometry.x=argument_list[4].integer_reference;
11282           if (attribute_flag[5] != 0)
11283             geometry.y=argument_list[5].integer_reference;
11284           if (attribute_flag[6] != 0)
11285             image->gravity=(GravityType) argument_list[6].integer_reference;
11286           SetGeometry(image,&offset_geometry);
11287           if (attribute_flag[7] != 0)
11288             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11289               &offset_geometry,exception);
11290           offset.x=offset_geometry.x;
11291           offset.y=offset_geometry.y;
11292           if (attribute_flag[8] != 0)
11293             offset.x=argument_list[8].integer_reference;
11294           if (attribute_flag[9] != 0)
11295             offset.y=argument_list[9].integer_reference;
11296           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11297             exception);
11298           break;
11299         }
11300         case 144:  /* Color */
11301         {
11302           PixelInfo
11303             color;
11304
11305           (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11306           if (attribute_flag[0] != 0)
11307             (void) QueryColorCompliance(argument_list[0].string_reference,
11308               AllCompliance,&color,exception);
11309           (void) SetImageColor(image,&color,exception);
11310           break;
11311         }
11312         case 145:  /* WaveletDenoise */
11313         {
11314           if (attribute_flag[0] != 0)
11315             {
11316               flags=ParseGeometry(argument_list[0].string_reference,
11317                 &geometry_info);
11318               if ((flags & PercentValue) != 0)
11319                 {
11320                   geometry_info.rho=QuantumRange*geometry_info.rho/100.0;
11321                   geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
11322                 }
11323               if ((flags & SigmaValue) == 0)
11324                 geometry_info.sigma=0.0;
11325             }
11326           if (attribute_flag[1] != 0)
11327             geometry_info.rho=argument_list[1].real_reference;
11328           if (attribute_flag[2] != 0)
11329             geometry_info.sigma=argument_list[2].real_reference;
11330           if (attribute_flag[3] != 0)
11331             channel=(ChannelType) argument_list[3].integer_reference;
11332           channel_mask=SetImageChannelMask(image,channel);
11333           image=WaveletDenoiseImage(image,geometry_info.rho,geometry_info.sigma,
11334             exception);
11335           if (image != (Image *) NULL)
11336             (void) SetImageChannelMask(image,channel_mask);
11337           break;
11338         }
11339         case 146:  /* Colorspace */
11340         {
11341           ColorspaceType
11342             colorspace;
11343
11344           colorspace=sRGBColorspace;
11345           if (attribute_flag[0] != 0)
11346             colorspace=(ColorspaceType) argument_list[0].integer_reference;
11347           (void) TransformImageColorspace(image,colorspace,exception);
11348           break;
11349         }
11350       }
11351       if (next != (Image *) NULL)
11352         (void) CatchImageException(next);
11353       if (region_image != (Image *) NULL)
11354         {
11355           /*
11356             Composite region.
11357           */
11358           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11359             region_info.x,region_info.y,exception);
11360           (void) status;
11361           (void) CatchImageException(region_image);
11362           image=DestroyImage(image);
11363           image=region_image;
11364         }
11365       if (image != (Image *) NULL)
11366         {
11367           number_images++;
11368           if (next && (next != image))
11369             {
11370               image->next=next->next;
11371               if (image->next != (Image *) NULL)
11372                 image->next->previous=image;
11373               DeleteImageFromRegistry(*pv,next);
11374             }
11375           sv_setiv(*pv,PTR2IV(image));
11376           next=image;
11377         }
11378       if (*pv)
11379         pv++;
11380     }
11381
11382   PerlException:
11383     if (reference_vector)
11384       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11385     InheritPerlException(exception,perl_exception);
11386     exception=DestroyExceptionInfo(exception);
11387     sv_setiv(perl_exception,(IV) number_images);
11388     SvPOK_on(perl_exception);
11389     ST(0)=sv_2mortal(perl_exception);
11390     XSRETURN(1);
11391   }
11392 \f
11393 #
11394 ###############################################################################
11395 #                                                                             #
11396 #                                                                             #
11397 #                                                                             #
11398 #   M o n t a g e                                                             #
11399 #                                                                             #
11400 #                                                                             #
11401 #                                                                             #
11402 ###############################################################################
11403 #
11404 #
11405 void
11406 Montage(ref,...)
11407   Image::Magick ref=NO_INIT
11408   ALIAS:
11409     MontageImage  = 1
11410     montage       = 2
11411     montageimage  = 3
11412   PPCODE:
11413   {
11414     AV
11415       *av;
11416
11417     char
11418       *attribute;
11419
11420     ExceptionInfo
11421       *exception;
11422
11423     HV
11424       *hv;
11425
11426     Image
11427       *image,
11428       *next;
11429
11430     PixelInfo
11431       transparent_color;
11432
11433     MontageInfo
11434       *montage_info;
11435
11436     register ssize_t
11437       i;
11438
11439     ssize_t
11440       sp;
11441
11442     struct PackageInfo
11443       *info;
11444
11445     SV
11446       *av_reference,
11447       *perl_exception,
11448       *reference,
11449       *rv,
11450       *sv;
11451
11452     PERL_UNUSED_VAR(ref);
11453     PERL_UNUSED_VAR(ix);
11454     exception=AcquireExceptionInfo();
11455     perl_exception=newSVpv("",0);
11456     sv=NULL;
11457     attribute=NULL;
11458     if (sv_isobject(ST(0)) == 0)
11459       {
11460         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11461           PackageName);
11462         goto PerlException;
11463       }
11464     reference=SvRV(ST(0));
11465     hv=SvSTASH(reference);
11466     av=newAV();
11467     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11468     SvREFCNT_dec(av);
11469     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11470     if (image == (Image *) NULL)
11471       {
11472         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11473           PackageName);
11474         goto PerlException;
11475       }
11476     /*
11477       Get options.
11478     */
11479     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11480     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11481     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11482       exception);
11483     for (i=2; i < items; i+=2)
11484     {
11485       attribute=(char *) SvPV(ST(i-1),na);
11486       switch (*attribute)
11487       {
11488         case 'B':
11489         case 'b':
11490         {
11491           if (LocaleCompare(attribute,"background") == 0)
11492             {
11493               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11494                 &montage_info->background_color,exception);
11495               for (next=image; next; next=next->next)
11496                 next->background_color=montage_info->background_color;
11497               break;
11498             }
11499           if (LocaleCompare(attribute,"border") == 0)
11500             {
11501               montage_info->border_width=SvIV(ST(i));
11502               break;
11503             }
11504           if (LocaleCompare(attribute,"bordercolor") == 0)
11505             {
11506               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11507                 &montage_info->border_color,exception);
11508               for (next=image; next; next=next->next)
11509                 next->border_color=montage_info->border_color;
11510               break;
11511             }
11512           if (LocaleCompare(attribute,"borderwidth") == 0)
11513             {
11514               montage_info->border_width=SvIV(ST(i));
11515               break;
11516             }
11517           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11518             attribute);
11519           break;
11520         }
11521         case 'C':
11522         case 'c':
11523         {
11524           if (LocaleCompare(attribute,"compose") == 0)
11525             {
11526               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11527                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11528               if (sp < 0)
11529                 {
11530                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11531                     SvPV(ST(i),na));
11532                   break;
11533                 }
11534               for (next=image; next; next=next->next)
11535                 next->compose=(CompositeOperator) sp;
11536               break;
11537             }
11538           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11539             attribute);
11540           break;
11541         }
11542         case 'F':
11543         case 'f':
11544         {
11545           if (LocaleCompare(attribute,"fill") == 0)
11546             {
11547               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11548                 &montage_info->fill,exception);
11549               break;
11550             }
11551           if (LocaleCompare(attribute,"font") == 0)
11552             {
11553               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11554               break;
11555             }
11556           if (LocaleCompare(attribute,"frame") == 0)
11557             {
11558               char
11559                 *p;
11560
11561               p=SvPV(ST(i),na);
11562               if (IsGeometry(p) == MagickFalse)
11563                 {
11564                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11565                     p);
11566                   break;
11567                 }
11568               (void) CloneString(&montage_info->frame,p);
11569               if (*p == '\0')
11570                 montage_info->frame=(char *) NULL;
11571               break;
11572             }
11573           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11574             attribute);
11575           break;
11576         }
11577         case 'G':
11578         case 'g':
11579         {
11580           if (LocaleCompare(attribute,"geometry") == 0)
11581             {
11582               char
11583                 *p;
11584
11585               p=SvPV(ST(i),na);
11586               if (IsGeometry(p) == MagickFalse)
11587                 {
11588                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11589                     p);
11590                   break;
11591                 }
11592              (void) CloneString(&montage_info->geometry,p);
11593              if (*p == '\0')
11594                montage_info->geometry=(char *) NULL;
11595              break;
11596            }
11597          if (LocaleCompare(attribute,"gravity") == 0)
11598            {
11599              ssize_t
11600                in;
11601
11602              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11603                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11604              if (in < 0)
11605                {
11606                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11607                    SvPV(ST(i),na));
11608                  return;
11609                }
11610              montage_info->gravity=(GravityType) in;
11611              for (next=image; next; next=next->next)
11612                next->gravity=(GravityType) in;
11613              break;
11614            }
11615           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11616             attribute);
11617           break;
11618         }
11619         case 'L':
11620         case 'l':
11621         {
11622           if (LocaleCompare(attribute,"label") == 0)
11623             {
11624               for (next=image; next; next=next->next)
11625                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11626                   info ? info->image_info : (ImageInfo *) NULL,next,
11627                   SvPV(ST(i),na),exception),exception);
11628               break;
11629             }
11630           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11631             attribute);
11632           break;
11633         }
11634         case 'M':
11635         case 'm':
11636         {
11637           if (LocaleCompare(attribute,"mattecolor") == 0)
11638             {
11639               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11640                 &montage_info->alpha_color,exception);
11641               for (next=image; next; next=next->next)
11642                 next->alpha_color=montage_info->alpha_color;
11643               break;
11644             }
11645           if (LocaleCompare(attribute,"mode") == 0)
11646             {
11647               ssize_t
11648                 in;
11649
11650               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11651                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11652               switch (in)
11653               {
11654                 default:
11655                 {
11656                   ThrowPerlException(exception,OptionError,
11657                     "UnrecognizedModeType",SvPV(ST(i),na));
11658                   break;
11659                 }
11660                 case FrameMode:
11661                 {
11662                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11663                   montage_info->shadow=MagickTrue;
11664                   break;
11665                 }
11666                 case UnframeMode:
11667                 {
11668                   montage_info->frame=(char *) NULL;
11669                   montage_info->shadow=MagickFalse;
11670                   montage_info->border_width=0;
11671                   break;
11672                 }
11673                 case ConcatenateMode:
11674                 {
11675                   montage_info->frame=(char *) NULL;
11676                   montage_info->shadow=MagickFalse;
11677                   (void) CloneString(&montage_info->geometry,"+0+0");
11678                   montage_info->border_width=0;
11679                 }
11680               }
11681               break;
11682             }
11683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11684             attribute);
11685           break;
11686         }
11687         case 'P':
11688         case 'p':
11689         {
11690           if (LocaleCompare(attribute,"pointsize") == 0)
11691             {
11692               montage_info->pointsize=SvIV(ST(i));
11693               break;
11694             }
11695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11696             attribute);
11697           break;
11698         }
11699         case 'S':
11700         case 's':
11701         {
11702           if (LocaleCompare(attribute,"shadow") == 0)
11703             {
11704               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11705                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11706               if (sp < 0)
11707                 {
11708                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11709                     SvPV(ST(i),na));
11710                   break;
11711                 }
11712              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11713              break;
11714             }
11715           if (LocaleCompare(attribute,"stroke") == 0)
11716             {
11717               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11718                 &montage_info->stroke,exception);
11719               break;
11720             }
11721           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11722             attribute);
11723           break;
11724         }
11725         case 'T':
11726         case 't':
11727         {
11728           if (LocaleCompare(attribute,"texture") == 0)
11729             {
11730               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11731               break;
11732             }
11733           if (LocaleCompare(attribute,"tile") == 0)
11734             {
11735               char *p=SvPV(ST(i),na);
11736               if (IsGeometry(p) == MagickFalse)
11737                 {
11738                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11739                     p);
11740                   break;
11741                 }
11742               (void) CloneString(&montage_info->tile,p);
11743               if (*p == '\0')
11744                 montage_info->tile=(char *) NULL;
11745               break;
11746             }
11747           if (LocaleCompare(attribute,"title") == 0)
11748             {
11749               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11750               break;
11751             }
11752           if (LocaleCompare(attribute,"transparent") == 0)
11753             {
11754               PixelInfo
11755                 transparent_color;
11756
11757               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11758                 &transparent_color,exception);
11759               for (next=image; next; next=next->next)
11760                 (void) TransparentPaintImage(next,&transparent_color,
11761                   TransparentAlpha,MagickFalse,exception);
11762               break;
11763             }
11764           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11765             attribute);
11766           break;
11767         }
11768         default:
11769         {
11770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11771             attribute);
11772           break;
11773         }
11774       }
11775     }
11776     image=MontageImageList(info->image_info,montage_info,image,exception);
11777     montage_info=DestroyMontageInfo(montage_info);
11778     if (image == (Image *) NULL)
11779       goto PerlException;
11780     if (transparent_color.alpha != TransparentAlpha)
11781       for (next=image; next; next=next->next)
11782         (void) TransparentPaintImage(next,&transparent_color,
11783           TransparentAlpha,MagickFalse,exception);
11784     for (  ; image; image=image->next)
11785     {
11786       AddImageToRegistry(sv,image);
11787       rv=newRV(sv);
11788       av_push(av,sv_bless(rv,hv));
11789       SvREFCNT_dec(sv);
11790     }
11791     exception=DestroyExceptionInfo(exception);
11792     ST(0)=av_reference;
11793     SvREFCNT_dec(perl_exception);
11794     XSRETURN(1);
11795
11796   PerlException:
11797     InheritPerlException(exception,perl_exception);
11798     exception=DestroyExceptionInfo(exception);
11799     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11800     SvPOK_on(perl_exception);
11801     ST(0)=sv_2mortal(perl_exception);
11802     XSRETURN(1);
11803   }
11804 \f
11805 #
11806 ###############################################################################
11807 #                                                                             #
11808 #                                                                             #
11809 #                                                                             #
11810 #   M o r p h                                                                 #
11811 #                                                                             #
11812 #                                                                             #
11813 #                                                                             #
11814 ###############################################################################
11815 #
11816 #
11817 void
11818 Morph(ref,...)
11819   Image::Magick ref=NO_INIT
11820   ALIAS:
11821     MorphImage  = 1
11822     morph       = 2
11823     morphimage  = 3
11824   PPCODE:
11825   {
11826     AV
11827       *av;
11828
11829     char
11830       *attribute;
11831
11832     ExceptionInfo
11833       *exception;
11834
11835     HV
11836       *hv;
11837
11838     Image
11839       *image;
11840
11841     register ssize_t
11842       i;
11843
11844     ssize_t
11845       number_frames;
11846
11847     struct PackageInfo
11848       *info;
11849
11850     SV
11851       *av_reference,
11852       *perl_exception,
11853       *reference,
11854       *rv,
11855       *sv;
11856
11857     PERL_UNUSED_VAR(ref);
11858     PERL_UNUSED_VAR(ix);
11859     exception=AcquireExceptionInfo();
11860     perl_exception=newSVpv("",0);
11861     sv=NULL;
11862     av=NULL;
11863     attribute=NULL;
11864     if (sv_isobject(ST(0)) == 0)
11865       {
11866         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11867           PackageName);
11868         goto PerlException;
11869       }
11870     reference=SvRV(ST(0));
11871     hv=SvSTASH(reference);
11872     av=newAV();
11873     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11874     SvREFCNT_dec(av);
11875     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11876     if (image == (Image *) NULL)
11877       {
11878         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11879           PackageName);
11880         goto PerlException;
11881       }
11882     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11883     /*
11884       Get attribute.
11885     */
11886     number_frames=30;
11887     for (i=2; i < items; i+=2)
11888     {
11889       attribute=(char *) SvPV(ST(i-1),na);
11890       switch (*attribute)
11891       {
11892         case 'F':
11893         case 'f':
11894         {
11895           if (LocaleCompare(attribute,"frames") == 0)
11896             {
11897               number_frames=SvIV(ST(i));
11898               break;
11899             }
11900           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11901             attribute);
11902           break;
11903         }
11904         default:
11905         {
11906           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11907             attribute);
11908           break;
11909         }
11910       }
11911     }
11912     image=MorphImages(image,number_frames,exception);
11913     if (image == (Image *) NULL)
11914       goto PerlException;
11915     for ( ; image; image=image->next)
11916     {
11917       AddImageToRegistry(sv,image);
11918       rv=newRV(sv);
11919       av_push(av,sv_bless(rv,hv));
11920       SvREFCNT_dec(sv);
11921     }
11922     exception=DestroyExceptionInfo(exception);
11923     ST(0)=av_reference;
11924     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11925     XSRETURN(1);
11926
11927   PerlException:
11928     InheritPerlException(exception,perl_exception);
11929     exception=DestroyExceptionInfo(exception);
11930     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11931     SvPOK_on(perl_exception);
11932     ST(0)=sv_2mortal(perl_exception);
11933     XSRETURN(1);
11934   }
11935 \f
11936 #
11937 ###############################################################################
11938 #                                                                             #
11939 #                                                                             #
11940 #                                                                             #
11941 #   M o s a i c                                                               #
11942 #                                                                             #
11943 #                                                                             #
11944 #                                                                             #
11945 ###############################################################################
11946 #
11947 #
11948 void
11949 Mosaic(ref)
11950   Image::Magick ref=NO_INIT
11951   ALIAS:
11952     MosaicImage   = 1
11953     mosaic        = 2
11954     mosaicimage   = 3
11955   PPCODE:
11956   {
11957     AV
11958       *av;
11959
11960     ExceptionInfo
11961       *exception;
11962
11963     HV
11964       *hv;
11965
11966     Image
11967       *image;
11968
11969     struct PackageInfo
11970       *info;
11971
11972     SV
11973       *perl_exception,
11974       *reference,
11975       *rv,
11976       *sv;
11977
11978     PERL_UNUSED_VAR(ref);
11979     PERL_UNUSED_VAR(ix);
11980     exception=AcquireExceptionInfo();
11981     perl_exception=newSVpv("",0);
11982     sv=NULL;
11983     if (sv_isobject(ST(0)) == 0)
11984       {
11985         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11986           PackageName);
11987         goto PerlException;
11988       }
11989     reference=SvRV(ST(0));
11990     hv=SvSTASH(reference);
11991     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11992     if (image == (Image *) NULL)
11993       {
11994         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11995           PackageName);
11996         goto PerlException;
11997       }
11998     image=MergeImageLayers(image,MosaicLayer,exception);
11999     /*
12000       Create blessed Perl array for the returned image.
12001     */
12002     av=newAV();
12003     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12004     SvREFCNT_dec(av);
12005     AddImageToRegistry(sv,image);
12006     rv=newRV(sv);
12007     av_push(av,sv_bless(rv,hv));
12008     SvREFCNT_dec(sv);
12009     (void) CopyMagickString(info->image_info->filename,image->filename,
12010       MagickPathExtent);
12011     SetImageInfo(info->image_info,0,exception);
12012     exception=DestroyExceptionInfo(exception);
12013     SvREFCNT_dec(perl_exception);
12014     XSRETURN(1);
12015
12016   PerlException:
12017     InheritPerlException(exception,perl_exception);
12018     exception=DestroyExceptionInfo(exception);
12019     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12020     SvPOK_on(perl_exception);  /* return messages in string context */
12021     ST(0)=sv_2mortal(perl_exception);
12022     XSRETURN(1);
12023   }
12024 \f
12025 #
12026 ###############################################################################
12027 #                                                                             #
12028 #                                                                             #
12029 #                                                                             #
12030 #   P i n g                                                                   #
12031 #                                                                             #
12032 #                                                                             #
12033 #                                                                             #
12034 ###############################################################################
12035 #
12036 #
12037 void
12038 Ping(ref,...)
12039   Image::Magick ref=NO_INIT
12040   ALIAS:
12041     PingImage  = 1
12042     ping       = 2
12043     pingimage  = 3
12044   PPCODE:
12045   {
12046     AV
12047       *av;
12048
12049     char
12050       **keep,
12051       **list;
12052
12053     ExceptionInfo
12054       *exception;
12055
12056     Image
12057       *image,
12058       *next;
12059
12060     int
12061       n;
12062
12063     MagickBooleanType
12064       status;
12065
12066     register char
12067       **p;
12068
12069     register ssize_t
12070       i;
12071
12072     ssize_t
12073       ac;
12074
12075     STRLEN
12076       *length;
12077
12078     struct PackageInfo
12079       *info,
12080       *package_info;
12081
12082     SV
12083       *perl_exception,
12084       *reference;
12085
12086     size_t
12087       count;
12088
12089     PERL_UNUSED_VAR(ref);
12090     PERL_UNUSED_VAR(ix);
12091     exception=AcquireExceptionInfo();
12092     perl_exception=newSVpv("",0);
12093     package_info=(struct PackageInfo *) NULL;
12094     ac=(items < 2) ? 1 : items-1;
12095     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12096     keep=list;
12097     length=(STRLEN *) NULL;
12098     if (list == (char **) NULL)
12099       {
12100         ThrowPerlException(exception,ResourceLimitError,
12101           "MemoryAllocationFailed",PackageName);
12102         goto PerlException;
12103       }
12104     keep=list;
12105     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12106     if (length == (STRLEN *) NULL)
12107       {
12108         ThrowPerlException(exception,ResourceLimitError,
12109           "MemoryAllocationFailed",PackageName);
12110         goto PerlException;
12111       }
12112     if (sv_isobject(ST(0)) == 0)
12113       {
12114         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12115           PackageName);
12116         goto PerlException;
12117       }
12118     reference=SvRV(ST(0));
12119     if (SvTYPE(reference) != SVt_PVAV)
12120       {
12121         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12122           PackageName);
12123         goto PerlException;
12124       }
12125     av=(AV *) reference;
12126     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12127       exception);
12128     package_info=ClonePackageInfo(info,exception);
12129     n=1;
12130     if (items <= 1)
12131       *list=(char *) (*package_info->image_info->filename ?
12132         package_info->image_info->filename : "XC:black");
12133     else
12134       for (n=0, i=0; i < ac; i++)
12135       {
12136         list[n]=(char *) SvPV(ST(i+1),length[n]);
12137         if ((items >= 3) && strEQcase(list[n],"blob"))
12138           {
12139             void
12140               *blob;
12141
12142             i++;
12143             blob=(void *) (SvPV(ST(i+1),length[n]));
12144             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12145           }
12146         if ((items >= 3) && strEQcase(list[n],"filename"))
12147           continue;
12148         if ((items >= 3) && strEQcase(list[n],"file"))
12149           {
12150             FILE
12151               *file;
12152
12153             PerlIO
12154               *io_info;
12155
12156             i++;
12157             io_info=IoIFP(sv_2io(ST(i+1)));
12158             if (io_info == (PerlIO *) NULL)
12159               {
12160                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12161                   PackageName);
12162                 continue;
12163               }
12164             file=PerlIO_findFILE(io_info);
12165             if (file == (FILE *) NULL)
12166               {
12167                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12168                   PackageName);
12169                 continue;
12170               }
12171             SetImageInfoFile(package_info->image_info,file);
12172           }
12173         if ((items >= 3) && strEQcase(list[n],"magick"))
12174           continue;
12175         n++;
12176       }
12177     list[n]=(char *) NULL;
12178     keep=list;
12179     status=ExpandFilenames(&n,&list);
12180     if (status == MagickFalse)
12181       {
12182         ThrowPerlException(exception,ResourceLimitError,
12183           "MemoryAllocationFailed",PackageName);
12184         goto PerlException;
12185       }
12186     count=0;
12187     for (i=0; i < n; i++)
12188     {
12189       (void) CopyMagickString(package_info->image_info->filename,list[i],
12190         MagickPathExtent);
12191       image=PingImage(package_info->image_info,exception);
12192       if (image == (Image *) NULL)
12193         break;
12194       if ((package_info->image_info->file != (FILE *) NULL) ||
12195           (package_info->image_info->blob != (void *) NULL))
12196         DisassociateImageStream(image);
12197       count+=GetImageListLength(image);
12198       EXTEND(sp,4*count);
12199       for (next=image; next; next=next->next)
12200       {
12201         PUSHs(sv_2mortal(newSViv(next->columns)));
12202         PUSHs(sv_2mortal(newSViv(next->rows)));
12203         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12204         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12205       }
12206       image=DestroyImageList(image);
12207     }
12208     /*
12209       Free resources.
12210     */
12211     for (i=0; i < n; i++)
12212       if (list[i] != (char *) NULL)
12213         for (p=keep; list[i] != *p++; )
12214           if (*p == NULL)
12215             {
12216               list[i]=(char *) RelinquishMagickMemory(list[i]);
12217               break;
12218             }
12219
12220   PerlException:
12221     if (package_info != (struct PackageInfo *) NULL)
12222       DestroyPackageInfo(package_info);
12223     if (list && (list != keep))
12224       list=(char **) RelinquishMagickMemory(list);
12225     if (keep)
12226       keep=(char **) RelinquishMagickMemory(keep);
12227     if (length)
12228       length=(STRLEN *) RelinquishMagickMemory(length);
12229     InheritPerlException(exception,perl_exception);
12230     exception=DestroyExceptionInfo(exception);
12231     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12232   }
12233 \f
12234 #
12235 ###############################################################################
12236 #                                                                             #
12237 #                                                                             #
12238 #                                                                             #
12239 #   P r e v i e w                                                             #
12240 #                                                                             #
12241 #                                                                             #
12242 #                                                                             #
12243 ###############################################################################
12244 #
12245 #
12246 void
12247 Preview(ref,...)
12248   Image::Magick ref=NO_INIT
12249   ALIAS:
12250     PreviewImage = 1
12251     preview      = 2
12252     previewimage = 3
12253   PPCODE:
12254   {
12255     AV
12256       *av;
12257
12258     ExceptionInfo
12259       *exception;
12260
12261     HV
12262       *hv;
12263
12264     Image
12265       *image,
12266       *preview_image;
12267
12268     PreviewType
12269       preview_type;
12270
12271     struct PackageInfo
12272       *info;
12273
12274     SV
12275       *av_reference,
12276       *perl_exception,
12277       *reference,
12278       *rv,
12279       *sv;
12280
12281     PERL_UNUSED_VAR(ref);
12282     PERL_UNUSED_VAR(ix);
12283     exception=AcquireExceptionInfo();
12284     perl_exception=newSVpv("",0);
12285     sv=NULL;
12286     av=NULL;
12287     if (sv_isobject(ST(0)) == 0)
12288       {
12289         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12290           PackageName);
12291         goto PerlException;
12292       }
12293     reference=SvRV(ST(0));
12294     hv=SvSTASH(reference);
12295     av=newAV();
12296     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12297     SvREFCNT_dec(av);
12298     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12299     if (image == (Image *) NULL)
12300       {
12301         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12302           PackageName);
12303         goto PerlException;
12304       }
12305     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12306     preview_type=GammaPreview;
12307     if (items > 1)
12308       preview_type=(PreviewType)
12309         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12310     for ( ; image; image=image->next)
12311     {
12312       preview_image=PreviewImage(image,preview_type,exception);
12313       if (preview_image == (Image *) NULL)
12314         goto PerlException;
12315       AddImageToRegistry(sv,preview_image);
12316       rv=newRV(sv);
12317       av_push(av,sv_bless(rv,hv));
12318       SvREFCNT_dec(sv);
12319     }
12320     exception=DestroyExceptionInfo(exception);
12321     ST(0)=av_reference;
12322     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12323     XSRETURN(1);
12324
12325   PerlException:
12326     InheritPerlException(exception,perl_exception);
12327     exception=DestroyExceptionInfo(exception);
12328     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12329     SvPOK_on(perl_exception);
12330     ST(0)=sv_2mortal(perl_exception);
12331     XSRETURN(1);
12332   }
12333 \f
12334 #
12335 ###############################################################################
12336 #                                                                             #
12337 #                                                                             #
12338 #                                                                             #
12339 #   Q u e r y C o l o r                                                       #
12340 #                                                                             #
12341 #                                                                             #
12342 #                                                                             #
12343 ###############################################################################
12344 #
12345 #
12346 void
12347 QueryColor(ref,...)
12348   Image::Magick ref=NO_INIT
12349   ALIAS:
12350     querycolor = 1
12351   PPCODE:
12352   {
12353     char
12354       *name;
12355
12356     ExceptionInfo
12357       *exception;
12358
12359     PixelInfo
12360       color;
12361
12362     register ssize_t
12363       i;
12364
12365     SV
12366       *perl_exception;
12367
12368     PERL_UNUSED_VAR(ref);
12369     PERL_UNUSED_VAR(ix);
12370     exception=AcquireExceptionInfo();
12371     perl_exception=newSVpv("",0);
12372     if (items == 1)
12373       {
12374         const ColorInfo
12375           **colorlist;
12376
12377         size_t
12378           colors;
12379
12380         colorlist=GetColorInfoList("*",&colors,exception);
12381         EXTEND(sp,colors);
12382         for (i=0; i < (ssize_t) colors; i++)
12383         {
12384           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12385         }
12386         colorlist=(const ColorInfo **)
12387           RelinquishMagickMemory((ColorInfo **) colorlist);
12388         goto PerlException;
12389       }
12390     EXTEND(sp,5*items);
12391     for (i=1; i < items; i++)
12392     {
12393       name=(char *) SvPV(ST(i),na);
12394       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12395         {
12396           PUSHs(&sv_undef);
12397           continue;
12398         }
12399       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12400       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12401       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12402       if (color.colorspace == CMYKColorspace)
12403         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12404       if (color.alpha_trait != UndefinedPixelTrait)
12405         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12406     }
12407
12408   PerlException:
12409     InheritPerlException(exception,perl_exception);
12410     exception=DestroyExceptionInfo(exception);
12411     SvREFCNT_dec(perl_exception);
12412   }
12413 \f
12414 #
12415 ###############################################################################
12416 #                                                                             #
12417 #                                                                             #
12418 #                                                                             #
12419 #   Q u e r y C o l o r N a m e                                               #
12420 #                                                                             #
12421 #                                                                             #
12422 #                                                                             #
12423 ###############################################################################
12424 #
12425 #
12426 void
12427 QueryColorname(ref,...)
12428   Image::Magick ref=NO_INIT
12429   ALIAS:
12430     querycolorname = 1
12431   PPCODE:
12432   {
12433     AV
12434       *av;
12435
12436     char
12437       message[MagickPathExtent];
12438
12439     ExceptionInfo
12440       *exception;
12441
12442     Image
12443       *image;
12444
12445     PixelInfo
12446       target_color;
12447
12448     register ssize_t
12449       i;
12450
12451     struct PackageInfo
12452       *info;
12453
12454     SV
12455       *perl_exception,
12456       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12457
12458     PERL_UNUSED_VAR(ref);
12459     PERL_UNUSED_VAR(ix);
12460     exception=AcquireExceptionInfo();
12461     perl_exception=newSVpv("",0);
12462     reference=SvRV(ST(0));
12463     av=(AV *) reference;
12464     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12465       exception);
12466     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12467     if (image == (Image *) NULL)
12468       {
12469         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12470           PackageName);
12471         goto PerlException;
12472       }
12473     EXTEND(sp,items);
12474     for (i=1; i < items; i++)
12475     {
12476       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12477         exception);
12478       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12479         exception);
12480       PUSHs(sv_2mortal(newSVpv(message,0)));
12481     }
12482
12483   PerlException:
12484     InheritPerlException(exception,perl_exception);
12485     exception=DestroyExceptionInfo(exception);
12486     SvREFCNT_dec(perl_exception);
12487   }
12488 \f
12489 #
12490 ###############################################################################
12491 #                                                                             #
12492 #                                                                             #
12493 #                                                                             #
12494 #   Q u e r y F o n t                                                         #
12495 #                                                                             #
12496 #                                                                             #
12497 #                                                                             #
12498 ###############################################################################
12499 #
12500 #
12501 void
12502 QueryFont(ref,...)
12503   Image::Magick ref=NO_INIT
12504   ALIAS:
12505     queryfont = 1
12506   PPCODE:
12507   {
12508     char
12509       *name,
12510       message[MagickPathExtent];
12511
12512     ExceptionInfo
12513       *exception;
12514
12515     register ssize_t
12516       i;
12517
12518     SV
12519       *perl_exception;
12520
12521     volatile const TypeInfo
12522       *type_info;
12523
12524     PERL_UNUSED_VAR(ref);
12525     PERL_UNUSED_VAR(ix);
12526     exception=AcquireExceptionInfo();
12527     perl_exception=newSVpv("",0);
12528     if (items == 1)
12529       {
12530         const TypeInfo
12531           **typelist;
12532
12533         size_t
12534           types;
12535
12536         typelist=GetTypeInfoList("*",&types,exception);
12537         EXTEND(sp,types);
12538         for (i=0; i < (ssize_t) types; i++)
12539         {
12540           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12541         }
12542         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12543           typelist);
12544         goto PerlException;
12545       }
12546     EXTEND(sp,10*items);
12547     for (i=1; i < items; i++)
12548     {
12549       name=(char *) SvPV(ST(i),na);
12550       type_info=GetTypeInfo(name,exception);
12551       if (type_info == (TypeInfo *) NULL)
12552         {
12553           PUSHs(&sv_undef);
12554           continue;
12555         }
12556       if (type_info->name == (char *) NULL)
12557         PUSHs(&sv_undef);
12558       else
12559         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12560       if (type_info->description == (char *) NULL)
12561         PUSHs(&sv_undef);
12562       else
12563         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12564       if (type_info->family == (char *) NULL)
12565         PUSHs(&sv_undef);
12566       else
12567         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12568       if (type_info->style == UndefinedStyle)
12569         PUSHs(&sv_undef);
12570       else
12571         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12572           type_info->style),0)));
12573       if (type_info->stretch == UndefinedStretch)
12574         PUSHs(&sv_undef);
12575       else
12576         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12577           type_info->stretch),0)));
12578       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12579         type_info->weight);
12580       PUSHs(sv_2mortal(newSVpv(message,0)));
12581       if (type_info->encoding == (char *) NULL)
12582         PUSHs(&sv_undef);
12583       else
12584         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12585       if (type_info->foundry == (char *) NULL)
12586         PUSHs(&sv_undef);
12587       else
12588         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12589       if (type_info->format == (char *) NULL)
12590         PUSHs(&sv_undef);
12591       else
12592         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12593       if (type_info->metrics == (char *) NULL)
12594         PUSHs(&sv_undef);
12595       else
12596         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12597       if (type_info->glyphs == (char *) NULL)
12598         PUSHs(&sv_undef);
12599       else
12600         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12601     }
12602
12603   PerlException:
12604     InheritPerlException(exception,perl_exception);
12605     exception=DestroyExceptionInfo(exception);
12606     SvREFCNT_dec(perl_exception);
12607   }
12608 \f
12609 #
12610 ###############################################################################
12611 #                                                                             #
12612 #                                                                             #
12613 #                                                                             #
12614 #   Q u e r y F o n t M e t r i c s                                           #
12615 #                                                                             #
12616 #                                                                             #
12617 #                                                                             #
12618 ###############################################################################
12619 #
12620 #
12621 void
12622 QueryFontMetrics(ref,...)
12623   Image::Magick ref=NO_INIT
12624   ALIAS:
12625     queryfontmetrics = 1
12626   PPCODE:
12627   {
12628     AffineMatrix
12629       affine,
12630       current;
12631
12632     AV
12633       *av;
12634
12635     char
12636       *attribute;
12637
12638     double
12639       x,
12640       y;
12641
12642     DrawInfo
12643       *draw_info;
12644
12645     ExceptionInfo
12646       *exception;
12647
12648     GeometryInfo
12649       geometry_info;
12650
12651     Image
12652       *image;
12653
12654     MagickBooleanType
12655       status;
12656
12657     MagickStatusType
12658       flags;
12659
12660     register ssize_t
12661       i;
12662
12663     ssize_t
12664       type;
12665
12666     struct PackageInfo
12667       *info,
12668       *package_info;
12669
12670     SV
12671       *perl_exception,
12672       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12673
12674     TypeMetric
12675       metrics;
12676
12677     PERL_UNUSED_VAR(ref);
12678     PERL_UNUSED_VAR(ix);
12679     exception=AcquireExceptionInfo();
12680     package_info=(struct PackageInfo *) NULL;
12681     perl_exception=newSVpv("",0);
12682     reference=SvRV(ST(0));
12683     av=(AV *) reference;
12684     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12685       exception);
12686     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12687     if (image == (Image *) NULL)
12688       {
12689         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12690           PackageName);
12691         goto PerlException;
12692       }
12693     package_info=ClonePackageInfo(info,exception);
12694     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12695     CloneString(&draw_info->text,"");
12696     current=draw_info->affine;
12697     GetAffineMatrix(&affine);
12698     x=0.0;
12699     y=0.0;
12700     EXTEND(sp,7*items);
12701     for (i=2; i < items; i+=2)
12702     {
12703       attribute=(char *) SvPV(ST(i-1),na);
12704       switch (*attribute)
12705       {
12706         case 'A':
12707         case 'a':
12708         {
12709           if (LocaleCompare(attribute,"antialias") == 0)
12710             {
12711               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12712                 SvPV(ST(i),na));
12713               if (type < 0)
12714                 {
12715                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12716                     SvPV(ST(i),na));
12717                   break;
12718                 }
12719               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12720               break;
12721             }
12722           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12723             attribute);
12724           break;
12725         }
12726         case 'd':
12727         case 'D':
12728         {
12729           if (LocaleCompare(attribute,"density") == 0)
12730             {
12731               CloneString(&draw_info->density,SvPV(ST(i),na));
12732               break;
12733             }
12734           if (LocaleCompare(attribute,"direction") == 0)
12735             {
12736               draw_info->direction=(DirectionType) ParseCommandOption(
12737                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12738               break;
12739             }
12740           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12741             attribute);
12742           break;
12743         }
12744         case 'e':
12745         case 'E':
12746         {
12747           if (LocaleCompare(attribute,"encoding") == 0)
12748             {
12749               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12750               break;
12751             }
12752           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12753             attribute);
12754           break;
12755         }
12756         case 'f':
12757         case 'F':
12758         {
12759           if (LocaleCompare(attribute,"family") == 0)
12760             {
12761               CloneString(&draw_info->family,SvPV(ST(i),na));
12762               break;
12763             }
12764           if (LocaleCompare(attribute,"fill") == 0)
12765             {
12766               if (info)
12767                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12768                   &draw_info->fill,exception);
12769               break;
12770             }
12771           if (LocaleCompare(attribute,"font") == 0)
12772             {
12773               CloneString(&draw_info->font,SvPV(ST(i),na));
12774               break;
12775             }
12776           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12777             attribute);
12778           break;
12779         }
12780         case 'g':
12781         case 'G':
12782         {
12783           if (LocaleCompare(attribute,"geometry") == 0)
12784             {
12785               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12786               break;
12787             }
12788           if (LocaleCompare(attribute,"gravity") == 0)
12789             {
12790               draw_info->gravity=(GravityType) ParseCommandOption(
12791                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12792               break;
12793             }
12794           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12795             attribute);
12796           break;
12797         }
12798         case 'i':
12799         case 'I':
12800         {
12801           if (LocaleCompare(attribute,"interline-spacing") == 0)
12802             {
12803               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12804               draw_info->interline_spacing=geometry_info.rho;
12805               break;
12806             }
12807           if (LocaleCompare(attribute,"interword-spacing") == 0)
12808             {
12809               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12810               draw_info->interword_spacing=geometry_info.rho;
12811               break;
12812             }
12813           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12814             attribute);
12815           break;
12816         }
12817         case 'k':
12818         case 'K':
12819         {
12820           if (LocaleCompare(attribute,"kerning") == 0)
12821             {
12822               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12823               draw_info->kerning=geometry_info.rho;
12824               break;
12825             }
12826           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12827             attribute);
12828           break;
12829         }
12830         case 'p':
12831         case 'P':
12832         {
12833           if (LocaleCompare(attribute,"pointsize") == 0)
12834             {
12835               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12836               draw_info->pointsize=geometry_info.rho;
12837               break;
12838             }
12839           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12840             attribute);
12841           break;
12842         }
12843         case 'r':
12844         case 'R':
12845         {
12846           if (LocaleCompare(attribute,"rotate") == 0)
12847             {
12848               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12849               affine.rx=geometry_info.rho;
12850               affine.ry=geometry_info.sigma;
12851               if ((flags & SigmaValue) == 0)
12852                 affine.ry=affine.rx;
12853               break;
12854             }
12855           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12856             attribute);
12857           break;
12858         }
12859         case 's':
12860         case 'S':
12861         {
12862           if (LocaleCompare(attribute,"scale") == 0)
12863             {
12864               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12865               affine.sx=geometry_info.rho;
12866               affine.sy=geometry_info.sigma;
12867               if ((flags & SigmaValue) == 0)
12868                 affine.sy=affine.sx;
12869               break;
12870             }
12871           if (LocaleCompare(attribute,"skew") == 0)
12872             {
12873               double
12874                 x_angle,
12875                 y_angle;
12876
12877               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12878               x_angle=geometry_info.rho;
12879               y_angle=geometry_info.sigma;
12880               if ((flags & SigmaValue) == 0)
12881                 y_angle=x_angle;
12882               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12883               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12884               break;
12885             }
12886           if (LocaleCompare(attribute,"stroke") == 0)
12887             {
12888               if (info)
12889                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12890                   &draw_info->stroke,exception);
12891               break;
12892             }
12893           if (LocaleCompare(attribute,"style") == 0)
12894             {
12895               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12896                 SvPV(ST(i),na));
12897               if (type < 0)
12898                 {
12899                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12900                     SvPV(ST(i),na));
12901                   break;
12902                 }
12903               draw_info->style=(StyleType) type;
12904               break;
12905             }
12906           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12907             attribute);
12908           break;
12909         }
12910         case 't':
12911         case 'T':
12912         {
12913           if (LocaleCompare(attribute,"text") == 0)
12914             {
12915               CloneString(&draw_info->text,SvPV(ST(i),na));
12916               break;
12917             }
12918           if (LocaleCompare(attribute,"translate") == 0)
12919             {
12920               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12921               affine.tx=geometry_info.rho;
12922               affine.ty=geometry_info.sigma;
12923               if ((flags & SigmaValue) == 0)
12924                 affine.ty=affine.tx;
12925               break;
12926             }
12927           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12928             attribute);
12929           break;
12930         }
12931         case 'w':
12932         case 'W':
12933         {
12934           if (LocaleCompare(attribute,"weight") == 0)
12935             {
12936               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12937               draw_info->weight=(size_t) geometry_info.rho;
12938               break;
12939             }
12940           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12941             attribute);
12942           break;
12943         }
12944         case 'x':
12945         case 'X':
12946         {
12947           if (LocaleCompare(attribute,"x") == 0)
12948             {
12949               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12950               x=geometry_info.rho;
12951               break;
12952             }
12953           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12954             attribute);
12955           break;
12956         }
12957         case 'y':
12958         case 'Y':
12959         {
12960           if (LocaleCompare(attribute,"y") == 0)
12961             {
12962               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12963               y=geometry_info.rho;
12964               break;
12965             }
12966           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12967             attribute);
12968           break;
12969         }
12970         default:
12971         {
12972           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12973             attribute);
12974           break;
12975         }
12976       }
12977     }
12978     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12979     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12980     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12981     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12982     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12983     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12984     if (draw_info->geometry == (char *) NULL)
12985       {
12986         draw_info->geometry=AcquireString((char *) NULL);
12987         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12988           "%.20g,%.20g",x,y);
12989       }
12990     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12991     (void) CatchImageException(image);
12992     if (status == MagickFalse)
12993       PUSHs(&sv_undef);
12994     else
12995       {
12996         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12997         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12998         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12999         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13000         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13001         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13002         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13003         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13004         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13005         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13006         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13007         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13008         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13009       }
13010     draw_info=DestroyDrawInfo(draw_info);
13011
13012   PerlException:
13013     if (package_info != (struct PackageInfo *) NULL)
13014       DestroyPackageInfo(package_info);
13015     InheritPerlException(exception,perl_exception);
13016     exception=DestroyExceptionInfo(exception);
13017     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13018   }
13019 \f
13020 #
13021 ###############################################################################
13022 #                                                                             #
13023 #                                                                             #
13024 #                                                                             #
13025 #   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                         #
13026 #                                                                             #
13027 #                                                                             #
13028 #                                                                             #
13029 ###############################################################################
13030 #
13031 #
13032 void
13033 QueryMultilineFontMetrics(ref,...)
13034   Image::Magick ref=NO_INIT
13035   ALIAS:
13036     querymultilinefontmetrics = 1
13037   PPCODE:
13038   {
13039     AffineMatrix
13040       affine,
13041       current;
13042
13043     AV
13044       *av;
13045
13046     char
13047       *attribute;
13048
13049     double
13050       x,
13051       y;
13052
13053     DrawInfo
13054       *draw_info;
13055
13056     ExceptionInfo
13057       *exception;
13058
13059     GeometryInfo
13060       geometry_info;
13061
13062     Image
13063       *image;
13064
13065     MagickBooleanType
13066       status;
13067
13068     MagickStatusType
13069       flags;
13070
13071     register ssize_t
13072       i;
13073
13074     ssize_t
13075       type;
13076
13077     struct PackageInfo
13078       *info,
13079       *package_info;
13080
13081     SV
13082       *perl_exception,
13083       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13084
13085     TypeMetric
13086       metrics;
13087
13088     PERL_UNUSED_VAR(ref);
13089     PERL_UNUSED_VAR(ix);
13090     exception=AcquireExceptionInfo();
13091     package_info=(struct PackageInfo *) NULL;
13092     perl_exception=newSVpv("",0);
13093     reference=SvRV(ST(0));
13094     av=(AV *) reference;
13095     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13096       exception);
13097     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13098     if (image == (Image *) NULL)
13099       {
13100         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13101           PackageName);
13102         goto PerlException;
13103       }
13104     package_info=ClonePackageInfo(info,exception);
13105     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13106     CloneString(&draw_info->text,"");
13107     current=draw_info->affine;
13108     GetAffineMatrix(&affine);
13109     x=0.0;
13110     y=0.0;
13111     EXTEND(sp,7*items);
13112     for (i=2; i < items; i+=2)
13113     {
13114       attribute=(char *) SvPV(ST(i-1),na);
13115       switch (*attribute)
13116       {
13117         case 'A':
13118         case 'a':
13119         {
13120           if (LocaleCompare(attribute,"antialias") == 0)
13121             {
13122               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13123                 SvPV(ST(i),na));
13124               if (type < 0)
13125                 {
13126                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13127                     SvPV(ST(i),na));
13128                   break;
13129                 }
13130               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13131               break;
13132             }
13133           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13134             attribute);
13135           break;
13136         }
13137         case 'd':
13138         case 'D':
13139         {
13140           if (LocaleCompare(attribute,"density") == 0)
13141             {
13142               CloneString(&draw_info->density,SvPV(ST(i),na));
13143               break;
13144             }
13145           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13146             attribute);
13147           break;
13148         }
13149         case 'e':
13150         case 'E':
13151         {
13152           if (LocaleCompare(attribute,"encoding") == 0)
13153             {
13154               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13155               break;
13156             }
13157           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13158             attribute);
13159           break;
13160         }
13161         case 'f':
13162         case 'F':
13163         {
13164           if (LocaleCompare(attribute,"family") == 0)
13165             {
13166               CloneString(&draw_info->family,SvPV(ST(i),na));
13167               break;
13168             }
13169           if (LocaleCompare(attribute,"fill") == 0)
13170             {
13171               if (info)
13172                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13173                   &draw_info->fill,exception);
13174               break;
13175             }
13176           if (LocaleCompare(attribute,"font") == 0)
13177             {
13178               CloneString(&draw_info->font,SvPV(ST(i),na));
13179               break;
13180             }
13181           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13182             attribute);
13183           break;
13184         }
13185         case 'g':
13186         case 'G':
13187         {
13188           if (LocaleCompare(attribute,"geometry") == 0)
13189             {
13190               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13191               break;
13192             }
13193           if (LocaleCompare(attribute,"gravity") == 0)
13194             {
13195               draw_info->gravity=(GravityType) ParseCommandOption(
13196                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13197               break;
13198             }
13199           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13200             attribute);
13201           break;
13202         }
13203         case 'p':
13204         case 'P':
13205         {
13206           if (LocaleCompare(attribute,"pointsize") == 0)
13207             {
13208               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13209               draw_info->pointsize=geometry_info.rho;
13210               break;
13211             }
13212           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13213             attribute);
13214           break;
13215         }
13216         case 'r':
13217         case 'R':
13218         {
13219           if (LocaleCompare(attribute,"rotate") == 0)
13220             {
13221               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13222               affine.rx=geometry_info.rho;
13223               affine.ry=geometry_info.sigma;
13224               if ((flags & SigmaValue) == 0)
13225                 affine.ry=affine.rx;
13226               break;
13227             }
13228           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13229             attribute);
13230           break;
13231         }
13232         case 's':
13233         case 'S':
13234         {
13235           if (LocaleCompare(attribute,"scale") == 0)
13236             {
13237               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13238               affine.sx=geometry_info.rho;
13239               affine.sy=geometry_info.sigma;
13240               if ((flags & SigmaValue) == 0)
13241                 affine.sy=affine.sx;
13242               break;
13243             }
13244           if (LocaleCompare(attribute,"skew") == 0)
13245             {
13246               double
13247                 x_angle,
13248                 y_angle;
13249
13250               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13251               x_angle=geometry_info.rho;
13252               y_angle=geometry_info.sigma;
13253               if ((flags & SigmaValue) == 0)
13254                 y_angle=x_angle;
13255               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13256               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13257               break;
13258             }
13259           if (LocaleCompare(attribute,"stroke") == 0)
13260             {
13261               if (info)
13262                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13263                   &draw_info->stroke,exception);
13264               break;
13265             }
13266           if (LocaleCompare(attribute,"style") == 0)
13267             {
13268               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13269                 SvPV(ST(i),na));
13270               if (type < 0)
13271                 {
13272                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13273                     SvPV(ST(i),na));
13274                   break;
13275                 }
13276               draw_info->style=(StyleType) type;
13277               break;
13278             }
13279           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13280             attribute);
13281           break;
13282         }
13283         case 't':
13284         case 'T':
13285         {
13286           if (LocaleCompare(attribute,"text") == 0)
13287             {
13288               CloneString(&draw_info->text,SvPV(ST(i),na));
13289               break;
13290             }
13291           if (LocaleCompare(attribute,"translate") == 0)
13292             {
13293               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13294               affine.tx=geometry_info.rho;
13295               affine.ty=geometry_info.sigma;
13296               if ((flags & SigmaValue) == 0)
13297                 affine.ty=affine.tx;
13298               break;
13299             }
13300           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13301             attribute);
13302           break;
13303         }
13304         case 'w':
13305         case 'W':
13306         {
13307           if (LocaleCompare(attribute,"weight") == 0)
13308             {
13309               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13310               draw_info->weight=(size_t) geometry_info.rho;
13311               break;
13312             }
13313           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13314             attribute);
13315           break;
13316         }
13317         case 'x':
13318         case 'X':
13319         {
13320           if (LocaleCompare(attribute,"x") == 0)
13321             {
13322               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13323               x=geometry_info.rho;
13324               break;
13325             }
13326           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13327             attribute);
13328           break;
13329         }
13330         case 'y':
13331         case 'Y':
13332         {
13333           if (LocaleCompare(attribute,"y") == 0)
13334             {
13335               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13336               y=geometry_info.rho;
13337               break;
13338             }
13339           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13340             attribute);
13341           break;
13342         }
13343         default:
13344         {
13345           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13346             attribute);
13347           break;
13348         }
13349       }
13350     }
13351     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13352     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13353     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13354     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13355     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13356     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13357     if (draw_info->geometry == (char *) NULL)
13358       {
13359         draw_info->geometry=AcquireString((char *) NULL);
13360         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13361           "%.20g,%.20g",x,y);
13362       }
13363     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13364     (void) CatchException(exception);
13365     if (status == MagickFalse)
13366       PUSHs(&sv_undef);
13367     else
13368       {
13369         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13370         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13371         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13372         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13373         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13374         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13375         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13376         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13377         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13378         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13379         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13380         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13381         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13382       }
13383     draw_info=DestroyDrawInfo(draw_info);
13384
13385   PerlException:
13386     if (package_info != (struct PackageInfo *) NULL)
13387       DestroyPackageInfo(package_info);
13388     InheritPerlException(exception,perl_exception);
13389     exception=DestroyExceptionInfo(exception);
13390     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13391   }
13392 \f
13393 #
13394 ###############################################################################
13395 #                                                                             #
13396 #                                                                             #
13397 #                                                                             #
13398 #   Q u e r y F o r m a t                                                     #
13399 #                                                                             #
13400 #                                                                             #
13401 #                                                                             #
13402 ###############################################################################
13403 #
13404 #
13405 void
13406 QueryFormat(ref,...)
13407   Image::Magick ref=NO_INIT
13408   ALIAS:
13409     queryformat = 1
13410   PPCODE:
13411   {
13412     char
13413       *name;
13414
13415     ExceptionInfo
13416       *exception;
13417
13418     register ssize_t
13419       i;
13420
13421     SV
13422       *perl_exception;
13423
13424     volatile const MagickInfo
13425       *magick_info;
13426
13427     PERL_UNUSED_VAR(ref);
13428     PERL_UNUSED_VAR(ix);
13429     exception=AcquireExceptionInfo();
13430     perl_exception=newSVpv("",0);
13431     if (items == 1)
13432       {
13433         char
13434           format[MagickPathExtent];
13435
13436         const MagickInfo
13437           **format_list;
13438
13439         size_t
13440           types;
13441
13442         format_list=GetMagickInfoList("*",&types,exception);
13443         EXTEND(sp,types);
13444         for (i=0; i < (ssize_t) types; i++)
13445         {
13446           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13447           LocaleLower(format);
13448           PUSHs(sv_2mortal(newSVpv(format,0)));
13449         }
13450         format_list=(const MagickInfo **)
13451           RelinquishMagickMemory((MagickInfo *) format_list);
13452         goto PerlException;
13453       }
13454     EXTEND(sp,8*items);
13455     for (i=1; i < items; i++)
13456     {
13457       name=(char *) SvPV(ST(i),na);
13458       magick_info=GetMagickInfo(name,exception);
13459       if (magick_info == (const MagickInfo *) NULL)
13460         {
13461           PUSHs(&sv_undef);
13462           continue;
13463         }
13464       if (magick_info->description == (char *) NULL)
13465         PUSHs(&sv_undef);
13466       else
13467         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13468       if (magick_info->module == (char *) NULL)
13469         PUSHs(&sv_undef);
13470       else
13471         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13472     }
13473
13474   PerlException:
13475     InheritPerlException(exception,perl_exception);
13476     exception=DestroyExceptionInfo(exception);
13477     SvREFCNT_dec(perl_exception);
13478   }
13479 \f
13480 #
13481 ###############################################################################
13482 #                                                                             #
13483 #                                                                             #
13484 #                                                                             #
13485 #   Q u e r y O p t i o n                                                     #
13486 #                                                                             #
13487 #                                                                             #
13488 #                                                                             #
13489 ###############################################################################
13490 #
13491 #
13492 void
13493 QueryOption(ref,...)
13494   Image::Magick ref=NO_INIT
13495   ALIAS:
13496     queryoption = 1
13497   PPCODE:
13498   {
13499     char
13500       **options;
13501
13502     ExceptionInfo
13503       *exception;
13504
13505     register ssize_t
13506       i;
13507
13508     ssize_t
13509       j,
13510       option;
13511
13512     SV
13513       *perl_exception;
13514
13515     PERL_UNUSED_VAR(ref);
13516     PERL_UNUSED_VAR(ix);
13517     exception=AcquireExceptionInfo();
13518     perl_exception=newSVpv("",0);
13519     EXTEND(sp,8*items);
13520     for (i=1; i < items; i++)
13521     {
13522       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13523         SvPV(ST(i),na));
13524       options=GetCommandOptions((CommandOption) option);
13525       if (options == (char **) NULL)
13526         PUSHs(&sv_undef);
13527       else
13528         {
13529           for (j=0; options[j] != (char *) NULL; j++)
13530             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13531           options=DestroyStringList(options);
13532         }
13533     }
13534
13535     InheritPerlException(exception,perl_exception);
13536     exception=DestroyExceptionInfo(exception);
13537     SvREFCNT_dec(perl_exception);
13538   }
13539 \f
13540 #
13541 ###############################################################################
13542 #                                                                             #
13543 #                                                                             #
13544 #                                                                             #
13545 #   R e a d                                                                   #
13546 #                                                                             #
13547 #                                                                             #
13548 #                                                                             #
13549 ###############################################################################
13550 #
13551 #
13552 void
13553 Read(ref,...)
13554   Image::Magick ref=NO_INIT
13555   ALIAS:
13556     ReadImage  = 1
13557     read       = 2
13558     readimage  = 3
13559   PPCODE:
13560   {
13561     AV
13562       *av;
13563
13564     char
13565       **keep,
13566       **list;
13567
13568     ExceptionInfo
13569       *exception;
13570
13571     HV
13572       *hv;
13573
13574     Image
13575       *image;
13576
13577     int
13578       n;
13579
13580     MagickBooleanType
13581       status;
13582
13583     register char
13584       **p;
13585
13586     register ssize_t
13587       i;
13588
13589     ssize_t
13590       ac,
13591       number_images;
13592
13593     STRLEN
13594       *length;
13595
13596     struct PackageInfo
13597       *info,
13598       *package_info;
13599
13600     SV
13601       *perl_exception,  /* Perl variable for storing messages */
13602       *reference,
13603       *rv,
13604       *sv;
13605
13606     PERL_UNUSED_VAR(ref);
13607     PERL_UNUSED_VAR(ix);
13608     exception=AcquireExceptionInfo();
13609     perl_exception=newSVpv("",0);
13610     sv=NULL;
13611     package_info=(struct PackageInfo *) NULL;
13612     number_images=0;
13613     ac=(items < 2) ? 1 : items-1;
13614     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13615     keep=list;
13616     length=(STRLEN *) NULL;
13617     if (list == (char **) NULL)
13618       {
13619         ThrowPerlException(exception,ResourceLimitError,
13620           "MemoryAllocationFailed",PackageName);
13621         goto PerlException;
13622       }
13623     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13624     if (length == (STRLEN *) NULL)
13625       {
13626         ThrowPerlException(exception,ResourceLimitError,
13627           "MemoryAllocationFailed",PackageName);
13628         goto PerlException;
13629       }
13630     if (sv_isobject(ST(0)) == 0)
13631       {
13632         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13633           PackageName);
13634         goto PerlException;
13635       }
13636     reference=SvRV(ST(0));
13637     hv=SvSTASH(reference);
13638     if (SvTYPE(reference) != SVt_PVAV)
13639       {
13640         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13641           PackageName);
13642         goto PerlException;
13643       }
13644     av=(AV *) reference;
13645     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13646       exception);
13647     package_info=ClonePackageInfo(info,exception);
13648     n=1;
13649     if (items <= 1)
13650       *list=(char *) (*package_info->image_info->filename ?
13651         package_info->image_info->filename : "XC:black");
13652     else
13653       for (n=0, i=0; i < ac; i++)
13654       {
13655         list[n]=(char *) SvPV(ST(i+1),length[n]);
13656         if ((items >= 3) && strEQcase(list[n],"blob"))
13657           {
13658             void
13659               *blob;
13660
13661             i++;
13662             blob=(void *) (SvPV(ST(i+1),length[n]));
13663             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13664           }
13665         if ((items >= 3) && strEQcase(list[n],"filename"))
13666           continue;
13667         if ((items >= 3) && strEQcase(list[n],"file"))
13668           {
13669             FILE
13670               *file;
13671
13672             PerlIO
13673               *io_info;
13674
13675             i++;
13676             io_info=IoIFP(sv_2io(ST(i+1)));
13677             if (io_info == (PerlIO *) NULL)
13678               {
13679                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13680                   PackageName);
13681                 continue;
13682               }
13683             file=PerlIO_findFILE(io_info);
13684             if (file == (FILE *) NULL)
13685               {
13686                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13687                   PackageName);
13688                 continue;
13689               }
13690             SetImageInfoFile(package_info->image_info,file);
13691           }
13692         if ((items >= 3) && strEQcase(list[n],"magick"))
13693           continue;
13694         n++;
13695       }
13696     list[n]=(char *) NULL;
13697     keep=list;
13698     status=ExpandFilenames(&n,&list);
13699     if (status == MagickFalse)
13700       {
13701         ThrowPerlException(exception,ResourceLimitError,
13702           "MemoryAllocationFailed",PackageName);
13703         goto PerlException;
13704       }
13705     number_images=0;
13706     for (i=0; i < n; i++)
13707     {
13708       if ((package_info->image_info->file == (FILE *) NULL) &&
13709           (package_info->image_info->blob == (void *) NULL))
13710         image=ReadImages(package_info->image_info,list[i],exception);
13711       else
13712         {
13713           image=ReadImages(package_info->image_info,
13714             package_info->image_info->filename,exception);
13715           if (image != (Image *) NULL)
13716             DisassociateImageStream(image);
13717         }
13718       if (image == (Image *) NULL)
13719         break;
13720       for ( ; image; image=image->next)
13721       {
13722         AddImageToRegistry(sv,image);
13723         rv=newRV(sv);
13724         av_push(av,sv_bless(rv,hv));
13725         SvREFCNT_dec(sv);
13726         number_images++;
13727       }
13728     }
13729     /*
13730       Free resources.
13731     */
13732     for (i=0; i < n; i++)
13733       if (list[i] != (char *) NULL)
13734         for (p=keep; list[i] != *p++; )
13735           if (*p == (char *) NULL)
13736             {
13737               list[i]=(char *) RelinquishMagickMemory(list[i]);
13738               break;
13739             }
13740
13741   PerlException:
13742     if (package_info != (struct PackageInfo *) NULL)
13743       DestroyPackageInfo(package_info);
13744     if (list && (list != keep))
13745       list=(char **) RelinquishMagickMemory(list);
13746     if (keep)
13747       keep=(char **) RelinquishMagickMemory(keep);
13748     if (length)
13749       length=(STRLEN *) RelinquishMagickMemory(length);
13750     InheritPerlException(exception,perl_exception);
13751     exception=DestroyExceptionInfo(exception);
13752     sv_setiv(perl_exception,(IV) number_images);
13753     SvPOK_on(perl_exception);
13754     ST(0)=sv_2mortal(perl_exception);
13755     XSRETURN(1);
13756   }
13757 \f
13758 #
13759 ###############################################################################
13760 #                                                                             #
13761 #                                                                             #
13762 #                                                                             #
13763 #   R e m o t e                                                               #
13764 #                                                                             #
13765 #                                                                             #
13766 #                                                                             #
13767 ###############################################################################
13768 #
13769 #
13770 void
13771 Remote(ref,...)
13772   Image::Magick ref=NO_INIT
13773   ALIAS:
13774     RemoteCommand  = 1
13775     remote         = 2
13776     remoteCommand  = 3
13777   PPCODE:
13778   {
13779     AV
13780       *av;
13781
13782     ExceptionInfo
13783       *exception;
13784
13785     register ssize_t
13786       i;
13787
13788     SV
13789       *perl_exception,
13790       *reference;
13791
13792     struct PackageInfo
13793       *info;
13794
13795     PERL_UNUSED_VAR(ref);
13796     PERL_UNUSED_VAR(ix);
13797     exception=AcquireExceptionInfo();
13798     perl_exception=newSVpv("",0);
13799     reference=SvRV(ST(0));
13800     av=(AV *) reference;
13801     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13802       exception);
13803     for (i=1; i < items; i++)
13804       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13805         SvPV(ST(i),na),exception);
13806     InheritPerlException(exception,perl_exception);
13807     exception=DestroyExceptionInfo(exception);
13808     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13809   }
13810 \f
13811 #
13812 ###############################################################################
13813 #                                                                             #
13814 #                                                                             #
13815 #                                                                             #
13816 #   S e t                                                                     #
13817 #                                                                             #
13818 #                                                                             #
13819 #                                                                             #
13820 ###############################################################################
13821 #
13822 #
13823 void
13824 Set(ref,...)
13825   Image::Magick ref=NO_INIT
13826   ALIAS:
13827     SetAttributes  = 1
13828     SetAttribute   = 2
13829     set            = 3
13830     setattributes  = 4
13831     setattribute   = 5
13832   PPCODE:
13833   {
13834     ExceptionInfo
13835       *exception;
13836
13837     Image
13838       *image;
13839
13840     register ssize_t
13841       i;
13842
13843     struct PackageInfo
13844       *info;
13845
13846     SV
13847       *perl_exception,
13848       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13849
13850     PERL_UNUSED_VAR(ref);
13851     PERL_UNUSED_VAR(ix);
13852     exception=AcquireExceptionInfo();
13853     perl_exception=newSVpv("",0);
13854     if (sv_isobject(ST(0)) == 0)
13855       {
13856         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13857           PackageName);
13858         goto PerlException;
13859       }
13860     reference=SvRV(ST(0));
13861     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13862     if (items == 2)
13863       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13864     else
13865       for (i=2; i < items; i+=2)
13866         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13867
13868   PerlException:
13869     InheritPerlException(exception,perl_exception);
13870     exception=DestroyExceptionInfo(exception);
13871     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13872     SvPOK_on(perl_exception);
13873     ST(0)=sv_2mortal(perl_exception);
13874     XSRETURN(1);
13875   }
13876 \f
13877 #
13878 ###############################################################################
13879 #                                                                             #
13880 #                                                                             #
13881 #                                                                             #
13882 #   S e t P i x e l                                                           #
13883 #                                                                             #
13884 #                                                                             #
13885 #                                                                             #
13886 ###############################################################################
13887 #
13888 #
13889 void
13890 SetPixel(ref,...)
13891   Image::Magick ref=NO_INIT
13892   ALIAS:
13893     setpixel = 1
13894     setPixel = 2
13895   PPCODE:
13896   {
13897     AV
13898       *av;
13899
13900     char
13901       *attribute;
13902
13903     ChannelType
13904       channel,
13905       channel_mask;
13906
13907     ExceptionInfo
13908       *exception;
13909
13910     Image
13911       *image;
13912
13913     MagickBooleanType
13914       normalize;
13915
13916     RectangleInfo
13917       region;
13918
13919     register ssize_t
13920       i;
13921
13922     register Quantum
13923       *q;
13924
13925     ssize_t
13926       option;
13927
13928     struct PackageInfo
13929       *info;
13930
13931     SV
13932       *perl_exception,
13933       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13934
13935     PERL_UNUSED_VAR(ref);
13936     PERL_UNUSED_VAR(ix);
13937     exception=AcquireExceptionInfo();
13938     perl_exception=newSVpv("",0);
13939     reference=SvRV(ST(0));
13940     av=(AV *) reference;
13941     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13942       exception);
13943     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13944     if (image == (Image *) NULL)
13945       {
13946         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13947           PackageName);
13948         goto PerlException;
13949       }
13950     av=(AV *) NULL;
13951     normalize=MagickTrue;
13952     region.x=0;
13953     region.y=0;
13954     region.width=image->columns;
13955     region.height=1;
13956     if (items == 1)
13957       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13958     channel=DefaultChannels;
13959     for (i=2; i < items; i+=2)
13960     {
13961       attribute=(char *) SvPV(ST(i-1),na);
13962       switch (*attribute)
13963       {
13964         case 'C':
13965         case 'c':
13966         {
13967           if (LocaleCompare(attribute,"channel") == 0)
13968             {
13969               ssize_t
13970                 option;
13971
13972               option=ParseChannelOption(SvPV(ST(i),na));
13973               if (option < 0)
13974                 {
13975                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13976                     SvPV(ST(i),na));
13977                   return;
13978                 }
13979               channel=(ChannelType) option;
13980               break;
13981             }
13982           if (LocaleCompare(attribute,"color") == 0)
13983             {
13984               if (SvTYPE(ST(i)) != SVt_RV)
13985                 {
13986                   char
13987                     message[MagickPathExtent];
13988
13989                   (void) FormatLocaleString(message,MagickPathExtent,
13990                     "invalid %.60s value",attribute);
13991                   ThrowPerlException(exception,OptionError,message,
13992                     SvPV(ST(i),na));
13993                 }
13994               av=(AV *) SvRV(ST(i));
13995               break;
13996             }
13997           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13998             attribute);
13999           break;
14000         }
14001         case 'g':
14002         case 'G':
14003         {
14004           if (LocaleCompare(attribute,"geometry") == 0)
14005             {
14006               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14007               break;
14008             }
14009           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14010             attribute);
14011           break;
14012         }
14013         case 'N':
14014         case 'n':
14015         {
14016           if (LocaleCompare(attribute,"normalize") == 0)
14017             {
14018               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14019                 SvPV(ST(i),na));
14020               if (option < 0)
14021                 {
14022                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14023                     SvPV(ST(i),na));
14024                   break;
14025                 }
14026              normalize=option != 0 ? MagickTrue : MagickFalse;
14027              break;
14028             }
14029           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14030             attribute);
14031           break;
14032         }
14033         case 'x':
14034         case 'X':
14035         {
14036           if (LocaleCompare(attribute,"x") == 0)
14037             {
14038               region.x=SvIV(ST(i));
14039               break;
14040             }
14041           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14042             attribute);
14043           break;
14044         }
14045         case 'y':
14046         case 'Y':
14047         {
14048           if (LocaleCompare(attribute,"y") == 0)
14049             {
14050               region.y=SvIV(ST(i));
14051               break;
14052             }
14053           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14054             attribute);
14055           break;
14056         }
14057         default:
14058         {
14059           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14060             attribute);
14061           break;
14062         }
14063       }
14064     }
14065     (void) SetImageStorageClass(image,DirectClass,exception);
14066     channel_mask=SetImageChannelMask(image,channel);
14067     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14068     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14069         (SvTYPE(av) != SVt_PVAV))
14070       PUSHs(&sv_undef);
14071     else
14072       {
14073         double
14074           scale;
14075
14076         register ssize_t
14077           i;
14078
14079         i=0;
14080         scale=1.0;
14081         if (normalize != MagickFalse)
14082           scale=QuantumRange;
14083         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14084             (i <= av_len(av)))
14085           {
14086             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14087               av_fetch(av,i,0)))),q);
14088             i++;
14089           }
14090         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14091             (i <= av_len(av)))
14092           {
14093             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14094               av_fetch(av,i,0)))),q);
14095             i++;
14096           }
14097         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14098             (i <= av_len(av)))
14099           {
14100             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14101               av_fetch(av,i,0)))),q);
14102             i++;
14103           }
14104         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14105             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14106           {
14107             SetPixelBlack(image,ClampToQuantum(scale*
14108               SvNV(*(av_fetch(av,i,0)))),q);
14109             i++;
14110           }
14111         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14112             (i <= av_len(av)))
14113           {
14114             SetPixelAlpha(image,ClampToQuantum(scale*
14115               SvNV(*(av_fetch(av,i,0)))),q);
14116             i++;
14117           }
14118         (void) SyncAuthenticPixels(image,exception);
14119       }
14120     (void) SetImageChannelMask(image,channel_mask);
14121
14122   PerlException:
14123     InheritPerlException(exception,perl_exception);
14124     exception=DestroyExceptionInfo(exception);
14125     SvREFCNT_dec(perl_exception);
14126   }
14127 \f
14128 #
14129 ###############################################################################
14130 #                                                                             #
14131 #                                                                             #
14132 #                                                                             #
14133 #   S m u s h                                                                 #
14134 #                                                                             #
14135 #                                                                             #
14136 #                                                                             #
14137 ###############################################################################
14138 #
14139 #
14140 void
14141 Smush(ref,...)
14142   Image::Magick ref=NO_INIT
14143   ALIAS:
14144     SmushImage  = 1
14145     smush       = 2
14146     smushimage  = 3
14147   PPCODE:
14148   {
14149     AV
14150       *av;
14151
14152     char
14153       *attribute;
14154
14155     ExceptionInfo
14156       *exception;
14157
14158     HV
14159       *hv;
14160
14161     Image
14162       *image;
14163
14164     register ssize_t
14165       i;
14166
14167     ssize_t
14168       offset,
14169       stack;
14170
14171     struct PackageInfo
14172       *info;
14173
14174     SV
14175       *av_reference,
14176       *perl_exception,
14177       *reference,
14178       *rv,
14179       *sv;
14180
14181     PERL_UNUSED_VAR(ref);
14182     PERL_UNUSED_VAR(ix);
14183     exception=AcquireExceptionInfo();
14184     perl_exception=newSVpv("",0);
14185     sv=NULL;
14186     attribute=NULL;
14187     av=NULL;
14188     if (sv_isobject(ST(0)) == 0)
14189       {
14190         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14191           PackageName);
14192         goto PerlException;
14193       }
14194     reference=SvRV(ST(0));
14195     hv=SvSTASH(reference);
14196     av=newAV();
14197     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14198     SvREFCNT_dec(av);
14199     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14200     if (image == (Image *) NULL)
14201       {
14202         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14203           PackageName);
14204         goto PerlException;
14205       }
14206     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14207     /*
14208       Get options.
14209     */
14210     offset=0;
14211     stack=MagickTrue;
14212     for (i=2; i < items; i+=2)
14213     {
14214       attribute=(char *) SvPV(ST(i-1),na);
14215       switch (*attribute)
14216       {
14217         case 'O':
14218         case 'o':
14219         {
14220           if (LocaleCompare(attribute,"offset") == 0)
14221             {
14222               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14223               break;
14224             }
14225           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14226             attribute);
14227           break;
14228         }
14229         case 'S':
14230         case 's':
14231         {
14232           if (LocaleCompare(attribute,"stack") == 0)
14233             {
14234               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14235                 SvPV(ST(i),na));
14236               if (stack < 0)
14237                 {
14238                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14239                     SvPV(ST(i),na));
14240                   return;
14241                 }
14242               break;
14243             }
14244           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14245             attribute);
14246           break;
14247         }
14248         default:
14249         {
14250           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14251             attribute);
14252           break;
14253         }
14254       }
14255     }
14256     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14257       exception);
14258     if (image == (Image *) NULL)
14259       goto PerlException;
14260     for ( ; image; image=image->next)
14261     {
14262       AddImageToRegistry(sv,image);
14263       rv=newRV(sv);
14264       av_push(av,sv_bless(rv,hv));
14265       SvREFCNT_dec(sv);
14266     }
14267     exception=DestroyExceptionInfo(exception);
14268     ST(0)=av_reference;
14269     SvREFCNT_dec(perl_exception);
14270     XSRETURN(1);
14271
14272   PerlException:
14273     InheritPerlException(exception,perl_exception);
14274     exception=DestroyExceptionInfo(exception);
14275     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14276     SvPOK_on(perl_exception);
14277     ST(0)=sv_2mortal(perl_exception);
14278     XSRETURN(1);
14279   }
14280 \f
14281 #
14282 ###############################################################################
14283 #                                                                             #
14284 #                                                                             #
14285 #                                                                             #
14286 #   S t a t i s t i c s                                                       #
14287 #                                                                             #
14288 #                                                                             #
14289 #                                                                             #
14290 ###############################################################################
14291 #
14292 #
14293 void
14294 Statistics(ref,...)
14295   Image::Magick ref=NO_INIT
14296   ALIAS:
14297     StatisticsImage = 1
14298     statistics      = 2
14299     statisticsimage = 3
14300   PPCODE:
14301   {
14302 #define ChannelStatistics(channel) \
14303 { \
14304   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14305     (double) channel_statistics[channel].depth); \
14306   PUSHs(sv_2mortal(newSVpv(message,0))); \
14307   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14308     channel_statistics[channel].minima/QuantumRange); \
14309   PUSHs(sv_2mortal(newSVpv(message,0))); \
14310   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14311     channel_statistics[channel].maxima/QuantumRange); \
14312   PUSHs(sv_2mortal(newSVpv(message,0))); \
14313   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14314     channel_statistics[channel].mean/QuantumRange); \
14315   PUSHs(sv_2mortal(newSVpv(message,0))); \
14316   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14317     channel_statistics[channel].standard_deviation/QuantumRange); \
14318   PUSHs(sv_2mortal(newSVpv(message,0))); \
14319   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14320     channel_statistics[channel].kurtosis); \
14321   PUSHs(sv_2mortal(newSVpv(message,0))); \
14322   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14323     channel_statistics[channel].skewness); \
14324   PUSHs(sv_2mortal(newSVpv(message,0))); \
14325   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14326     channel_statistics[channel].entropy); \
14327   PUSHs(sv_2mortal(newSVpv(message,0))); \
14328 }
14329
14330     AV
14331       *av;
14332
14333     char
14334       message[MagickPathExtent];
14335
14336     ChannelStatistics
14337       *channel_statistics;
14338
14339     ExceptionInfo
14340       *exception;
14341
14342     Image
14343       *image;
14344
14345     ssize_t
14346       count;
14347
14348     struct PackageInfo
14349       *info;
14350
14351     SV
14352       *perl_exception,
14353       *reference;
14354
14355     PERL_UNUSED_VAR(ref);
14356     PERL_UNUSED_VAR(ix);
14357     exception=AcquireExceptionInfo();
14358     perl_exception=newSVpv("",0);
14359     av=NULL;
14360     if (sv_isobject(ST(0)) == 0)
14361       {
14362         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14363           PackageName);
14364         goto PerlException;
14365       }
14366     reference=SvRV(ST(0));
14367     av=newAV();
14368     SvREFCNT_dec(av);
14369     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14370     if (image == (Image *) NULL)
14371       {
14372         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14373           PackageName);
14374         goto PerlException;
14375       }
14376     count=0;
14377     for ( ; image; image=image->next)
14378     {
14379       register size_t
14380         i;
14381
14382       channel_statistics=GetImageStatistics(image,exception);
14383       if (channel_statistics == (ChannelStatistics *) NULL)
14384         continue;
14385       count++;
14386       for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
14387       {
14388         PixelChannel channel=GetPixelChannelChannel(image,i);
14389         PixelTrait traits=GetPixelChannelTraits(image,channel);
14390         if (traits == UndefinedPixelTrait)
14391           continue;
14392         EXTEND(sp,8*(i+1)*count);
14393         ChannelStatistics(channel);
14394       }
14395       EXTEND(sp,8*(i+1)*count);
14396       ChannelStatistics(CompositePixelChannel);
14397       channel_statistics=(ChannelStatistics *)
14398         RelinquishMagickMemory(channel_statistics);
14399     }
14400
14401   PerlException:
14402     InheritPerlException(exception,perl_exception);
14403     exception=DestroyExceptionInfo(exception);
14404     SvREFCNT_dec(perl_exception);
14405   }
14406 \f
14407 #
14408 ###############################################################################
14409 #                                                                             #
14410 #                                                                             #
14411 #                                                                             #
14412 #   S y n c A u t h e n t i c P i x e l s                                     #
14413 #                                                                             #
14414 #                                                                             #
14415 #                                                                             #
14416 ###############################################################################
14417 #
14418 #
14419 void
14420 SyncAuthenticPixels(ref,...)
14421   Image::Magick ref = NO_INIT
14422   ALIAS:
14423     Syncauthenticpixels = 1
14424     SyncImagePixels = 2
14425     syncimagepixels = 3
14426   CODE:
14427   {
14428     ExceptionInfo
14429       *exception;
14430
14431     Image
14432       *image;
14433
14434     MagickBooleanType
14435       status;
14436
14437     struct PackageInfo
14438       *info;
14439
14440     SV
14441       *perl_exception,
14442       *reference;
14443
14444     PERL_UNUSED_VAR(ref);
14445     PERL_UNUSED_VAR(ix);
14446     exception=AcquireExceptionInfo();
14447     perl_exception=newSVpv("",0);
14448     if (sv_isobject(ST(0)) == 0)
14449       {
14450         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14451           PackageName);
14452         goto PerlException;
14453       }
14454
14455     reference=SvRV(ST(0));
14456     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14457     if (image == (Image *) NULL)
14458       {
14459         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14460           PackageName);
14461         goto PerlException;
14462       }
14463
14464     status=SyncAuthenticPixels(image,exception);
14465     if (status != MagickFalse)
14466       return;
14467
14468   PerlException:
14469     InheritPerlException(exception,perl_exception);
14470     exception=DestroyExceptionInfo(exception);
14471     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14472   }
14473 \f
14474 #
14475 ###############################################################################
14476 #                                                                             #
14477 #                                                                             #
14478 #                                                                             #
14479 #   W r i t e                                                                 #
14480 #                                                                             #
14481 #                                                                             #
14482 #                                                                             #
14483 ###############################################################################
14484 #
14485 #
14486 void
14487 Write(ref,...)
14488   Image::Magick ref=NO_INIT
14489   ALIAS:
14490     WriteImage    = 1
14491     write         = 2
14492     writeimage    = 3
14493   PPCODE:
14494   {
14495     char
14496       filename[MagickPathExtent];
14497
14498     ExceptionInfo
14499       *exception;
14500
14501     Image
14502       *image,
14503       *next;
14504
14505     register ssize_t
14506       i;
14507
14508     ssize_t
14509       number_images,
14510       scene;
14511
14512     struct PackageInfo
14513       *info,
14514       *package_info;
14515
14516     SV
14517       *perl_exception,
14518       *reference;
14519
14520     PERL_UNUSED_VAR(ref);
14521     PERL_UNUSED_VAR(ix);
14522     exception=AcquireExceptionInfo();
14523     perl_exception=newSVpv("",0);
14524     number_images=0;
14525     package_info=(struct PackageInfo *) NULL;
14526     if (sv_isobject(ST(0)) == 0)
14527       {
14528         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14529           PackageName);
14530         goto PerlException;
14531       }
14532     reference=SvRV(ST(0));
14533     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14534     if (image == (Image *) NULL)
14535       {
14536         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14537           PackageName);
14538         goto PerlException;
14539       }
14540     package_info=ClonePackageInfo(info,exception);
14541     if (items == 2)
14542       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14543     else
14544       if (items > 2)
14545         for (i=2; i < items; i+=2)
14546           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14547             exception);
14548     (void) CopyMagickString(filename,package_info->image_info->filename,
14549       MagickPathExtent);
14550     scene=0;
14551     for (next=image; next; next=next->next)
14552     {
14553       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14554       next->scene=scene++;
14555     }
14556     *package_info->image_info->magick='\0';
14557     SetImageInfo(package_info->image_info,(unsigned int)
14558       GetImageListLength(image),exception);
14559     for (next=image; next; next=next->next)
14560     {
14561       (void) WriteImage(package_info->image_info,next,exception);
14562       number_images++;
14563       if (package_info->image_info->adjoin)
14564         break;
14565     }
14566
14567   PerlException:
14568     if (package_info != (struct PackageInfo *) NULL)
14569       DestroyPackageInfo(package_info);
14570     InheritPerlException(exception,perl_exception);
14571     exception=DestroyExceptionInfo(exception);
14572     sv_setiv(perl_exception,(IV) number_images);
14573     SvPOK_on(perl_exception);
14574     ST(0)=sv_2mortal(perl_exception);
14575     XSRETURN(1);
14576   }