]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
Fix compiler exception
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                                 Cristy                                      %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include <MagickCore/MagickCore.h>
57 #include "EXTERN.h"
58 #include "perl.h"
59 #include "XSUB.h"
60 #include <math.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "Mode", { {"geometry", StringReference},
535       {"width", IntegerReference},{"height", IntegerReference},
536       {"channel", MagickChannelOptions} } },
537     { "Statistic", { {"geometry", StringReference},
538       {"width", IntegerReference},{"height", IntegerReference},
539       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
540     { "Perceptible", { {"epsilon", RealReference},
541       {"channel", MagickChannelOptions} } },
542     { "Poly", { {"terms", ArrayReference},
543       {"channel", MagickChannelOptions} } },
544     { "Grayscale", { {"method", MagickNoiseOptions} } },
545     { "CannyEdge", { {"geometry", StringReference},
546       {"radius", RealReference}, {"sigma", RealReference},
547       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
548     { "HoughLine", { {"geometry", StringReference},
549       {"width", IntegerReference}, {"height", IntegerReference},
550       {"threshold", IntegerReference} } },
551     { "MeanShift", { {"geometry", StringReference},
552       {"width", IntegerReference}, {"height", IntegerReference},
553       {"distance", RealReference} } },
554     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
555       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
556     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
557     { "CopyPixels", { {"image", ImageReference}, {"geometry", StringReference},
558       {"width", IntegerReference}, {"height", IntegerReference},
559       {"x", IntegerReference}, {"y", IntegerReference},
560       {"gravity", MagickGravityOptions}, {"offset", StringReference}, 
561       {"dx", IntegerReference}, {"dy", IntegerReference} } },
562     { "Color", { {"color", StringReference} } },
563     { "WaveletDenoise", { {"threshold", StringReference},
564       {"channel", MagickChannelOptions} } },
565   };
566
567 static SplayTreeInfo
568   *magick_registry = (SplayTreeInfo *) NULL;
569 \f
570 /*
571   Forward declarations.
572 */
573 static Image
574   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
575
576 static ssize_t
577   strEQcase(const char *,const char *);
578 \f
579 /*
580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
581 %                                                                             %
582 %                                                                             %
583 %                                                                             %
584 %   C l o n e P a c k a g e I n f o                                           %
585 %                                                                             %
586 %                                                                             %
587 %                                                                             %
588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
589 %
590 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
591 %  a new one.
592 %
593 %  The format of the ClonePackageInfo routine is:
594 %
595 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
596 %        exception)
597 %
598 %  A description of each parameter follows:
599 %
600 %    o info: a structure of type info.
601 %
602 %    o exception: Return any errors or warnings in this structure.
603 %
604 */
605 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
606   ExceptionInfo *exception)
607 {
608   struct PackageInfo
609     *clone_info;
610
611   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
612   if (clone_info == (struct PackageInfo *) NULL)
613     {
614       ThrowPerlException(exception,ResourceLimitError,
615         "UnableToClonePackageInfo",PackageName);
616       return((struct PackageInfo *) NULL);
617     }
618   if (info == (struct PackageInfo *) NULL)
619     {
620       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
621       return(clone_info);
622     }
623   *clone_info=(*info);
624   clone_info->image_info=CloneImageInfo(info->image_info);
625   return(clone_info);
626 }
627 \f
628 /*
629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
630 %                                                                             %
631 %                                                                             %
632 %                                                                             %
633 %   c o n s t a n t                                                           %
634 %                                                                             %
635 %                                                                             %
636 %                                                                             %
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638 %
639 %  constant() returns a double value for the specified name.
640 %
641 %  The format of the constant routine is:
642 %
643 %      double constant(char *name,ssize_t sans)
644 %
645 %  A description of each parameter follows:
646 %
647 %    o value: Method constant returns a double value for the specified name.
648 %
649 %    o name: The name of the constant.
650 %
651 %    o sans: This integer value is not used.
652 %
653 */
654 static double constant(char *name,ssize_t sans)
655 {
656   (void) sans;
657   errno=0;
658   switch (*name)
659   {
660     case 'B':
661     {
662       if (strEQ(name,"BlobError"))
663         return(BlobError);
664       if (strEQ(name,"BlobWarning"))
665         return(BlobWarning);
666       break;
667     }
668     case 'C':
669     {
670       if (strEQ(name,"CacheError"))
671         return(CacheError);
672       if (strEQ(name,"CacheWarning"))
673         return(CacheWarning);
674       if (strEQ(name,"CoderError"))
675         return(CoderError);
676       if (strEQ(name,"CoderWarning"))
677         return(CoderWarning);
678       if (strEQ(name,"ConfigureError"))
679         return(ConfigureError);
680       if (strEQ(name,"ConfigureWarning"))
681         return(ConfigureWarning);
682       if (strEQ(name,"CorruptImageError"))
683         return(CorruptImageError);
684       if (strEQ(name,"CorruptImageWarning"))
685         return(CorruptImageWarning);
686       break;
687     }
688     case 'D':
689     {
690       if (strEQ(name,"DelegateError"))
691         return(DelegateError);
692       if (strEQ(name,"DelegateWarning"))
693         return(DelegateWarning);
694       if (strEQ(name,"DrawError"))
695         return(DrawError);
696       if (strEQ(name,"DrawWarning"))
697         return(DrawWarning);
698       break;
699     }
700     case 'E':
701     {
702       if (strEQ(name,"ErrorException"))
703         return(ErrorException);
704       if (strEQ(name,"ExceptionError"))
705         return(CoderError);
706       if (strEQ(name,"ExceptionWarning"))
707         return(CoderWarning);
708       break;
709     }
710     case 'F':
711     {
712       if (strEQ(name,"FatalErrorException"))
713         return(FatalErrorException);
714       if (strEQ(name,"FileOpenError"))
715         return(FileOpenError);
716       if (strEQ(name,"FileOpenWarning"))
717         return(FileOpenWarning);
718       break;
719     }
720     case 'I':
721     {
722       if (strEQ(name,"ImageError"))
723         return(ImageError);
724       if (strEQ(name,"ImageWarning"))
725         return(ImageWarning);
726       break;
727     }
728     case 'M':
729     {
730       if (strEQ(name,"MaxRGB"))
731         return(QuantumRange);
732       if (strEQ(name,"MissingDelegateError"))
733         return(MissingDelegateError);
734       if (strEQ(name,"MissingDelegateWarning"))
735         return(MissingDelegateWarning);
736       if (strEQ(name,"ModuleError"))
737         return(ModuleError);
738       if (strEQ(name,"ModuleWarning"))
739         return(ModuleWarning);
740       break;
741     }
742     case 'O':
743     {
744       if (strEQ(name,"Opaque"))
745         return(OpaqueAlpha);
746       if (strEQ(name,"OptionError"))
747         return(OptionError);
748       if (strEQ(name,"OptionWarning"))
749         return(OptionWarning);
750       break;
751     }
752     case 'Q':
753     {
754       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
755         return(MAGICKCORE_QUANTUM_DEPTH);
756       if (strEQ(name,"QuantumDepth"))
757         return(MAGICKCORE_QUANTUM_DEPTH);
758       if (strEQ(name,"QuantumRange"))
759         return(QuantumRange);
760       break;
761     }
762     case 'R':
763     {
764       if (strEQ(name,"ResourceLimitError"))
765         return(ResourceLimitError);
766       if (strEQ(name,"ResourceLimitWarning"))
767         return(ResourceLimitWarning);
768       if (strEQ(name,"RegistryError"))
769         return(RegistryError);
770       if (strEQ(name,"RegistryWarning"))
771         return(RegistryWarning);
772       break;
773     }
774     case 'S':
775     {
776       if (strEQ(name,"StreamError"))
777         return(StreamError);
778       if (strEQ(name,"StreamWarning"))
779         return(StreamWarning);
780       if (strEQ(name,"Success"))
781         return(0);
782       break;
783     }
784     case 'T':
785     {
786       if (strEQ(name,"Transparent"))
787         return(TransparentAlpha);
788       if (strEQ(name,"TypeError"))
789         return(TypeError);
790       if (strEQ(name,"TypeWarning"))
791         return(TypeWarning);
792       break;
793     }
794     case 'W':
795     {
796       if (strEQ(name,"WarningException"))
797         return(WarningException);
798       break;
799     }
800     case 'X':
801     {
802       if (strEQ(name,"XServerError"))
803         return(XServerError);
804       if (strEQ(name,"XServerWarning"))
805         return(XServerWarning);
806       break;
807     }
808   }
809   errno=EINVAL;
810   return(0);
811 }
812 \f
813 /*
814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
815 %                                                                             %
816 %                                                                             %
817 %                                                                             %
818 %   D e s t r o y P a c k a g e I n f o                                       %
819 %                                                                             %
820 %                                                                             %
821 %                                                                             %
822 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
823 %
824 %  Method DestroyPackageInfo frees a previously created info structure.
825 %
826 %  The format of the DestroyPackageInfo routine is:
827 %
828 %      DestroyPackageInfo(struct PackageInfo *info)
829 %
830 %  A description of each parameter follows:
831 %
832 %    o info: a structure of type info.
833 %
834 */
835 static void DestroyPackageInfo(struct PackageInfo *info)
836 {
837   info->image_info=DestroyImageInfo(info->image_info);
838   info=(struct PackageInfo *) RelinquishMagickMemory(info);
839 }
840 \f
841 /*
842 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
843 %                                                                             %
844 %                                                                             %
845 %                                                                             %
846 %   G e t L i s t                                                             %
847 %                                                                             %
848 %                                                                             %
849 %                                                                             %
850 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
851 %
852 %  Method GetList is recursively called by SetupList to traverse the
853 %  Image__Magick reference.  If building an reference_vector (see SetupList),
854 %  *current is the current position in *reference_vector and *last is the final
855 %  entry in *reference_vector.
856 %
857 %  The format of the GetList routine is:
858 %
859 %      GetList(info)
860 %
861 %  A description of each parameter follows:
862 %
863 %    o info: a structure of type info.
864 %
865 */
866 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
867   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
868 {
869   Image
870     *image;
871
872   if (reference == (SV *) NULL)
873     return(NULL);
874   switch (SvTYPE(reference))
875   {
876     case SVt_PVAV:
877     {
878       AV
879         *av;
880
881       Image
882         *head,
883         *previous;
884
885       register ssize_t
886         i;
887
888       ssize_t
889         n;
890
891       /*
892         Array of images.
893       */
894       previous=(Image *) NULL;
895       head=(Image *) NULL;
896       av=(AV *) reference;
897       n=av_len(av);
898       for (i=0; i <= n; i++)
899       {
900         SV
901           **rv;
902
903         rv=av_fetch(av,i,0);
904         if (rv && *rv && sv_isobject(*rv))
905           {
906             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
907               exception);
908             if (image == (Image *) NULL)
909               continue;
910             if (image == previous)
911               {
912                 image=CloneImage(image,0,0,MagickTrue,exception);
913                 if (image == (Image *) NULL)
914                   return(NULL);
915               }
916             image->previous=previous;
917             *(previous ? &previous->next : &head)=image;
918             for (previous=image; previous->next; previous=previous->next) ;
919           }
920       }
921       return(head);
922     }
923     case SVt_PVMG:
924     {
925       /*
926         Blessed scalar, one image.
927       */
928       image=INT2PTR(Image *,SvIV(reference));
929       if (image == (Image *) NULL)
930         return(NULL);
931       image->previous=(Image *) NULL;
932       image->next=(Image *) NULL;
933       if (reference_vector)
934         {
935           if (*current == *last)
936             {
937               *last+=256;
938               if (*reference_vector == (SV **) NULL)
939                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
940                   sizeof(*reference_vector));
941               else
942                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
943                   *last,sizeof(*reference_vector));
944             }
945           if (*reference_vector == (SV **) NULL)
946             {
947               ThrowPerlException(exception,ResourceLimitError,
948                 "MemoryAllocationFailed",PackageName);
949               return((Image *) NULL);
950             }
951           (*reference_vector)[*current]=reference;
952           (*reference_vector)[++(*current)]=NULL;
953         }
954       return(image);
955     }
956     default:
957       break;
958   }
959   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
960     (double) SvTYPE(reference));
961   return((Image *) NULL);
962 }
963 \f
964 /*
965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 %                                                                             %
967 %                                                                             %
968 %                                                                             %
969 %   G e t P a c k a g e I n f o                                               %
970 %                                                                             %
971 %                                                                             %
972 %                                                                             %
973 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974 %
975 %  Method GetPackageInfo looks up or creates an info structure for the given
976 %  Image__Magick reference.  If it does create a new one, the information in
977 %  package_info is used to initialize it.
978 %
979 %  The format of the GetPackageInfo routine is:
980 %
981 %      struct PackageInfo *GetPackageInfo(void *reference,
982 %        struct PackageInfo *package_info,ExceptionInfo *exception)
983 %
984 %  A description of each parameter follows:
985 %
986 %    o info: a structure of type info.
987 %
988 %    o exception: Return any errors or warnings in this structure.
989 %
990 */
991 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
992   struct PackageInfo *package_info,ExceptionInfo *exception)
993 {
994   char
995     message[MagickPathExtent];
996
997   struct PackageInfo
998     *clone_info;
999
1000   SV
1001     *sv;
1002
1003   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
1004     PackageName,XS_VERSION,reference);
1005   sv=perl_get_sv(message,(TRUE | 0x02));
1006   if (sv == (SV *) NULL)
1007     {
1008       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1009         message);
1010       return(package_info);
1011     }
1012   if (SvREFCNT(sv) == 0)
1013     (void) SvREFCNT_inc(sv);
1014   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1015     return(clone_info);
1016   clone_info=ClonePackageInfo(package_info,exception);
1017   sv_setiv(sv,PTR2IV(clone_info));
1018   return(clone_info);
1019 }
1020 \f
1021 /*
1022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1023 %                                                                             %
1024 %                                                                             %
1025 %                                                                             %
1026 %   S e t A t t r i b u t e                                                   %
1027 %                                                                             %
1028 %                                                                             %
1029 %                                                                             %
1030 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031 %
1032 %  SetAttribute() sets the attribute to the value in sval.  This can change
1033 %  either or both of image or info.
1034 %
1035 %  The format of the SetAttribute routine is:
1036 %
1037 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1038 %        SV *sval,ExceptionInfo *exception)
1039 %
1040 %  A description of each parameter follows:
1041 %
1042 %    o list: a list of strings.
1043 %
1044 %    o string: a character string.
1045 %
1046 */
1047
1048 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1049 {
1050   char
1051     *q;
1052
1053   double
1054     value;
1055
1056   value=InterpretSiPrefixValue(string,&q);
1057   if (*q == '%')
1058     value*=interval/100.0;
1059   return(value);
1060 }
1061
1062 static inline double StringToDouble(const char *string,char **sentinal)
1063 {
1064   return(InterpretLocaleValue(string,sentinal));
1065 }
1066
1067 static double StringToDoubleInterval(const char *string,const double interval)
1068 {
1069   char
1070     *q;
1071
1072   double
1073     value;
1074
1075   value=InterpretLocaleValue(string,&q);
1076   if (*q == '%')
1077     value*=interval/100.0;
1078   return(value);
1079 }
1080
1081 static inline ssize_t StringToLong(const char *value)
1082 {
1083   return(strtol(value,(char **) NULL,10));
1084 }
1085
1086 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1087   const char *attribute,SV *sval,ExceptionInfo *exception)
1088 {
1089   GeometryInfo
1090     geometry_info;
1091
1092   long
1093     x,
1094     y;
1095
1096   PixelInfo
1097     pixel;
1098
1099   MagickStatusType
1100     flags;
1101
1102   PixelInfo
1103     *color,
1104     target_color;
1105
1106   ssize_t
1107     sp;
1108
1109   switch (*attribute)
1110   {
1111     case 'A':
1112     case 'a':
1113     {
1114       if (LocaleCompare(attribute,"adjoin") == 0)
1115         {
1116           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1117             SvPV(sval,na)) : SvIV(sval);
1118           if (sp < 0)
1119             {
1120               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1121                 SvPV(sval,na));
1122               break;
1123             }
1124           if (info)
1125             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1126           break;
1127         }
1128       if (LocaleCompare(attribute,"alpha") == 0)
1129         {
1130           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1131             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1132           if (sp < 0)
1133             {
1134               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1135                 SvPV(sval,na));
1136               break;
1137             }
1138           for ( ; image; image=image->next)
1139             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1140               exception);
1141           break;
1142         }
1143       if (LocaleCompare(attribute,"antialias") == 0)
1144         {
1145           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1146             SvPV(sval,na)) : SvIV(sval);
1147           if (sp < 0)
1148             {
1149               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1150                 SvPV(sval,na));
1151               break;
1152             }
1153           if (info)
1154             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1155           break;
1156         }
1157       if (LocaleCompare(attribute,"area-limit") == 0)
1158         {
1159           MagickSizeType
1160             limit;
1161
1162           limit=MagickResourceInfinity;
1163           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1164             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1165               100.0);
1166           (void) SetMagickResourceLimit(AreaResource,limit);
1167           break;
1168         }
1169       if (LocaleCompare(attribute,"attenuate") == 0)
1170         {
1171           if (info)
1172             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1173           break;
1174         }
1175       if (LocaleCompare(attribute,"authenticate") == 0)
1176         {
1177           if (info)
1178             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1179           break;
1180         }
1181       if (info)
1182         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1183       for ( ; image; image=image->next)
1184         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1185       break;
1186     }
1187     case 'B':
1188     case 'b':
1189     {
1190       if (LocaleCompare(attribute,"background") == 0)
1191         {
1192           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1193             exception);
1194           if (info)
1195             info->image_info->background_color=target_color;
1196           for ( ; image; image=image->next)
1197             image->background_color=target_color;
1198           break;
1199         }
1200       if (LocaleCompare(attribute,"blue-primary") == 0)
1201         {
1202           for ( ; image; image=image->next)
1203           {
1204             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1205             image->chromaticity.blue_primary.x=geometry_info.rho;
1206             image->chromaticity.blue_primary.y=geometry_info.sigma;
1207             if ((flags & SigmaValue) == 0)
1208               image->chromaticity.blue_primary.y=
1209                 image->chromaticity.blue_primary.x;
1210           }
1211           break;
1212         }
1213       if (LocaleCompare(attribute,"bordercolor") == 0)
1214         {
1215           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1216             exception);
1217           if (info)
1218             info->image_info->border_color=target_color;
1219           for ( ; image; image=image->next)
1220             image->border_color=target_color;
1221           break;
1222         }
1223       if (info)
1224         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1225       for ( ; image; image=image->next)
1226         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1227       break;
1228     }
1229     case 'C':
1230     case 'c':
1231     {
1232       if (LocaleCompare(attribute,"cache-threshold") == 0)
1233         {
1234           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1235             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1236           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1237             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1238           break;
1239         }
1240       if (LocaleCompare(attribute,"clip-mask") == 0)
1241         {
1242           Image
1243             *clip_mask;
1244
1245           clip_mask=(Image *) NULL;
1246           if (SvPOK(sval))
1247             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1248           for ( ; image; image=image->next)
1249             SetImageMask(image,ReadPixelMask,clip_mask,exception);
1250           break;
1251         }
1252       if (LocaleNCompare(attribute,"colormap",8) == 0)
1253         {
1254           for ( ; image; image=image->next)
1255           {
1256             int
1257               items;
1258
1259             long
1260               i;
1261
1262             if (image->storage_class == DirectClass)
1263               continue;
1264             i=0;
1265             items=sscanf(attribute,"%*[^[][%ld",&i);
1266             (void) items;
1267             if (i > (ssize_t) image->colors)
1268               i%=image->colors;
1269             if ((strchr(SvPV(sval,na),',') == 0) ||
1270                 (strchr(SvPV(sval,na),')') != 0))
1271               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1272                 image->colormap+i,exception);
1273             else
1274               {
1275                 color=image->colormap+i;
1276                 pixel.red=color->red;
1277                 pixel.green=color->green;
1278                 pixel.blue=color->blue;
1279                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1280                 pixel.red=geometry_info.rho;
1281                 pixel.green=geometry_info.sigma;
1282                 pixel.blue=geometry_info.xi;
1283                 color->red=ClampToQuantum(pixel.red);
1284                 color->green=ClampToQuantum(pixel.green);
1285                 color->blue=ClampToQuantum(pixel.blue);
1286               }
1287           }
1288           break;
1289         }
1290       if (LocaleCompare(attribute,"colorspace") == 0)
1291         {
1292           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1293             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1294           if (sp < 0)
1295             {
1296               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1297                 SvPV(sval,na));
1298               break;
1299             }
1300           for ( ; image; image=image->next)
1301             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1302               exception);
1303           break;
1304         }
1305       if (LocaleCompare(attribute,"comment") == 0)
1306         {
1307           for ( ; image; image=image->next)
1308             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1309               info ? info->image_info : (ImageInfo *) NULL,image,
1310               SvPV(sval,na),exception),exception);
1311           break;
1312         }
1313       if (LocaleCompare(attribute,"compression") == 0)
1314         {
1315           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1316             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1317           if (sp < 0)
1318             {
1319               ThrowPerlException(exception,OptionError,
1320                 "UnrecognizedImageCompression",SvPV(sval,na));
1321               break;
1322             }
1323           if (info)
1324             info->image_info->compression=(CompressionType) sp;
1325           for ( ; image; image=image->next)
1326             image->compression=(CompressionType) sp;
1327           break;
1328         }
1329       if (info)
1330         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1331       for ( ; image; image=image->next)
1332         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1333       break;
1334     }
1335     case 'D':
1336     case 'd':
1337     {
1338       if (LocaleCompare(attribute,"debug") == 0)
1339         {
1340           SetLogEventMask(SvPV(sval,na));
1341           break;
1342         }
1343       if (LocaleCompare(attribute,"delay") == 0)
1344         {
1345           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1346           for ( ; image; image=image->next)
1347           {
1348             image->delay=(size_t) floor(geometry_info.rho+0.5);
1349             if ((flags & SigmaValue) != 0)
1350               image->ticks_per_second=(ssize_t)
1351                 floor(geometry_info.sigma+0.5);
1352           }
1353           break;
1354         }
1355       if (LocaleCompare(attribute,"disk-limit") == 0)
1356         {
1357           MagickSizeType
1358             limit;
1359
1360           limit=MagickResourceInfinity;
1361           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1362             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1363               100.0);
1364           (void) SetMagickResourceLimit(DiskResource,limit);
1365           break;
1366         }
1367       if (LocaleCompare(attribute,"density") == 0)
1368         {
1369           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1370             {
1371               ThrowPerlException(exception,OptionError,"MissingGeometry",
1372                 SvPV(sval,na));
1373               break;
1374             }
1375           if (info)
1376             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1377           for ( ; image; image=image->next)
1378           {
1379             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1380             image->resolution.x=geometry_info.rho;
1381             image->resolution.y=geometry_info.sigma;
1382             if ((flags & SigmaValue) == 0)
1383               image->resolution.y=image->resolution.x;
1384           }
1385           break;
1386         }
1387       if (LocaleCompare(attribute,"depth") == 0)
1388         {
1389           if (info)
1390             info->image_info->depth=SvIV(sval);
1391           for ( ; image; image=image->next)
1392             (void) SetImageDepth(image,SvIV(sval),exception);
1393           break;
1394         }
1395       if (LocaleCompare(attribute,"dispose") == 0)
1396         {
1397           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1398             SvPV(sval,na)) : SvIV(sval);
1399           if (sp < 0)
1400             {
1401               ThrowPerlException(exception,OptionError,
1402                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1403               break;
1404             }
1405           for ( ; image; image=image->next)
1406             image->dispose=(DisposeType) sp;
1407           break;
1408         }
1409       if (LocaleCompare(attribute,"dither") == 0)
1410         {
1411           if (info)
1412             {
1413               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1414                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1415               if (sp < 0)
1416                 {
1417                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1418                     SvPV(sval,na));
1419                   break;
1420                 }
1421               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1422             }
1423           break;
1424         }
1425       if (LocaleCompare(attribute,"display") == 0)
1426         {
1427           display:
1428           if (info)
1429             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1430           break;
1431         }
1432       if (info)
1433         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1434       for ( ; image; image=image->next)
1435         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1436       break;
1437     }
1438     case 'E':
1439     case 'e':
1440     {
1441       if (LocaleCompare(attribute,"endian") == 0)
1442         {
1443           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1444             SvPV(sval,na)) : SvIV(sval);
1445           if (sp < 0)
1446             {
1447               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1448                 SvPV(sval,na));
1449               break;
1450             }
1451           if (info)
1452             info->image_info->endian=(EndianType) sp;
1453           for ( ; image; image=image->next)
1454             image->endian=(EndianType) sp;
1455           break;
1456         }
1457       if (LocaleCompare(attribute,"extract") == 0)
1458         {
1459           /*
1460             Set image extract geometry.
1461           */
1462           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1463           break;
1464         }
1465       if (info)
1466         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1467       for ( ; image; image=image->next)
1468         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1469       break;
1470     }
1471     case 'F':
1472     case 'f':
1473     {
1474       if (LocaleCompare(attribute,"filename") == 0)
1475         {
1476           if (info)
1477             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1478               MagickPathExtent);
1479           for ( ; image; image=image->next)
1480             (void) CopyMagickString(image->filename,SvPV(sval,na),
1481               MagickPathExtent);
1482           break;
1483         }
1484       if (LocaleCompare(attribute,"file") == 0)
1485         {
1486           FILE
1487             *file;
1488
1489           PerlIO
1490             *io_info;
1491
1492           if (info == (struct PackageInfo *) NULL)
1493             break;
1494           io_info=IoIFP(sv_2io(sval));
1495           if (io_info == (PerlIO *) NULL)
1496             {
1497               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1498                 PackageName);
1499               break;
1500             }
1501           file=PerlIO_findFILE(io_info);
1502           if (file == (FILE *) NULL)
1503             {
1504               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1505                 PackageName);
1506               break;
1507             }
1508           SetImageInfoFile(info->image_info,file);
1509           break;
1510         }
1511       if (LocaleCompare(attribute,"fill") == 0)
1512         {
1513           if (info)
1514             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1515           break;
1516         }
1517       if (LocaleCompare(attribute,"font") == 0)
1518         {
1519           if (info)
1520             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1521           break;
1522         }
1523       if (LocaleCompare(attribute,"foreground") == 0)
1524         break;
1525       if (LocaleCompare(attribute,"fuzz") == 0)
1526         {
1527           if (info)
1528             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1529               QuantumRange+1.0);
1530           for ( ; image; image=image->next)
1531             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1532               QuantumRange+1.0);
1533           break;
1534         }
1535       if (info)
1536         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1537       for ( ; image; image=image->next)
1538         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1539       break;
1540     }
1541     case 'G':
1542     case 'g':
1543     {
1544       if (LocaleCompare(attribute,"gamma") == 0)
1545         {
1546           for ( ; image; image=image->next)
1547             image->gamma=SvNV(sval);
1548           break;
1549         }
1550       if (LocaleCompare(attribute,"gravity") == 0)
1551         {
1552           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1553             SvPV(sval,na)) : SvIV(sval);
1554           if (sp < 0)
1555             {
1556               ThrowPerlException(exception,OptionError,
1557                 "UnrecognizedGravityType",SvPV(sval,na));
1558               break;
1559             }
1560           if (info)
1561             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1562           for ( ; image; image=image->next)
1563             image->gravity=(GravityType) sp;
1564           break;
1565         }
1566       if (LocaleCompare(attribute,"green-primary") == 0)
1567         {
1568           for ( ; image; image=image->next)
1569           {
1570             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1571             image->chromaticity.green_primary.x=geometry_info.rho;
1572             image->chromaticity.green_primary.y=geometry_info.sigma;
1573             if ((flags & SigmaValue) == 0)
1574               image->chromaticity.green_primary.y=
1575                 image->chromaticity.green_primary.x;
1576           }
1577           break;
1578         }
1579       if (info)
1580         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1581       for ( ; image; image=image->next)
1582         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1583       break;
1584     }
1585     case 'I':
1586     case 'i':
1587     {
1588       if (LocaleNCompare(attribute,"index",5) == 0)
1589         {
1590           int
1591             items;
1592
1593           long
1594             index;
1595
1596           register Quantum
1597             *q;
1598
1599           CacheView
1600             *image_view;
1601
1602           for ( ; image; image=image->next)
1603           {
1604             if (image->storage_class != PseudoClass)
1605               continue;
1606             x=0;
1607             y=0;
1608             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1609             (void) items;
1610             image_view=AcquireAuthenticCacheView(image,exception);
1611             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1612             if (q != (Quantum *) NULL)
1613               {
1614                 items=sscanf(SvPV(sval,na),"%ld",&index);
1615                 if ((index >= 0) && (index < (ssize_t) image->colors))
1616                   SetPixelIndex(image,index,q);
1617                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1618               }
1619             image_view=DestroyCacheView(image_view);
1620           }
1621           break;
1622         }
1623       if (LocaleCompare(attribute,"iterations") == 0)
1624         {
1625   iterations:
1626           for ( ; image; image=image->next)
1627             image->iterations=SvIV(sval);
1628           break;
1629         }
1630       if (LocaleCompare(attribute,"interlace") == 0)
1631         {
1632           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1633             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1634           if (sp < 0)
1635             {
1636               ThrowPerlException(exception,OptionError,
1637                 "UnrecognizedInterlaceType",SvPV(sval,na));
1638               break;
1639             }
1640           if (info)
1641             info->image_info->interlace=(InterlaceType) sp;
1642           for ( ; image; image=image->next)
1643             image->interlace=(InterlaceType) sp;
1644           break;
1645         }
1646       if (info)
1647         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1648       for ( ; image; image=image->next)
1649         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1650       break;
1651     }
1652     case 'L':
1653     case 'l':
1654     {
1655       if (LocaleCompare(attribute,"label") == 0)
1656         {
1657           for ( ; image; image=image->next)
1658             (void) SetImageProperty(image,"label",InterpretImageProperties(
1659               info ? info->image_info : (ImageInfo *) NULL,image,
1660               SvPV(sval,na),exception),exception);
1661           break;
1662         }
1663       if (LocaleCompare(attribute,"loop") == 0)
1664         goto iterations;
1665       if (info)
1666         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1667       for ( ; image; image=image->next)
1668         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1669       break;
1670     }
1671     case 'M':
1672     case 'm':
1673     {
1674       if (LocaleCompare(attribute,"magick") == 0)
1675         {
1676           if (info)
1677             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1678               "%s:",SvPV(sval,na));
1679           for ( ; image; image=image->next)
1680             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1681           break;
1682         }
1683       if (LocaleCompare(attribute,"map-limit") == 0)
1684         {
1685           MagickSizeType
1686             limit;
1687
1688           limit=MagickResourceInfinity;
1689           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1690             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1691               100.0);
1692           (void) SetMagickResourceLimit(MapResource,limit);
1693           break;
1694         }
1695       if (LocaleCompare(attribute,"mask") == 0)
1696         {
1697           Image
1698             *mask;
1699
1700           mask=(Image *) NULL;
1701           if (SvPOK(sval))
1702             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1703           for ( ; image; image=image->next)
1704             SetImageMask(image,ReadPixelMask,mask,exception);
1705           break;
1706         }
1707       if (LocaleCompare(attribute,"mattecolor") == 0)
1708         {
1709           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1710             exception);
1711           if (info)
1712             info->image_info->alpha_color=target_color;
1713           for ( ; image; image=image->next)
1714             image->alpha_color=target_color;
1715           break;
1716         }
1717       if (LocaleCompare(attribute,"matte") == 0)
1718         {
1719           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1720             SvPV(sval,na)) : SvIV(sval);
1721           if (sp < 0)
1722             {
1723               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1724                 SvPV(sval,na));
1725               break;
1726             }
1727           for ( ; image; image=image->next)
1728             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1729           break;
1730         }
1731       if (LocaleCompare(attribute,"memory-limit") == 0)
1732         {
1733           MagickSizeType
1734             limit;
1735
1736           limit=MagickResourceInfinity;
1737           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1738             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1739               100.0);
1740           (void) SetMagickResourceLimit(MemoryResource,limit);
1741           break;
1742         }
1743       if (LocaleCompare(attribute,"monochrome") == 0)
1744         {
1745           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1746             SvPV(sval,na)) : SvIV(sval);
1747           if (sp < 0)
1748             {
1749               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1750                 SvPV(sval,na));
1751               break;
1752             }
1753           if (info)
1754             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1755           for ( ; image; image=image->next)
1756             (void) SetImageType(image,BilevelType,exception);
1757           break;
1758         }
1759       if (info)
1760         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1761       for ( ; image; image=image->next)
1762         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1763       break;
1764     }
1765     case 'O':
1766     case 'o':
1767     {
1768       if (LocaleCompare(attribute,"option") == 0)
1769         {
1770           if (info)
1771             DefineImageOption(info->image_info,SvPV(sval,na));
1772           break;
1773         }
1774       if (LocaleCompare(attribute,"orientation") == 0)
1775         {
1776           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1777             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1778           if (sp < 0)
1779             {
1780               ThrowPerlException(exception,OptionError,
1781                 "UnrecognizedOrientationType",SvPV(sval,na));
1782               break;
1783             }
1784           if (info)
1785             info->image_info->orientation=(OrientationType) sp;
1786           for ( ; image; image=image->next)
1787             image->orientation=(OrientationType) sp;
1788           break;
1789         }
1790       if (info)
1791         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1792       for ( ; image; image=image->next)
1793         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1794       break;
1795     }
1796     case 'P':
1797     case 'p':
1798     {
1799       if (LocaleCompare(attribute,"page") == 0)
1800         {
1801           char
1802             *geometry;
1803
1804           geometry=GetPageGeometry(SvPV(sval,na));
1805           if (info)
1806             (void) CloneString(&info->image_info->page,geometry);
1807           for ( ; image; image=image->next)
1808             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1809           geometry=(char *) RelinquishMagickMemory(geometry);
1810           break;
1811         }
1812       if (LocaleNCompare(attribute,"pixel",5) == 0)
1813         {
1814           int
1815             items;
1816
1817           PixelInfo
1818             pixel;
1819
1820           register Quantum
1821             *q;
1822
1823           CacheView
1824             *image_view;
1825
1826           for ( ; image; image=image->next)
1827           {
1828             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1829               break;
1830             x=0;
1831             y=0;
1832             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1833             (void) items;
1834             image_view=AcquireVirtualCacheView(image,exception);
1835             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1836             if (q != (Quantum *) NULL)
1837               {
1838                 if ((strchr(SvPV(sval,na),',') == 0) ||
1839                     (strchr(SvPV(sval,na),')') != 0))
1840                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1841                     &pixel,exception);
1842                 else
1843                   {
1844                     GetPixelInfo(image,&pixel);
1845                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1846                     pixel.red=geometry_info.rho;
1847                     if ((flags & SigmaValue) != 0)
1848                       pixel.green=geometry_info.sigma;
1849                     if ((flags & XiValue) != 0)
1850                       pixel.blue=geometry_info.xi;
1851                     if ((flags & PsiValue) != 0)
1852                       pixel.alpha=geometry_info.psi;
1853                     if ((flags & ChiValue) != 0)
1854                       pixel.black=geometry_info.chi;
1855                   }
1856                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1857                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1858                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1859                 if (image->colorspace == CMYKColorspace)
1860                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1861                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1862                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1863               }
1864             image_view=DestroyCacheView(image_view);
1865           }
1866           break;
1867         }
1868       if (LocaleCompare(attribute,"pointsize") == 0)
1869         {
1870           if (info)
1871             {
1872               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1873               info->image_info->pointsize=geometry_info.rho;
1874             }
1875           break;
1876         }
1877       if (LocaleCompare(attribute,"preview") == 0)
1878         {
1879           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1880             SvPV(sval,na)) : SvIV(sval);
1881           if (sp < 0)
1882             {
1883               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1884                 SvPV(sval,na));
1885               break;
1886             }
1887           if (info)
1888             info->image_info->preview_type=(PreviewType) sp;
1889           break;
1890         }
1891       if (info)
1892         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1893       for ( ; image; image=image->next)
1894         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1895       break;
1896     }
1897     case 'Q':
1898     case 'q':
1899     {
1900       if (LocaleCompare(attribute,"quality") == 0)
1901         {
1902           if (info)
1903             info->image_info->quality=SvIV(sval);
1904           for ( ; image; image=image->next)
1905             image->quality=SvIV(sval);
1906           break;
1907         }
1908       if (info)
1909         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1910       for ( ; image; image=image->next)
1911         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1912       break;
1913     }
1914     case 'R':
1915     case 'r':
1916     {
1917       if (LocaleCompare(attribute,"read-mask") == 0)
1918         {
1919           Image
1920             *mask;
1921
1922           mask=(Image *) NULL;
1923           if (SvPOK(sval))
1924             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1925           for ( ; image; image=image->next)
1926             SetImageMask(image,ReadPixelMask,mask,exception);
1927           break;
1928         }
1929       if (LocaleCompare(attribute,"red-primary") == 0)
1930         {
1931           for ( ; image; image=image->next)
1932           {
1933             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1934             image->chromaticity.red_primary.x=geometry_info.rho;
1935             image->chromaticity.red_primary.y=geometry_info.sigma;
1936             if ((flags & SigmaValue) == 0)
1937               image->chromaticity.red_primary.y=
1938                 image->chromaticity.red_primary.x;
1939           }
1940           break;
1941         }
1942       if (LocaleCompare(attribute,"render") == 0)
1943         {
1944           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1945             SvPV(sval,na)) : SvIV(sval);
1946           if (sp < 0)
1947             {
1948               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1949                 SvPV(sval,na));
1950               break;
1951             }
1952          for ( ; image; image=image->next)
1953            image->rendering_intent=(RenderingIntent) sp;
1954          break;
1955        }
1956       if (LocaleCompare(attribute,"repage") == 0)
1957         {
1958           RectangleInfo
1959             geometry;
1960
1961           for ( ; image; image=image->next)
1962           {
1963             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1964             if ((flags & WidthValue) != 0)
1965               {
1966                 if ((flags & HeightValue) == 0)
1967                   geometry.height=geometry.width;
1968                 image->page.width=geometry.width;
1969                 image->page.height=geometry.height;
1970               }
1971             if ((flags & AspectValue) != 0)
1972               {
1973                 if ((flags & XValue) != 0)
1974                   image->page.x+=geometry.x;
1975                 if ((flags & YValue) != 0)
1976                   image->page.y+=geometry.y;
1977               }
1978             else
1979               {
1980                 if ((flags & XValue) != 0)
1981                   {
1982                     image->page.x=geometry.x;
1983                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1984                       image->page.width=image->columns+geometry.x;
1985                   }
1986                 if ((flags & YValue) != 0)
1987                   {
1988                     image->page.y=geometry.y;
1989                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1990                       image->page.height=image->rows+geometry.y;
1991                   }
1992               }
1993           }
1994           break;
1995         }
1996       if (info)
1997         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1998       for ( ; image; image=image->next)
1999         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2000       break;
2001     }
2002     case 'S':
2003     case 's':
2004     {
2005       if (LocaleCompare(attribute,"sampling-factor") == 0)
2006         {
2007           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2008             {
2009               ThrowPerlException(exception,OptionError,"MissingGeometry",
2010                 SvPV(sval,na));
2011               break;
2012             }
2013           if (info)
2014             (void) CloneString(&info->image_info->sampling_factor,
2015               SvPV(sval,na));
2016           break;
2017         }
2018       if (LocaleCompare(attribute,"scene") == 0)
2019         {
2020           for ( ; image; image=image->next)
2021             image->scene=SvIV(sval);
2022           break;
2023         }
2024       if (LocaleCompare(attribute,"server") == 0)
2025         goto display;
2026       if (LocaleCompare(attribute,"size") == 0)
2027         {
2028           if (info)
2029             {
2030               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2031                 {
2032                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2033                     SvPV(sval,na));
2034                   break;
2035                 }
2036               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2037             }
2038           break;
2039         }
2040       if (LocaleCompare(attribute,"stroke") == 0)
2041         {
2042           if (info)
2043             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2044           break;
2045         }
2046       if (info)
2047         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2048       for ( ; image; image=image->next)
2049         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2050       break;
2051     }
2052     case 'T':
2053     case 't':
2054     {
2055       if (LocaleCompare(attribute,"texture") == 0)
2056         {
2057           if (info)
2058             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2059           break;
2060         }
2061       if (LocaleCompare(attribute,"thread-limit") == 0)
2062         {
2063           MagickSizeType
2064             limit;
2065
2066           limit=MagickResourceInfinity;
2067           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2068             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2069               100.0);
2070           (void) SetMagickResourceLimit(ThreadResource,limit);
2071           break;
2072         }
2073       if (LocaleCompare(attribute,"tile-offset") == 0)
2074         {
2075           char
2076             *geometry;
2077
2078           geometry=GetPageGeometry(SvPV(sval,na));
2079           if (info)
2080             (void) CloneString(&info->image_info->page,geometry);
2081           for ( ; image; image=image->next)
2082             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2083               exception);
2084           geometry=(char *) RelinquishMagickMemory(geometry);
2085           break;
2086         }
2087       if (LocaleCompare(attribute,"time-limit") == 0)
2088         {
2089           MagickSizeType
2090             limit;
2091
2092           limit=MagickResourceInfinity;
2093           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2094             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2095               100.0);
2096           (void) SetMagickResourceLimit(TimeResource,limit);
2097           break;
2098         }
2099       if (LocaleCompare(attribute,"transparent-color") == 0)
2100         {
2101           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2102             exception);
2103           if (info)
2104             info->image_info->transparent_color=target_color;
2105           for ( ; image; image=image->next)
2106             image->transparent_color=target_color;
2107           break;
2108         }
2109       if (LocaleCompare(attribute,"type") == 0)
2110         {
2111           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2112             SvPV(sval,na)) : SvIV(sval);
2113           if (sp < 0)
2114             {
2115               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2116                 SvPV(sval,na));
2117               break;
2118             }
2119           if (info)
2120             info->image_info->type=(ImageType) sp;
2121           for ( ; image; image=image->next)
2122             SetImageType(image,(ImageType) sp,exception);
2123           break;
2124         }
2125       if (info)
2126         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2127       for ( ; image; image=image->next)
2128         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2129       break;
2130     }
2131     case 'U':
2132     case 'u':
2133     {
2134       if (LocaleCompare(attribute,"units") == 0)
2135         {
2136           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2137             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2138           if (sp < 0)
2139             {
2140               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2141                 SvPV(sval,na));
2142               break;
2143             }
2144           if (info)
2145             info->image_info->units=(ResolutionType) sp;
2146           for ( ; image; image=image->next)
2147           {
2148             ResolutionType
2149               units;
2150
2151             units=(ResolutionType) sp;
2152             if (image->units != units)
2153               switch (image->units)
2154               {
2155                 case UndefinedResolution:
2156                 case PixelsPerInchResolution:
2157                 {
2158                   if (units == PixelsPerCentimeterResolution)
2159                     {
2160                       image->resolution.x*=2.54;
2161                       image->resolution.y*=2.54;
2162                     }
2163                   break;
2164                 }
2165                 case PixelsPerCentimeterResolution:
2166                 {
2167                   if (units == PixelsPerInchResolution)
2168                     {
2169                       image->resolution.x/=2.54;
2170                       image->resolution.y/=2.54;
2171                     }
2172                   break;
2173                 }
2174               }
2175             image->units=units;
2176           }
2177           break;
2178         }
2179       if (info)
2180         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2181       for ( ; image; image=image->next)
2182         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2183       break;
2184     }
2185     case 'V':
2186     case 'v':
2187     {
2188       if (LocaleCompare(attribute,"verbose") == 0)
2189         {
2190           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2191             SvPV(sval,na)) : SvIV(sval);
2192           if (sp < 0)
2193             {
2194               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2195                 SvPV(sval,na));
2196               break;
2197             }
2198           if (info)
2199             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2200           break;
2201         }
2202       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2203         {
2204           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2205             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2206           if (sp < 0)
2207             {
2208               ThrowPerlException(exception,OptionError,
2209                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2210               break;
2211             }
2212           for ( ; image; image=image->next)
2213             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2214           break;
2215         }
2216       if (info)
2217         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2218       for ( ; image; image=image->next)
2219         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2220       break;
2221     }
2222     case 'W':
2223     case 'w':
2224     {
2225       if (LocaleCompare(attribute,"white-point") == 0)
2226         {
2227           for ( ; image; image=image->next)
2228           {
2229             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2230             image->chromaticity.white_point.x=geometry_info.rho;
2231             image->chromaticity.white_point.y=geometry_info.sigma;
2232             if ((flags & SigmaValue) == 0)
2233               image->chromaticity.white_point.y=
2234                 image->chromaticity.white_point.x;
2235           }
2236           break;
2237         }
2238       if (LocaleCompare(attribute,"write-mask") == 0)
2239         {
2240           Image
2241             *mask;
2242
2243           mask=(Image *) NULL;
2244           if (SvPOK(sval))
2245             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
2246           for ( ; image; image=image->next)
2247             SetImageMask(image,WritePixelMask,mask,exception);
2248           break;
2249         }
2250       if (info)
2251         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2252       for ( ; image; image=image->next)
2253         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2254       break;
2255     }
2256     default:
2257     {
2258       if (info)
2259         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2260       for ( ; image; image=image->next)
2261         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2262       break;
2263     }
2264   }
2265 }
2266 \f
2267 /*
2268 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2269 %                                                                             %
2270 %                                                                             %
2271 %                                                                             %
2272 %   S e t u p L i s t                                                         %
2273 %                                                                             %
2274 %                                                                             %
2275 %                                                                             %
2276 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2277 %
2278 %  Method SetupList returns the list of all the images linked by their
2279 %  image->next and image->previous link lists for use with ImageMagick.  If
2280 %  info is non-NULL, an info structure is returned in *info.  If
2281 %  reference_vector is non-NULL,an array of SV* are returned in
2282 %  *reference_vector.  Reference_vector is used when the images are going to be
2283 %  replaced with new Image*'s.
2284 %
2285 %  The format of the SetupList routine is:
2286 %
2287 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2288 %        SV ***reference_vector,ExceptionInfo *exception)
2289 %
2290 %  A description of each parameter follows:
2291 %
2292 %    o list: a list of strings.
2293 %
2294 %    o string: a character string.
2295 %
2296 %    o exception: Return any errors or warnings in this structure.
2297 %
2298 */
2299 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2300   SV ***reference_vector,ExceptionInfo *exception)
2301 {
2302   Image
2303     *image;
2304
2305   ssize_t
2306     current,
2307     last;
2308
2309   if (reference_vector)
2310     *reference_vector=NULL;
2311   if (info)
2312     *info=NULL;
2313   current=0;
2314   last=0;
2315   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2316   if (info && (SvTYPE(reference) == SVt_PVAV))
2317     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2318       exception);
2319   return(image);
2320 }
2321 \f
2322 /*
2323 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2324 %                                                                             %
2325 %                                                                             %
2326 %                                                                             %
2327 %   s t r E Q c a s e                                                         %
2328 %                                                                             %
2329 %                                                                             %
2330 %                                                                             %
2331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2332 %
2333 %  strEQcase() compares two strings and returns 0 if they are the
2334 %  same or if the second string runs out first.  The comparison is case
2335 %  insensitive.
2336 %
2337 %  The format of the strEQcase routine is:
2338 %
2339 %      ssize_t strEQcase(const char *p,const char *q)
2340 %
2341 %  A description of each parameter follows:
2342 %
2343 %    o p: a character string.
2344 %
2345 %    o q: a character string.
2346 %
2347 %
2348 */
2349 static ssize_t strEQcase(const char *p,const char *q)
2350 {
2351   char
2352     c;
2353
2354   register ssize_t
2355     i;
2356
2357   for (i=0 ; (c=(*q)) != 0; i++)
2358   {
2359     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2360         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2361       return(0);
2362     p++;
2363     q++;
2364   }
2365   return(((*q == 0) && (*p == 0)) ? i : 0);
2366 }
2367 \f
2368 /*
2369 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2370 %                                                                             %
2371 %                                                                             %
2372 %                                                                             %
2373 %   I m a g e : : M a g i c k                                                 %
2374 %                                                                             %
2375 %                                                                             %
2376 %                                                                             %
2377 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2378 %
2379 %
2380 */
2381 MODULE = Image::Magick PACKAGE = Image::Magick
2382
2383 PROTOTYPES: ENABLE
2384
2385 BOOT:
2386   MagickCoreGenesis("PerlMagick",MagickFalse);
2387   SetWarningHandler(NULL);
2388   SetErrorHandler(NULL);
2389   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2390     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2391
2392 void
2393 UNLOAD()
2394   PPCODE:
2395   {
2396     if (magick_registry != (SplayTreeInfo *) NULL)
2397       magick_registry=DestroySplayTree(magick_registry);
2398     MagickCoreTerminus();
2399   }
2400
2401 double
2402 constant(name,argument)
2403   char *name
2404   ssize_t argument
2405 \f
2406 #
2407 ###############################################################################
2408 #                                                                             #
2409 #                                                                             #
2410 #                                                                             #
2411 #   A n i m a t e                                                             #
2412 #                                                                             #
2413 #                                                                             #
2414 #                                                                             #
2415 ###############################################################################
2416 #
2417 #
2418 void
2419 Animate(ref,...)
2420   Image::Magick ref=NO_INIT
2421   ALIAS:
2422     AnimateImage  = 1
2423     animate       = 2
2424     animateimage  = 3
2425   PPCODE:
2426   {
2427     ExceptionInfo
2428       *exception;
2429
2430     Image
2431       *image;
2432
2433     register ssize_t
2434       i;
2435
2436     struct PackageInfo
2437       *info,
2438       *package_info;
2439
2440     SV
2441       *perl_exception,
2442       *reference;
2443
2444     PERL_UNUSED_VAR(ref);
2445     PERL_UNUSED_VAR(ix);
2446     exception=AcquireExceptionInfo();
2447     perl_exception=newSVpv("",0);
2448     package_info=(struct PackageInfo *) NULL;
2449     if (sv_isobject(ST(0)) == 0)
2450       {
2451         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2452           PackageName);
2453         goto PerlException;
2454       }
2455     reference=SvRV(ST(0));
2456     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2457     if (image == (Image *) NULL)
2458       {
2459         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2460           PackageName);
2461         goto PerlException;
2462       }
2463     package_info=ClonePackageInfo(info,exception);
2464     if (items == 2)
2465       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2466     else
2467       if (items > 2)
2468         for (i=2; i < items; i+=2)
2469           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2470             exception);
2471     (void) AnimateImages(package_info->image_info,image,exception);
2472     (void) CatchImageException(image);
2473
2474   PerlException:
2475     if (package_info != (struct PackageInfo *) NULL)
2476       DestroyPackageInfo(package_info);
2477     InheritPerlException(exception,perl_exception);
2478     exception=DestroyExceptionInfo(exception);
2479     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2480     SvPOK_on(perl_exception);
2481     ST(0)=sv_2mortal(perl_exception);
2482     XSRETURN(1);
2483   }
2484 \f
2485 #
2486 ###############################################################################
2487 #                                                                             #
2488 #                                                                             #
2489 #                                                                             #
2490 #   A p p e n d                                                               #
2491 #                                                                             #
2492 #                                                                             #
2493 #                                                                             #
2494 ###############################################################################
2495 #
2496 #
2497 void
2498 Append(ref,...)
2499   Image::Magick ref=NO_INIT
2500   ALIAS:
2501     AppendImage  = 1
2502     append       = 2
2503     appendimage  = 3
2504   PPCODE:
2505   {
2506     AV
2507       *av;
2508
2509     char
2510       *attribute;
2511
2512     ExceptionInfo
2513       *exception;
2514
2515     HV
2516       *hv;
2517
2518     Image
2519       *image;
2520
2521     register ssize_t
2522       i;
2523
2524     ssize_t
2525       stack;
2526
2527     struct PackageInfo
2528       *info;
2529
2530     SV
2531       *av_reference,
2532       *perl_exception,
2533       *reference,
2534       *rv,
2535       *sv;
2536
2537     PERL_UNUSED_VAR(ref);
2538     PERL_UNUSED_VAR(ix);
2539     exception=AcquireExceptionInfo();
2540     perl_exception=newSVpv("",0);
2541     sv=NULL;
2542     attribute=NULL;
2543     av=NULL;
2544     if (sv_isobject(ST(0)) == 0)
2545       {
2546         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2547           PackageName);
2548         goto PerlException;
2549       }
2550     reference=SvRV(ST(0));
2551     hv=SvSTASH(reference);
2552     av=newAV();
2553     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2554     SvREFCNT_dec(av);
2555     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2556     if (image == (Image *) NULL)
2557       {
2558         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2559           PackageName);
2560         goto PerlException;
2561       }
2562     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2563     /*
2564       Get options.
2565     */
2566     stack=MagickTrue;
2567     for (i=2; i < items; i+=2)
2568     {
2569       attribute=(char *) SvPV(ST(i-1),na);
2570       switch (*attribute)
2571       {
2572         case 'S':
2573         case 's':
2574         {
2575           if (LocaleCompare(attribute,"stack") == 0)
2576             {
2577               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2578                 SvPV(ST(i),na));
2579               if (stack < 0)
2580                 {
2581                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2582                     SvPV(ST(i),na));
2583                   return;
2584                 }
2585               break;
2586             }
2587           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2588             attribute);
2589           break;
2590         }
2591         default:
2592         {
2593           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2594             attribute);
2595           break;
2596         }
2597       }
2598     }
2599     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2600     if (image == (Image *) NULL)
2601       goto PerlException;
2602     for ( ; image; image=image->next)
2603     {
2604       AddImageToRegistry(sv,image);
2605       rv=newRV(sv);
2606       av_push(av,sv_bless(rv,hv));
2607       SvREFCNT_dec(sv);
2608     }
2609     exception=DestroyExceptionInfo(exception);
2610     ST(0)=av_reference;
2611     SvREFCNT_dec(perl_exception);
2612     XSRETURN(1);
2613
2614   PerlException:
2615     InheritPerlException(exception,perl_exception);
2616     exception=DestroyExceptionInfo(exception);
2617     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2618     SvPOK_on(perl_exception);
2619     ST(0)=sv_2mortal(perl_exception);
2620     XSRETURN(1);
2621   }
2622 \f
2623 #
2624 ###############################################################################
2625 #                                                                             #
2626 #                                                                             #
2627 #                                                                             #
2628 #   A v e r a g e                                                             #
2629 #                                                                             #
2630 #                                                                             #
2631 #                                                                             #
2632 ###############################################################################
2633 #
2634 #
2635 void
2636 Average(ref)
2637   Image::Magick ref=NO_INIT
2638   ALIAS:
2639     AverageImage   = 1
2640     average        = 2
2641     averageimage   = 3
2642   PPCODE:
2643   {
2644     AV
2645       *av;
2646
2647     char
2648       *p;
2649
2650     ExceptionInfo
2651       *exception;
2652
2653     HV
2654       *hv;
2655
2656     Image
2657       *image;
2658
2659     struct PackageInfo
2660       *info;
2661
2662     SV
2663       *perl_exception,
2664       *reference,
2665       *rv,
2666       *sv;
2667
2668     PERL_UNUSED_VAR(ref);
2669     PERL_UNUSED_VAR(ix);
2670     exception=AcquireExceptionInfo();
2671     perl_exception=newSVpv("",0);
2672     sv=NULL;
2673     if (sv_isobject(ST(0)) == 0)
2674       {
2675         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2676           PackageName);
2677         goto PerlException;
2678       }
2679     reference=SvRV(ST(0));
2680     hv=SvSTASH(reference);
2681     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2682     if (image == (Image *) NULL)
2683       {
2684         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2685           PackageName);
2686         goto PerlException;
2687       }
2688     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2689     if (image == (Image *) NULL)
2690       goto PerlException;
2691     /*
2692       Create blessed Perl array for the returned image.
2693     */
2694     av=newAV();
2695     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2696     SvREFCNT_dec(av);
2697     AddImageToRegistry(sv,image);
2698     rv=newRV(sv);
2699     av_push(av,sv_bless(rv,hv));
2700     SvREFCNT_dec(sv);
2701     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2702     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2703       "average-%.*s",(int) (MagickPathExtent-9),
2704       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2705     (void) CopyMagickString(image->filename,info->image_info->filename,
2706       MagickPathExtent);
2707     SetImageInfo(info->image_info,0,exception);
2708     exception=DestroyExceptionInfo(exception);
2709     SvREFCNT_dec(perl_exception);
2710     XSRETURN(1);
2711
2712   PerlException:
2713     InheritPerlException(exception,perl_exception);
2714     exception=DestroyExceptionInfo(exception);
2715     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2716     SvPOK_on(perl_exception);
2717     ST(0)=sv_2mortal(perl_exception);
2718     XSRETURN(1);
2719   }
2720 \f
2721 #
2722 ###############################################################################
2723 #                                                                             #
2724 #                                                                             #
2725 #                                                                             #
2726 #   B l o b T o I m a g e                                                     #
2727 #                                                                             #
2728 #                                                                             #
2729 #                                                                             #
2730 ###############################################################################
2731 #
2732 #
2733 void
2734 BlobToImage(ref,...)
2735   Image::Magick ref=NO_INIT
2736   ALIAS:
2737     BlobToImage  = 1
2738     blobtoimage  = 2
2739     blobto       = 3
2740   PPCODE:
2741   {
2742     AV
2743       *av;
2744
2745     char
2746       **keep,
2747       **list;
2748
2749     ExceptionInfo
2750       *exception;
2751
2752     HV
2753       *hv;
2754
2755     Image
2756       *image;
2757
2758     register char
2759       **p;
2760
2761     register ssize_t
2762       i;
2763
2764     ssize_t
2765       ac,
2766       n,
2767       number_images;
2768
2769     STRLEN
2770       *length;
2771
2772     struct PackageInfo
2773       *info;
2774
2775     SV
2776       *perl_exception,
2777       *reference,
2778       *rv,
2779       *sv;
2780
2781     PERL_UNUSED_VAR(ref);
2782     PERL_UNUSED_VAR(ix);
2783     exception=AcquireExceptionInfo();
2784     perl_exception=newSVpv("",0);
2785     sv=NULL;
2786     number_images=0;
2787     ac=(items < 2) ? 1 : items-1;
2788     length=(STRLEN *) NULL;
2789     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2790     if (list == (char **) NULL)
2791       {
2792         ThrowPerlException(exception,ResourceLimitError,
2793           "MemoryAllocationFailed",PackageName);
2794         goto PerlException;
2795       }
2796     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2797     if (length == (STRLEN *) NULL)
2798       {
2799         ThrowPerlException(exception,ResourceLimitError,
2800           "MemoryAllocationFailed",PackageName);
2801         goto PerlException;
2802       }
2803     if (sv_isobject(ST(0)) == 0)
2804       {
2805         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2806           PackageName);
2807         goto PerlException;
2808       }
2809     reference=SvRV(ST(0));
2810     hv=SvSTASH(reference);
2811     if (SvTYPE(reference) != SVt_PVAV)
2812       {
2813         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2814           PackageName);
2815         goto PerlException;
2816       }
2817     av=(AV *) reference;
2818     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2819       exception);
2820     n=1;
2821     if (items <= 1)
2822       {
2823         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2824         goto PerlException;
2825       }
2826     for (n=0, i=0; i < ac; i++)
2827     {
2828       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2829       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2830         {
2831           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2832           continue;
2833         }
2834       n++;
2835     }
2836     list[n]=(char *) NULL;
2837     keep=list;
2838     for (i=number_images=0; i < n; i++)
2839     {
2840       image=BlobToImage(info->image_info,list[i],length[i],exception);
2841       if (image == (Image *) NULL)
2842         break;
2843       for ( ; image; image=image->next)
2844       {
2845         AddImageToRegistry(sv,image);
2846         rv=newRV(sv);
2847         av_push(av,sv_bless(rv,hv));
2848         SvREFCNT_dec(sv);
2849         number_images++;
2850       }
2851     }
2852     /*
2853       Free resources.
2854     */
2855     for (i=0; i < n; i++)
2856       if (list[i] != (char *) NULL)
2857         for (p=keep; list[i] != *p++; )
2858           if (*p == (char *) NULL)
2859             {
2860               list[i]=(char *) RelinquishMagickMemory(list[i]);
2861               break;
2862             }
2863
2864   PerlException:
2865     if (list)
2866       list=(char **) RelinquishMagickMemory(list);
2867     if (length)
2868       length=(STRLEN *) RelinquishMagickMemory(length);
2869     InheritPerlException(exception,perl_exception);
2870     exception=DestroyExceptionInfo(exception);
2871     sv_setiv(perl_exception,(IV) number_images);
2872     SvPOK_on(perl_exception);
2873     ST(0)=sv_2mortal(perl_exception);
2874     XSRETURN(1);
2875   }
2876 \f
2877 #
2878 ###############################################################################
2879 #                                                                             #
2880 #                                                                             #
2881 #                                                                             #
2882 #   C h a n n e l F x                                                         #
2883 #                                                                             #
2884 #                                                                             #
2885 #                                                                             #
2886 ###############################################################################
2887 #
2888 #
2889 void
2890 ChannelFx(ref,...)
2891   Image::Magick ref=NO_INIT
2892   ALIAS:
2893     ChannelFxImage  = 1
2894     channelfx       = 2
2895     channelfximage  = 3
2896   PPCODE:
2897   {
2898     AV
2899       *av;
2900
2901     char
2902       *attribute,
2903       expression[MagickPathExtent];
2904
2905     ChannelType
2906       channel,
2907       channel_mask;
2908
2909     ExceptionInfo
2910       *exception;
2911
2912     HV
2913       *hv;
2914
2915     Image
2916       *image;
2917
2918     register ssize_t
2919       i;
2920
2921     struct PackageInfo
2922       *info;
2923
2924     SV
2925       *av_reference,
2926       *perl_exception,
2927       *reference,
2928       *rv,
2929       *sv;
2930
2931     PERL_UNUSED_VAR(ref);
2932     PERL_UNUSED_VAR(ix);
2933     exception=AcquireExceptionInfo();
2934     perl_exception=newSVpv("",0);
2935     sv=NULL;
2936     attribute=NULL;
2937     av=NULL;
2938     if (sv_isobject(ST(0)) == 0)
2939       {
2940         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2941           PackageName);
2942         goto PerlException;
2943       }
2944     reference=SvRV(ST(0));
2945     hv=SvSTASH(reference);
2946     av=newAV();
2947     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2948     SvREFCNT_dec(av);
2949     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2950     if (image == (Image *) NULL)
2951       {
2952         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2953           PackageName);
2954         goto PerlException;
2955       }
2956     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2957     /*
2958       Get options.
2959     */
2960     channel=DefaultChannels;
2961     (void) CopyMagickString(expression,"u",MagickPathExtent);
2962     if (items == 2)
2963       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2964     else
2965       for (i=2; i < items; i+=2)
2966       {
2967         attribute=(char *) SvPV(ST(i-1),na);
2968         switch (*attribute)
2969         {
2970           case 'C':
2971           case 'c':
2972           {
2973             if (LocaleCompare(attribute,"channel") == 0)
2974               {
2975                 ssize_t
2976                   option;
2977
2978                 option=ParseChannelOption(SvPV(ST(i),na));
2979                 if (option < 0)
2980                   {
2981                     ThrowPerlException(exception,OptionError,
2982                       "UnrecognizedType",SvPV(ST(i),na));
2983                     return;
2984                   }
2985                 channel=(ChannelType) option;
2986                 break;
2987               }
2988             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2989               attribute);
2990             break;
2991           }
2992           case 'E':
2993           case 'e':
2994           {
2995             if (LocaleCompare(attribute,"expression") == 0)
2996               {
2997                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2998                   MagickPathExtent);
2999                 break;
3000               }
3001             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3002               attribute);
3003             break;
3004           }
3005           default:
3006           {
3007             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3008               attribute);
3009             break;
3010           }
3011         }
3012       }
3013     channel_mask=SetImageChannelMask(image,channel);
3014     image=ChannelFxImage(image,expression,exception);
3015     if (image != (Image *) NULL)
3016       (void) SetImageChannelMask(image,channel_mask);
3017     if (image == (Image *) NULL)
3018       goto PerlException;
3019     for ( ; image; image=image->next)
3020     {
3021       AddImageToRegistry(sv,image);
3022       rv=newRV(sv);
3023       av_push(av,sv_bless(rv,hv));
3024       SvREFCNT_dec(sv);
3025     }
3026     exception=DestroyExceptionInfo(exception);
3027     ST(0)=av_reference;
3028     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3029     XSRETURN(1);
3030
3031   PerlException:
3032     InheritPerlException(exception,perl_exception);
3033     exception=DestroyExceptionInfo(exception);
3034     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3035     SvPOK_on(perl_exception);
3036     ST(0)=sv_2mortal(perl_exception);
3037     XSRETURN(1);
3038   }
3039 \f
3040 #
3041 ###############################################################################
3042 #                                                                             #
3043 #                                                                             #
3044 #                                                                             #
3045 #   C l o n e                                                                 #
3046 #                                                                             #
3047 #                                                                             #
3048 #                                                                             #
3049 ###############################################################################
3050 #
3051 #
3052 void
3053 Clone(ref)
3054   Image::Magick ref=NO_INIT
3055   ALIAS:
3056     CopyImage   = 1
3057     copy        = 2
3058     copyimage   = 3
3059     CloneImage  = 4
3060     clone       = 5
3061     cloneimage  = 6
3062     Clone       = 7
3063   PPCODE:
3064   {
3065     AV
3066       *av;
3067
3068     ExceptionInfo
3069       *exception;
3070
3071     HV
3072       *hv;
3073
3074     Image
3075       *clone,
3076       *image;
3077
3078     struct PackageInfo
3079       *info;
3080
3081     SV
3082       *perl_exception,
3083       *reference,
3084       *rv,
3085       *sv;
3086
3087     PERL_UNUSED_VAR(ref);
3088     PERL_UNUSED_VAR(ix);
3089     exception=AcquireExceptionInfo();
3090     perl_exception=newSVpv("",0);
3091     sv=NULL;
3092     if (sv_isobject(ST(0)) == 0)
3093       {
3094         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3095           PackageName);
3096         goto PerlException;
3097       }
3098     reference=SvRV(ST(0));
3099     hv=SvSTASH(reference);
3100     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3101     if (image == (Image *) NULL)
3102       {
3103         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3104           PackageName);
3105         goto PerlException;
3106       }
3107     /*
3108       Create blessed Perl array for the returned image.
3109     */
3110     av=newAV();
3111     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3112     SvREFCNT_dec(av);
3113     for ( ; image; image=image->next)
3114     {
3115       clone=CloneImage(image,0,0,MagickTrue,exception);
3116       if (clone == (Image *) NULL)
3117         break;
3118       AddImageToRegistry(sv,clone);
3119       rv=newRV(sv);
3120       av_push(av,sv_bless(rv,hv));
3121       SvREFCNT_dec(sv);
3122     }
3123     exception=DestroyExceptionInfo(exception);
3124     SvREFCNT_dec(perl_exception);
3125     XSRETURN(1);
3126
3127   PerlException:
3128     InheritPerlException(exception,perl_exception);
3129     exception=DestroyExceptionInfo(exception);
3130     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3131     SvPOK_on(perl_exception);
3132     ST(0)=sv_2mortal(perl_exception);
3133     XSRETURN(1);
3134   }
3135 \f
3136 #
3137 ###############################################################################
3138 #                                                                             #
3139 #                                                                             #
3140 #                                                                             #
3141 #   C L O N E                                                                 #
3142 #                                                                             #
3143 #                                                                             #
3144 #                                                                             #
3145 ###############################################################################
3146 #
3147 #
3148 void
3149 CLONE(ref,...)
3150   SV *ref;
3151   CODE:
3152   {
3153     PERL_UNUSED_VAR(ref);
3154     if (magick_registry != (SplayTreeInfo *) NULL)
3155       {
3156         register Image
3157           *p;
3158
3159         ResetSplayTreeIterator(magick_registry);
3160         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3161         while (p != (Image *) NULL)
3162         {
3163           ReferenceImage(p);
3164           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3165         }
3166       }
3167   }
3168 \f
3169 #
3170 ###############################################################################
3171 #                                                                             #
3172 #                                                                             #
3173 #                                                                             #
3174 #   C o a l e s c e                                                           #
3175 #                                                                             #
3176 #                                                                             #
3177 #                                                                             #
3178 ###############################################################################
3179 #
3180 #
3181 void
3182 Coalesce(ref)
3183   Image::Magick ref=NO_INIT
3184   ALIAS:
3185     CoalesceImage   = 1
3186     coalesce        = 2
3187     coalesceimage   = 3
3188   PPCODE:
3189   {
3190     AV
3191       *av;
3192
3193     ExceptionInfo
3194       *exception;
3195
3196     HV
3197       *hv;
3198
3199     Image
3200       *image;
3201
3202     struct PackageInfo
3203       *info;
3204
3205     SV
3206       *av_reference,
3207       *perl_exception,
3208       *reference,
3209       *rv,
3210       *sv;
3211
3212     PERL_UNUSED_VAR(ref);
3213     PERL_UNUSED_VAR(ix);
3214     exception=AcquireExceptionInfo();
3215     perl_exception=newSVpv("",0);
3216     sv=NULL;
3217     if (sv_isobject(ST(0)) == 0)
3218       {
3219         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3220           PackageName);
3221         goto PerlException;
3222       }
3223     reference=SvRV(ST(0));
3224     hv=SvSTASH(reference);
3225     av=newAV();
3226     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3227     SvREFCNT_dec(av);
3228     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3229     if (image == (Image *) NULL)
3230       {
3231         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3232           PackageName);
3233         goto PerlException;
3234       }
3235     image=CoalesceImages(image,exception);
3236     if (image == (Image *) NULL)
3237       goto PerlException;
3238     for ( ; image; image=image->next)
3239     {
3240       AddImageToRegistry(sv,image);
3241       rv=newRV(sv);
3242       av_push(av,sv_bless(rv,hv));
3243       SvREFCNT_dec(sv);
3244     }
3245     exception=DestroyExceptionInfo(exception);
3246     ST(0)=av_reference;
3247     SvREFCNT_dec(perl_exception);
3248     XSRETURN(1);
3249
3250   PerlException:
3251     InheritPerlException(exception,perl_exception);
3252     exception=DestroyExceptionInfo(exception);
3253     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3254     SvPOK_on(perl_exception);
3255     ST(0)=sv_2mortal(perl_exception);
3256     XSRETURN(1);
3257   }
3258 \f
3259 #
3260 ###############################################################################
3261 #                                                                             #
3262 #                                                                             #
3263 #                                                                             #
3264 #   C o m p a r e                                                             #
3265 #                                                                             #
3266 #                                                                             #
3267 #                                                                             #
3268 ###############################################################################
3269 #
3270 #
3271 void
3272 Compare(ref,...)
3273   Image::Magick ref=NO_INIT
3274   ALIAS:
3275     CompareImages = 1
3276     compare      = 2
3277     compareimage = 3
3278   PPCODE:
3279   {
3280     AV
3281       *av;
3282
3283     char
3284       *attribute;
3285
3286     double
3287       distortion;
3288
3289     ExceptionInfo
3290       *exception;
3291
3292     HV
3293       *hv;
3294
3295     Image
3296       *difference_image,
3297       *image,
3298       *reconstruct_image;
3299
3300     MetricType
3301       metric;
3302
3303     register ssize_t
3304       i;
3305
3306     ssize_t
3307       option;
3308
3309     struct PackageInfo
3310       *info;
3311
3312     SV
3313       *av_reference,
3314       *perl_exception,
3315       *reference,
3316       *rv,
3317       *sv;
3318
3319     PERL_UNUSED_VAR(ref);
3320     PERL_UNUSED_VAR(ix);
3321     exception=AcquireExceptionInfo();
3322     perl_exception=newSVpv("",0);
3323     sv=NULL;
3324     av=NULL;
3325     attribute=NULL;
3326     if (sv_isobject(ST(0)) == 0)
3327       {
3328         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3329           PackageName);
3330         goto PerlException;
3331       }
3332     reference=SvRV(ST(0));
3333     hv=SvSTASH(reference);
3334     av=newAV();
3335     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3336     SvREFCNT_dec(av);
3337     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3338     if (image == (Image *) NULL)
3339       {
3340         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3341           PackageName);
3342         goto PerlException;
3343       }
3344     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3345     /*
3346       Get attribute.
3347     */
3348     reconstruct_image=image;
3349     metric=RootMeanSquaredErrorMetric;
3350     for (i=2; i < items; i+=2)
3351     {
3352       attribute=(char *) SvPV(ST(i-1),na);
3353       switch (*attribute)
3354       {
3355         case 'C':
3356         case 'c':
3357         {
3358           if (LocaleCompare(attribute,"channel") == 0)
3359             {
3360               ssize_t
3361                 option;
3362
3363               option=ParseChannelOption(SvPV(ST(i),na));
3364               if (option < 0)
3365                 {
3366                   ThrowPerlException(exception,OptionError,
3367                     "UnrecognizedType",SvPV(ST(i),na));
3368                   return;
3369                 }
3370               (void) SetPixelChannelMask(image,(ChannelType) option);
3371               break;
3372             }
3373           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3374             attribute);
3375           break;
3376         }
3377         case 'F':
3378         case 'f':
3379         {
3380           if (LocaleCompare(attribute,"fuzz") == 0)
3381             {
3382               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3383               break;
3384             }
3385           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3386             attribute);
3387           break;
3388         }
3389         case 'I':
3390         case 'i':
3391         {
3392           if (LocaleCompare(attribute,"image") == 0)
3393             {
3394               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3395                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3396               break;
3397             }
3398           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3399             attribute);
3400           break;
3401         }
3402         case 'M':
3403         case 'm':
3404         {
3405           if (LocaleCompare(attribute,"metric") == 0)
3406             {
3407               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3408                 SvPV(ST(i),na));
3409               if (option < 0)
3410                 {
3411                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3412                     SvPV(ST(i),na));
3413                   break;
3414                 }
3415               metric=(MetricType) option;
3416               break;
3417             }
3418           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3419             attribute);
3420           break;
3421         }
3422         default:
3423         {
3424           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3425             attribute);
3426           break;
3427         }
3428       }
3429     }
3430     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3431       exception);
3432     if (difference_image != (Image *) NULL)
3433       {
3434         difference_image->error.mean_error_per_pixel=distortion;
3435         AddImageToRegistry(sv,difference_image);
3436         rv=newRV(sv);
3437         av_push(av,sv_bless(rv,hv));
3438         SvREFCNT_dec(sv);
3439       }
3440     exception=DestroyExceptionInfo(exception);
3441     ST(0)=av_reference;
3442     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3443     XSRETURN(1);
3444
3445   PerlException:
3446     InheritPerlException(exception,perl_exception);
3447     exception=DestroyExceptionInfo(exception);
3448     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3449     SvPOK_on(perl_exception);
3450     ST(0)=sv_2mortal(perl_exception);
3451     XSRETURN(1);
3452   }
3453 \f
3454 #
3455 ###############################################################################
3456 #                                                                             #
3457 #                                                                             #
3458 #                                                                             #
3459 #   C o m p l e x I m a g e s                                                 #
3460 #                                                                             #
3461 #                                                                             #
3462 #                                                                             #
3463 ###############################################################################
3464 #
3465 #
3466 void
3467 ComplexImages(ref)
3468   Image::Magick ref=NO_INIT
3469   ALIAS:
3470     ComplexImages   = 1
3471     compleximages   = 2
3472   PPCODE:
3473   {
3474     AV
3475       *av;
3476
3477     char
3478       *attribute,
3479       *p;
3480
3481     ComplexOperator
3482       op;
3483
3484     ExceptionInfo
3485       *exception;
3486
3487     HV
3488       *hv;
3489
3490     Image
3491       *image;
3492
3493     register ssize_t
3494       i;
3495
3496     struct PackageInfo
3497       *info;
3498
3499     SV
3500       *perl_exception,
3501       *reference,
3502       *rv,
3503       *sv;
3504
3505     PERL_UNUSED_VAR(ref);
3506     PERL_UNUSED_VAR(ix);
3507     exception=AcquireExceptionInfo();
3508     perl_exception=newSVpv("",0);
3509     sv=NULL;
3510     if (sv_isobject(ST(0)) == 0)
3511       {
3512         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3513           PackageName);
3514         goto PerlException;
3515       }
3516     reference=SvRV(ST(0));
3517     hv=SvSTASH(reference);
3518     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3519     if (image == (Image *) NULL)
3520       {
3521         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3522           PackageName);
3523         goto PerlException;
3524       }
3525     op=UndefinedComplexOperator;
3526     if (items == 2)
3527       {
3528         ssize_t
3529           in;
3530
3531         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3532           SvPV(ST(1),na));
3533         if (in < 0)
3534           {
3535             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3536               SvPV(ST(1),na));
3537             return;
3538           }
3539         op=(ComplexOperator) in;
3540       }
3541     else
3542       for (i=2; i < items; i+=2)
3543       {
3544         attribute=(char *) SvPV(ST(i-1),na);
3545         switch (*attribute)
3546         {
3547           case 'O':
3548           case 'o':
3549           {
3550             if (LocaleCompare(attribute,"operator") == 0)
3551               {
3552                 ssize_t
3553                   in;
3554
3555                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3556                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3557                 if (in < 0)
3558                   {
3559                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3560                       SvPV(ST(i),na));
3561                     return;
3562                   }
3563                 op=(ComplexOperator) in;
3564                 break;
3565               }
3566             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3567               attribute);
3568             break;
3569           }
3570           default:
3571           {
3572             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3573               attribute);
3574             break;
3575           }
3576         }
3577       }
3578     image=ComplexImages(image,op,exception);
3579     if (image == (Image *) NULL)
3580       goto PerlException;
3581     /*
3582       Create blessed Perl array for the returned image.
3583     */
3584     av=newAV();
3585     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3586     SvREFCNT_dec(av);
3587     AddImageToRegistry(sv,image);
3588     rv=newRV(sv);
3589     av_push(av,sv_bless(rv,hv));
3590     SvREFCNT_dec(sv);
3591     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3592     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3593       "complex-%.*s",(int) (MagickPathExtent-9),
3594       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3595     (void) CopyMagickString(image->filename,info->image_info->filename,
3596       MagickPathExtent);
3597     SetImageInfo(info->image_info,0,exception);
3598     exception=DestroyExceptionInfo(exception);
3599     SvREFCNT_dec(perl_exception);
3600     XSRETURN(1);
3601
3602   PerlException:
3603     InheritPerlException(exception,perl_exception);
3604     exception=DestroyExceptionInfo(exception);
3605     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3606     SvPOK_on(perl_exception);
3607     ST(0)=sv_2mortal(perl_exception);
3608     XSRETURN(1);
3609   }
3610 \f
3611 #
3612 ###############################################################################
3613 #                                                                             #
3614 #                                                                             #
3615 #                                                                             #
3616 #   C o m p a r e L a y e r s                                                 #
3617 #                                                                             #
3618 #                                                                             #
3619 #                                                                             #
3620 ###############################################################################
3621 #
3622 #
3623 void
3624 CompareLayers(ref)
3625   Image::Magick ref=NO_INIT
3626   ALIAS:
3627     CompareImagesLayers   = 1
3628     comparelayers        = 2
3629     compareimagelayers   = 3
3630   PPCODE:
3631   {
3632     AV
3633       *av;
3634
3635     char
3636       *attribute;
3637
3638     ExceptionInfo
3639       *exception;
3640
3641     HV
3642       *hv;
3643
3644     Image
3645       *image;
3646
3647     LayerMethod
3648       method;
3649
3650     register ssize_t
3651       i;
3652
3653     ssize_t
3654       option;
3655
3656     struct PackageInfo
3657       *info;
3658
3659     SV
3660       *av_reference,
3661       *perl_exception,
3662       *reference,
3663       *rv,
3664       *sv;
3665
3666     PERL_UNUSED_VAR(ref);
3667     PERL_UNUSED_VAR(ix);
3668     exception=AcquireExceptionInfo();
3669     perl_exception=newSVpv("",0);
3670     sv=NULL;
3671     if (sv_isobject(ST(0)) == 0)
3672       {
3673         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3674           PackageName);
3675         goto PerlException;
3676       }
3677     reference=SvRV(ST(0));
3678     hv=SvSTASH(reference);
3679     av=newAV();
3680     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3681     SvREFCNT_dec(av);
3682     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3683     if (image == (Image *) NULL)
3684       {
3685         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3686           PackageName);
3687         goto PerlException;
3688       }
3689     method=CompareAnyLayer;
3690     for (i=2; i < items; i+=2)
3691     {
3692       attribute=(char *) SvPV(ST(i-1),na);
3693       switch (*attribute)
3694       {
3695         case 'M':
3696         case 'm':
3697         {
3698           if (LocaleCompare(attribute,"method") == 0)
3699             {
3700               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3701                 SvPV(ST(i),na));
3702               if (option < 0)
3703                 {
3704                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3705                     SvPV(ST(i),na));
3706                   break;
3707                 }
3708                method=(LayerMethod) option;
3709               break;
3710             }
3711           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3712             attribute);
3713           break;
3714         }
3715         default:
3716         {
3717           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3718             attribute);
3719           break;
3720         }
3721       }
3722     }
3723     image=CompareImagesLayers(image,method,exception);
3724     if (image == (Image *) NULL)
3725       goto PerlException;
3726     for ( ; image; image=image->next)
3727     {
3728       AddImageToRegistry(sv,image);
3729       rv=newRV(sv);
3730       av_push(av,sv_bless(rv,hv));
3731       SvREFCNT_dec(sv);
3732     }
3733     exception=DestroyExceptionInfo(exception);
3734     ST(0)=av_reference;
3735     SvREFCNT_dec(perl_exception);
3736     XSRETURN(1);
3737
3738   PerlException:
3739     InheritPerlException(exception,perl_exception);
3740     exception=DestroyExceptionInfo(exception);
3741     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3742     SvPOK_on(perl_exception);
3743     ST(0)=sv_2mortal(perl_exception);
3744     XSRETURN(1);
3745   }
3746 \f
3747 #
3748 ###############################################################################
3749 #                                                                             #
3750 #                                                                             #
3751 #                                                                             #
3752 #   D e s t r o y                                                             #
3753 #                                                                             #
3754 #                                                                             #
3755 #                                                                             #
3756 ###############################################################################
3757 #
3758 #
3759 void
3760 DESTROY(ref)
3761   Image::Magick ref=NO_INIT
3762   PPCODE:
3763   {
3764     SV
3765       *reference;
3766
3767     PERL_UNUSED_VAR(ref);
3768     if (sv_isobject(ST(0)) == 0)
3769       croak("ReferenceIsNotMyType");
3770     reference=SvRV(ST(0));
3771     switch (SvTYPE(reference))
3772     {
3773       case SVt_PVAV:
3774       {
3775         char
3776           message[MagickPathExtent];
3777
3778         const SV
3779           *key;
3780
3781         HV
3782           *hv;
3783
3784         GV
3785           **gvp;
3786
3787         struct PackageInfo
3788           *info;
3789
3790         SV
3791           *sv;
3792
3793         /*
3794           Array (AV *) reference
3795         */
3796         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3797           XS_VERSION,reference);
3798         hv=gv_stashpv(PackageName, FALSE);
3799         if (!hv)
3800           break;
3801         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3802         if (!gvp)
3803           break;
3804         sv=GvSV(*gvp);
3805         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3806           {
3807             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3808             DestroyPackageInfo(info);
3809           }
3810         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3811         (void) key;
3812         break;
3813       }
3814       case SVt_PVMG:
3815       {
3816         Image
3817           *image;
3818
3819         /*
3820           Blessed scalar = (Image *) SvIV(reference)
3821         */
3822         image=INT2PTR(Image *,SvIV(reference));
3823         if (image != (Image *) NULL)
3824           DeleteImageFromRegistry(reference,image);
3825         break;
3826       }
3827       default:
3828         break;
3829     }
3830   }
3831 \f
3832 #
3833 ###############################################################################
3834 #                                                                             #
3835 #                                                                             #
3836 #                                                                             #
3837 #   D i s p l a y                                                             #
3838 #                                                                             #
3839 #                                                                             #
3840 #                                                                             #
3841 ###############################################################################
3842 #
3843 #
3844 void
3845 Display(ref,...)
3846   Image::Magick ref=NO_INIT
3847   ALIAS:
3848     DisplayImage  = 1
3849     display       = 2
3850     displayimage  = 3
3851   PPCODE:
3852   {
3853     ExceptionInfo
3854       *exception;
3855
3856     Image
3857       *image;
3858
3859     register ssize_t
3860       i;
3861
3862     struct PackageInfo
3863       *info,
3864       *package_info;
3865
3866     SV
3867       *perl_exception,
3868       *reference;
3869
3870     PERL_UNUSED_VAR(ref);
3871     PERL_UNUSED_VAR(ix);
3872     exception=AcquireExceptionInfo();
3873     perl_exception=newSVpv("",0);
3874     package_info=(struct PackageInfo *) NULL;
3875     if (sv_isobject(ST(0)) == 0)
3876       {
3877         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3878           PackageName);
3879         goto PerlException;
3880       }
3881     reference=SvRV(ST(0));
3882     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3883     if (image == (Image *) NULL)
3884       {
3885         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3886           PackageName);
3887         goto PerlException;
3888       }
3889     package_info=ClonePackageInfo(info,exception);
3890     if (items == 2)
3891       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3892     else
3893       if (items > 2)
3894         for (i=2; i < items; i+=2)
3895           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3896             exception);
3897     (void) DisplayImages(package_info->image_info,image,exception);
3898     (void) CatchImageException(image);
3899
3900   PerlException:
3901     if (package_info != (struct PackageInfo *) NULL)
3902       DestroyPackageInfo(package_info);
3903     InheritPerlException(exception,perl_exception);
3904     exception=DestroyExceptionInfo(exception);
3905     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3906     SvPOK_on(perl_exception);
3907     ST(0)=sv_2mortal(perl_exception);
3908     XSRETURN(1);
3909   }
3910 \f
3911 #
3912 ###############################################################################
3913 #                                                                             #
3914 #                                                                             #
3915 #                                                                             #
3916 #   E v a l u a t e I m a g e s                                               #
3917 #                                                                             #
3918 #                                                                             #
3919 #                                                                             #
3920 ###############################################################################
3921 #
3922 #
3923 void
3924 EvaluateImages(ref)
3925   Image::Magick ref=NO_INIT
3926   ALIAS:
3927     EvaluateImages   = 1
3928     evaluateimages   = 2
3929   PPCODE:
3930   {
3931     AV
3932       *av;
3933
3934     char
3935       *attribute,
3936       *p;
3937
3938     ExceptionInfo
3939       *exception;
3940
3941     HV
3942       *hv;
3943
3944     Image
3945       *image;
3946
3947     MagickEvaluateOperator
3948       op;
3949
3950     register ssize_t
3951       i;
3952
3953     struct PackageInfo
3954       *info;
3955
3956     SV
3957       *perl_exception,
3958       *reference,
3959       *rv,
3960       *sv;
3961
3962     PERL_UNUSED_VAR(ref);
3963     PERL_UNUSED_VAR(ix);
3964     exception=AcquireExceptionInfo();
3965     perl_exception=newSVpv("",0);
3966     sv=NULL;
3967     if (sv_isobject(ST(0)) == 0)
3968       {
3969         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3970           PackageName);
3971         goto PerlException;
3972       }
3973     reference=SvRV(ST(0));
3974     hv=SvSTASH(reference);
3975     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3976     if (image == (Image *) NULL)
3977       {
3978         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3979           PackageName);
3980         goto PerlException;
3981       }
3982     op=MeanEvaluateOperator;
3983     if (items == 2)
3984       {
3985         ssize_t
3986           in;
3987
3988         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3989           SvPV(ST(1),na));
3990         if (in < 0)
3991           {
3992             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3993               SvPV(ST(1),na));
3994             return;
3995           }
3996         op=(MagickEvaluateOperator) in;
3997       }
3998     else
3999       for (i=2; i < items; i+=2)
4000       {
4001         attribute=(char *) SvPV(ST(i-1),na);
4002         switch (*attribute)
4003         {
4004           case 'O':
4005           case 'o':
4006           {
4007             if (LocaleCompare(attribute,"operator") == 0)
4008               {
4009                 ssize_t
4010                   in;
4011
4012                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
4013                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
4014                 if (in < 0)
4015                   {
4016                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
4017                       SvPV(ST(i),na));
4018                     return;
4019                   }
4020                 op=(MagickEvaluateOperator) in;
4021                 break;
4022               }
4023             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4024               attribute);
4025             break;
4026           }
4027           default:
4028           {
4029             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4030               attribute);
4031             break;
4032           }
4033         }
4034       }
4035     image=EvaluateImages(image,op,exception);
4036     if (image == (Image *) NULL)
4037       goto PerlException;
4038     /*
4039       Create blessed Perl array for the returned image.
4040     */
4041     av=newAV();
4042     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4043     SvREFCNT_dec(av);
4044     AddImageToRegistry(sv,image);
4045     rv=newRV(sv);
4046     av_push(av,sv_bless(rv,hv));
4047     SvREFCNT_dec(sv);
4048     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4049     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4050       "evaluate-%.*s",(int) (MagickPathExtent-9),
4051       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4052     (void) CopyMagickString(image->filename,info->image_info->filename,
4053       MagickPathExtent);
4054     SetImageInfo(info->image_info,0,exception);
4055     exception=DestroyExceptionInfo(exception);
4056     SvREFCNT_dec(perl_exception);
4057     XSRETURN(1);
4058
4059   PerlException:
4060     InheritPerlException(exception,perl_exception);
4061     exception=DestroyExceptionInfo(exception);
4062     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4063     SvPOK_on(perl_exception);
4064     ST(0)=sv_2mortal(perl_exception);
4065     XSRETURN(1);
4066   }
4067 \f
4068 #
4069 ###############################################################################
4070 #                                                                             #
4071 #                                                                             #
4072 #                                                                             #
4073 #   F e a t u r e s                                                           #
4074 #                                                                             #
4075 #                                                                             #
4076 #                                                                             #
4077 ###############################################################################
4078 #
4079 #
4080 void
4081 Features(ref,...)
4082   Image::Magick ref=NO_INIT
4083   ALIAS:
4084     FeaturesImage = 1
4085     features      = 2
4086     featuresimage = 3
4087   PPCODE:
4088   {
4089 #define ChannelFeatures(channel,direction) \
4090 { \
4091   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4092     channel_features[channel].angular_second_moment[direction]); \
4093   PUSHs(sv_2mortal(newSVpv(message,0))); \
4094   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4095     channel_features[channel].contrast[direction]); \
4096   PUSHs(sv_2mortal(newSVpv(message,0))); \
4097   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4098     channel_features[channel].contrast[direction]); \
4099   PUSHs(sv_2mortal(newSVpv(message,0))); \
4100   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4101     channel_features[channel].variance_sum_of_squares[direction]); \
4102   PUSHs(sv_2mortal(newSVpv(message,0))); \
4103   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4104     channel_features[channel].inverse_difference_moment[direction]); \
4105   PUSHs(sv_2mortal(newSVpv(message,0))); \
4106   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4107     channel_features[channel].sum_average[direction]); \
4108   PUSHs(sv_2mortal(newSVpv(message,0))); \
4109   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4110     channel_features[channel].sum_variance[direction]); \
4111   PUSHs(sv_2mortal(newSVpv(message,0))); \
4112   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4113     channel_features[channel].sum_entropy[direction]); \
4114   PUSHs(sv_2mortal(newSVpv(message,0))); \
4115   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4116     channel_features[channel].entropy[direction]); \
4117   PUSHs(sv_2mortal(newSVpv(message,0))); \
4118   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4119     channel_features[channel].difference_variance[direction]); \
4120   PUSHs(sv_2mortal(newSVpv(message,0))); \
4121   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4122     channel_features[channel].difference_entropy[direction]); \
4123   PUSHs(sv_2mortal(newSVpv(message,0))); \
4124   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4125     channel_features[channel].measure_of_correlation_1[direction]); \
4126   PUSHs(sv_2mortal(newSVpv(message,0))); \
4127   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4128     channel_features[channel].measure_of_correlation_2[direction]); \
4129   PUSHs(sv_2mortal(newSVpv(message,0))); \
4130   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4131     channel_features[channel].maximum_correlation_coefficient[direction]); \
4132   PUSHs(sv_2mortal(newSVpv(message,0))); \
4133 }
4134
4135     AV
4136       *av;
4137
4138     char
4139       *attribute,
4140       message[MagickPathExtent];
4141
4142     ChannelFeatures
4143       *channel_features;
4144
4145     double
4146       distance;
4147
4148     ExceptionInfo
4149       *exception;
4150
4151     Image
4152       *image;
4153
4154     register ssize_t
4155       i;
4156
4157     ssize_t
4158       count;
4159
4160     struct PackageInfo
4161       *info;
4162
4163     SV
4164       *perl_exception,
4165       *reference;
4166
4167     PERL_UNUSED_VAR(ref);
4168     PERL_UNUSED_VAR(ix);
4169     exception=AcquireExceptionInfo();
4170     perl_exception=newSVpv("",0);
4171     av=NULL;
4172     if (sv_isobject(ST(0)) == 0)
4173       {
4174         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4175           PackageName);
4176         goto PerlException;
4177       }
4178     reference=SvRV(ST(0));
4179     av=newAV();
4180     SvREFCNT_dec(av);
4181     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4182     if (image == (Image *) NULL)
4183       {
4184         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4185           PackageName);
4186         goto PerlException;
4187       }
4188     distance=1.0;
4189     for (i=2; i < items; i+=2)
4190     {
4191       attribute=(char *) SvPV(ST(i-1),na);
4192       switch (*attribute)
4193       {
4194         case 'D':
4195         case 'd':
4196         {
4197           if (LocaleCompare(attribute,"distance") == 0)
4198             {
4199               distance=StringToLong((char *) SvPV(ST(1),na));
4200               break;
4201             }
4202           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4203             attribute);
4204           break;
4205         }
4206         default:
4207         {
4208           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4209             attribute);
4210           break;
4211         }
4212       }
4213     }
4214     count=0;
4215     for ( ; image; image=image->next)
4216     {
4217       channel_features=GetImageFeatures(image,distance,exception);
4218       if (channel_features == (ChannelFeatures *) NULL)
4219         continue;
4220       count++;
4221       EXTEND(sp,280*count);
4222       for (i=0; i < 4; i++)
4223       {
4224         ChannelFeatures(RedChannel,i);
4225         ChannelFeatures(GreenChannel,i);
4226         ChannelFeatures(BlueChannel,i);
4227         if (image->colorspace == CMYKColorspace)
4228           ChannelFeatures(BlackChannel,i);
4229         if (image->alpha_trait != UndefinedPixelTrait)
4230           ChannelFeatures(AlphaChannel,i);
4231       }
4232       channel_features=(ChannelFeatures *)
4233         RelinquishMagickMemory(channel_features);
4234     }
4235
4236   PerlException:
4237     InheritPerlException(exception,perl_exception);
4238     exception=DestroyExceptionInfo(exception);
4239     SvREFCNT_dec(perl_exception);
4240   }
4241 \f
4242 #
4243 ###############################################################################
4244 #                                                                             #
4245 #                                                                             #
4246 #                                                                             #
4247 #   F l a t t e n                                                             #
4248 #                                                                             #
4249 #                                                                             #
4250 #                                                                             #
4251 ###############################################################################
4252 #
4253 #
4254 void
4255 Flatten(ref)
4256   Image::Magick ref=NO_INIT
4257   ALIAS:
4258     FlattenImage   = 1
4259     flatten        = 2
4260     flattenimage   = 3
4261   PPCODE:
4262   {
4263     AV
4264       *av;
4265
4266     char
4267       *attribute,
4268       *p;
4269
4270     ExceptionInfo
4271       *exception;
4272
4273     HV
4274       *hv;
4275
4276     Image
4277       *image;
4278
4279     PixelInfo
4280       background_color;
4281
4282     register ssize_t
4283       i;
4284
4285     struct PackageInfo
4286       *info;
4287
4288     SV
4289       *perl_exception,
4290       *reference,
4291       *rv,
4292       *sv;
4293
4294     PERL_UNUSED_VAR(ref);
4295     PERL_UNUSED_VAR(ix);
4296     exception=AcquireExceptionInfo();
4297     perl_exception=newSVpv("",0);
4298     sv=NULL;
4299     if (sv_isobject(ST(0)) == 0)
4300       {
4301         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4302           PackageName);
4303         goto PerlException;
4304       }
4305     reference=SvRV(ST(0));
4306     hv=SvSTASH(reference);
4307     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4308     if (image == (Image *) NULL)
4309       {
4310         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4311           PackageName);
4312         goto PerlException;
4313       }
4314     background_color=image->background_color;
4315     if (items == 2)
4316       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4317         &background_color,exception);
4318     else
4319       for (i=2; i < items; i+=2)
4320       {
4321         attribute=(char *) SvPV(ST(i-1),na);
4322         switch (*attribute)
4323         {
4324           case 'B':
4325           case 'b':
4326           {
4327             if (LocaleCompare(attribute,"background") == 0)
4328               {
4329                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4330                   AllCompliance,&background_color,exception);
4331                 break;
4332               }
4333             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4334               attribute);
4335             break;
4336           }
4337           default:
4338           {
4339             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4340               attribute);
4341             break;
4342           }
4343         }
4344       }
4345     image->background_color=background_color;
4346     image=MergeImageLayers(image,FlattenLayer,exception);
4347     if (image == (Image *) NULL)
4348       goto PerlException;
4349     /*
4350       Create blessed Perl array for the returned image.
4351     */
4352     av=newAV();
4353     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4354     SvREFCNT_dec(av);
4355     AddImageToRegistry(sv,image);
4356     rv=newRV(sv);
4357     av_push(av,sv_bless(rv,hv));
4358     SvREFCNT_dec(sv);
4359     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4360     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4361       "flatten-%.*s",(int) (MagickPathExtent-9),
4362       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4363     (void) CopyMagickString(image->filename,info->image_info->filename,
4364       MagickPathExtent);
4365     SetImageInfo(info->image_info,0,exception);
4366     exception=DestroyExceptionInfo(exception);
4367     SvREFCNT_dec(perl_exception);
4368     XSRETURN(1);
4369
4370   PerlException:
4371     InheritPerlException(exception,perl_exception);
4372     exception=DestroyExceptionInfo(exception);
4373     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4374     SvPOK_on(perl_exception);  /* return messages in string context */
4375     ST(0)=sv_2mortal(perl_exception);
4376     XSRETURN(1);
4377   }
4378 \f
4379 #
4380 ###############################################################################
4381 #                                                                             #
4382 #                                                                             #
4383 #                                                                             #
4384 #   F x                                                                       #
4385 #                                                                             #
4386 #                                                                             #
4387 #                                                                             #
4388 ###############################################################################
4389 #
4390 #
4391 void
4392 Fx(ref,...)
4393   Image::Magick ref=NO_INIT
4394   ALIAS:
4395     FxImage  = 1
4396     fx       = 2
4397     fximage  = 3
4398   PPCODE:
4399   {
4400     AV
4401       *av;
4402
4403     char
4404       *attribute,
4405       expression[MagickPathExtent];
4406
4407     ChannelType
4408       channel,
4409       channel_mask;
4410
4411     ExceptionInfo
4412       *exception;
4413
4414     HV
4415       *hv;
4416
4417     Image
4418       *image;
4419
4420     register ssize_t
4421       i;
4422
4423     struct PackageInfo
4424       *info;
4425
4426     SV
4427       *av_reference,
4428       *perl_exception,
4429       *reference,
4430       *rv,
4431       *sv;
4432
4433     PERL_UNUSED_VAR(ref);
4434     PERL_UNUSED_VAR(ix);
4435     exception=AcquireExceptionInfo();
4436     perl_exception=newSVpv("",0);
4437     sv=NULL;
4438     attribute=NULL;
4439     av=NULL;
4440     if (sv_isobject(ST(0)) == 0)
4441       {
4442         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4443           PackageName);
4444         goto PerlException;
4445       }
4446     reference=SvRV(ST(0));
4447     hv=SvSTASH(reference);
4448     av=newAV();
4449     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4450     SvREFCNT_dec(av);
4451     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4452     if (image == (Image *) NULL)
4453       {
4454         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4455           PackageName);
4456         goto PerlException;
4457       }
4458     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4459     /*
4460       Get options.
4461     */
4462     channel=DefaultChannels;
4463     (void) CopyMagickString(expression,"u",MagickPathExtent);
4464     if (items == 2)
4465       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4466     else
4467       for (i=2; i < items; i+=2)
4468       {
4469         attribute=(char *) SvPV(ST(i-1),na);
4470         switch (*attribute)
4471         {
4472           case 'C':
4473           case 'c':
4474           {
4475             if (LocaleCompare(attribute,"channel") == 0)
4476               {
4477                 ssize_t
4478                   option;
4479
4480                 option=ParseChannelOption(SvPV(ST(i),na));
4481                 if (option < 0)
4482                   {
4483                     ThrowPerlException(exception,OptionError,
4484                       "UnrecognizedType",SvPV(ST(i),na));
4485                     return;
4486                   }
4487                 channel=(ChannelType) option;
4488                 break;
4489               }
4490             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4491               attribute);
4492             break;
4493           }
4494           case 'E':
4495           case 'e':
4496           {
4497             if (LocaleCompare(attribute,"expression") == 0)
4498               {
4499                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4500                   MagickPathExtent);
4501                 break;
4502               }
4503             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4504               attribute);
4505             break;
4506           }
4507           default:
4508           {
4509             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4510               attribute);
4511             break;
4512           }
4513         }
4514       }
4515     channel_mask=SetImageChannelMask(image,channel);
4516     image=FxImage(image,expression,exception);
4517     if (image != (Image *) NULL)
4518       (void) SetImageChannelMask(image,channel_mask);
4519     if (image == (Image *) NULL)
4520       goto PerlException;
4521     for ( ; image; image=image->next)
4522     {
4523       AddImageToRegistry(sv,image);
4524       rv=newRV(sv);
4525       av_push(av,sv_bless(rv,hv));
4526       SvREFCNT_dec(sv);
4527     }
4528     exception=DestroyExceptionInfo(exception);
4529     ST(0)=av_reference;
4530     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4531     XSRETURN(1);
4532
4533   PerlException:
4534     InheritPerlException(exception,perl_exception);
4535     exception=DestroyExceptionInfo(exception);
4536     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4537     SvPOK_on(perl_exception);
4538     ST(0)=sv_2mortal(perl_exception);
4539     XSRETURN(1);
4540   }
4541 \f
4542 #
4543 ###############################################################################
4544 #                                                                             #
4545 #                                                                             #
4546 #                                                                             #
4547 #   G e t                                                                     #
4548 #                                                                             #
4549 #                                                                             #
4550 #                                                                             #
4551 ###############################################################################
4552 #
4553 #
4554 void
4555 Get(ref,...)
4556   Image::Magick ref=NO_INIT
4557   ALIAS:
4558     GetAttributes = 1
4559     GetAttribute  = 2
4560     get           = 3
4561     getattributes = 4
4562     getattribute  = 5
4563   PPCODE:
4564   {
4565     char
4566       *attribute,
4567       color[MagickPathExtent];
4568
4569     const char
4570       *value;
4571
4572     ExceptionInfo
4573       *exception;
4574
4575     Image
4576       *image;
4577
4578     long
4579       j;
4580
4581     register ssize_t
4582       i;
4583
4584     struct PackageInfo
4585       *info;
4586
4587     SV
4588       *perl_exception,
4589       *reference,
4590       *s;
4591
4592     PERL_UNUSED_VAR(ref);
4593     PERL_UNUSED_VAR(ix);
4594     exception=AcquireExceptionInfo();
4595     perl_exception=newSVpv("",0);
4596     if (sv_isobject(ST(0)) == 0)
4597       {
4598         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4599           PackageName);
4600         XSRETURN_EMPTY;
4601       }
4602     reference=SvRV(ST(0));
4603     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4604     if (image == (Image *) NULL && !info)
4605       XSRETURN_EMPTY;
4606     EXTEND(sp,items);
4607     for (i=1; i < items; i++)
4608     {
4609       attribute=(char *) SvPV(ST(i),na);
4610       s=NULL;
4611       switch (*attribute)
4612       {
4613         case 'A':
4614         case 'a':
4615         {
4616           if (LocaleCompare(attribute,"adjoin") == 0)
4617             {
4618               if (info)
4619                 s=newSViv((ssize_t) info->image_info->adjoin);
4620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621               continue;
4622             }
4623           if (LocaleCompare(attribute,"antialias") == 0)
4624             {
4625               if (info)
4626                 s=newSViv((ssize_t) info->image_info->antialias);
4627               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4628               continue;
4629             }
4630           if (LocaleCompare(attribute,"area") == 0)
4631             {
4632               s=newSViv(GetMagickResource(AreaResource));
4633               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4634               continue;
4635             }
4636           if (LocaleCompare(attribute,"attenuate") == 0)
4637             {
4638               const char
4639                 *value;
4640
4641               value=GetImageProperty(image,attribute,exception);
4642               if (value != (const char *) NULL)
4643                 s=newSVpv(value,0);
4644               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4645               continue;
4646             }
4647           if (LocaleCompare(attribute,"authenticate") == 0)
4648             {
4649               if (info)
4650                 {
4651                   const char
4652                     *option;
4653
4654                   option=GetImageOption(info->image_info,attribute);
4655                   if (option != (const char *) NULL)
4656                     s=newSVpv(option,0);
4657                 }
4658               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4659               continue;
4660             }
4661           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4662             attribute);
4663           break;
4664         }
4665         case 'B':
4666         case 'b':
4667         {
4668           if (LocaleCompare(attribute,"background") == 0)
4669             {
4670               if (image == (Image *) NULL)
4671                 break;
4672               (void) FormatLocaleString(color,MagickPathExtent,
4673                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4674                 (double) image->background_color.green,
4675                 (double) image->background_color.blue,
4676                 (double) image->background_color.alpha);
4677               s=newSVpv(color,0);
4678               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4679               continue;
4680             }
4681           if (LocaleCompare(attribute,"base-columns") == 0)
4682             {
4683               if (image != (Image *) NULL)
4684                 s=newSViv((ssize_t) image->magick_columns);
4685               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4686               continue;
4687             }
4688           if (LocaleCompare(attribute,"base-filename") == 0)
4689             {
4690               if (image != (Image *) NULL)
4691                 s=newSVpv(image->magick_filename,0);
4692               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4693               continue;
4694             }
4695           if (LocaleCompare(attribute,"base-height") == 0)
4696             {
4697               if (image != (Image *) NULL)
4698                 s=newSViv((ssize_t) image->magick_rows);
4699               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4700               continue;
4701             }
4702           if (LocaleCompare(attribute,"base-rows") == 0)
4703             {
4704               if (image != (Image *) NULL)
4705                 s=newSViv((ssize_t) image->magick_rows);
4706               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4707               continue;
4708             }
4709           if (LocaleCompare(attribute,"base-width") == 0)
4710             {
4711               if (image != (Image *) NULL)
4712                 s=newSViv((ssize_t) image->magick_columns);
4713               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4714               continue;
4715             }
4716           if (LocaleCompare(attribute,"blue-primary") == 0)
4717             {
4718               if (image == (Image *) NULL)
4719                 break;
4720               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4721                 image->chromaticity.blue_primary.x,
4722                 image->chromaticity.blue_primary.y);
4723               s=newSVpv(color,0);
4724               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4725               continue;
4726             }
4727           if (LocaleCompare(attribute,"bordercolor") == 0)
4728             {
4729               if (image == (Image *) NULL)
4730                 break;
4731               (void) FormatLocaleString(color,MagickPathExtent,
4732                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4733                 (double) image->border_color.green,
4734                 (double) image->border_color.blue,
4735                 (double) image->border_color.alpha);
4736               s=newSVpv(color,0);
4737               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4738               continue;
4739             }
4740           if (LocaleCompare(attribute,"bounding-box") == 0)
4741             {
4742               char
4743                 geometry[MagickPathExtent];
4744
4745               RectangleInfo
4746                 page;
4747
4748               if (image == (Image *) NULL)
4749                 break;
4750               page=GetImageBoundingBox(image,exception);
4751               (void) FormatLocaleString(geometry,MagickPathExtent,
4752                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4753                 page.height,(double) page.x,(double) page.y);
4754               s=newSVpv(geometry,0);
4755               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4756               continue;
4757             }
4758           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4759             attribute);
4760           break;
4761         }
4762         case 'C':
4763         case 'c':
4764         {
4765           if (LocaleCompare(attribute,"class") == 0)
4766             {
4767               if (image == (Image *) NULL)
4768                 break;
4769               s=newSViv(image->storage_class);
4770               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4771                 image->storage_class));
4772               SvIOK_on(s);
4773               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4774               continue;
4775             }
4776           if (LocaleCompare(attribute,"clip-mask") == 0)
4777             {
4778               if (image != (Image *) NULL)
4779                 {
4780                   Image
4781                     *mask_image;
4782
4783                   SV
4784                     *sv;
4785
4786                   sv=NULL;
4787                   if (image->read_mask == MagickFalse)
4788                     ClipImage(image,exception);
4789                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4790                   if (mask_image != (Image *) NULL)
4791                     {
4792                       AddImageToRegistry(sv,mask_image);
4793                       s=sv_bless(newRV(sv),SvSTASH(reference));
4794                     }
4795                 }
4796               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4797               continue;
4798             }
4799           if (LocaleCompare(attribute,"clip-path") == 0)
4800             {
4801               if (image != (Image *) NULL)
4802                 {
4803                   Image
4804                     *mask_image;
4805
4806                   SV
4807                     *sv;
4808
4809                   sv=NULL;
4810                   if (image->read_mask != MagickFalse)
4811                     ClipImage(image,exception);
4812                   mask_image=GetImageMask(image,ReadPixelMask,exception);
4813                   if (mask_image != (Image *) NULL)
4814                     {
4815                       AddImageToRegistry(sv,mask_image);
4816                       s=sv_bless(newRV(sv),SvSTASH(reference));
4817                     }
4818                 }
4819               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4820               continue;
4821             }
4822           if (LocaleCompare(attribute,"compression") == 0)
4823             {
4824               j=info ? info->image_info->compression : image ?
4825                 image->compression : UndefinedCompression;
4826               if (info)
4827                 if (info->image_info->compression == UndefinedCompression)
4828                   j=image->compression;
4829               s=newSViv(j);
4830               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4831                 j));
4832               SvIOK_on(s);
4833               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4834               continue;
4835             }
4836           if (LocaleCompare(attribute,"colorspace") == 0)
4837             {
4838               j=image ? image->colorspace : RGBColorspace;
4839               s=newSViv(j);
4840               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4841                 j));
4842               SvIOK_on(s);
4843               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4844               continue;
4845             }
4846           if (LocaleCompare(attribute,"colors") == 0)
4847             {
4848               if (image != (Image *) NULL)
4849                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4850                   exception));
4851               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4852               continue;
4853             }
4854           if (LocaleNCompare(attribute,"colormap",8) == 0)
4855             {
4856               int
4857                 items;
4858
4859               if (image == (Image *) NULL || !image->colormap)
4860                 break;
4861               j=0;
4862               items=sscanf(attribute,"%*[^[][%ld",&j);
4863               (void) items;
4864               if (j > (ssize_t) image->colors)
4865                 j%=image->colors;
4866               (void) FormatLocaleString(color,MagickPathExtent,
4867                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4868                 (double) image->colormap[j].green,
4869                 (double) image->colormap[j].blue,
4870                 (double) image->colormap[j].alpha);
4871               s=newSVpv(color,0);
4872               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4873               continue;
4874             }
4875           if (LocaleCompare(attribute,"columns") == 0)
4876             {
4877               if (image != (Image *) NULL)
4878                 s=newSViv((ssize_t) image->columns);
4879               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4880               continue;
4881             }
4882           if (LocaleCompare(attribute,"comment") == 0)
4883             {
4884               const char
4885                 *value;
4886
4887               value=GetImageProperty(image,attribute,exception);
4888               if (value != (const char *) NULL)
4889                 s=newSVpv(value,0);
4890               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4891               continue;
4892             }
4893           if (LocaleCompare(attribute,"copyright") == 0)
4894             {
4895               s=newSVpv(GetMagickCopyright(),0);
4896               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4897               continue;
4898             }
4899           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4900             attribute);
4901           break;
4902         }
4903         case 'D':
4904         case 'd':
4905         {
4906           if (LocaleCompare(attribute,"density") == 0)
4907             {
4908               char
4909                 geometry[MagickPathExtent];
4910
4911               if (image == (Image *) NULL)
4912                 break;
4913               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4914                 image->resolution.x,image->resolution.y);
4915               s=newSVpv(geometry,0);
4916               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4917               continue;
4918             }
4919           if (LocaleCompare(attribute,"delay") == 0)
4920             {
4921               if (image != (Image *) NULL)
4922                 s=newSViv((ssize_t) image->delay);
4923               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4924               continue;
4925             }
4926           if (LocaleCompare(attribute,"depth") == 0)
4927             {
4928               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4929               if (image != (Image *) NULL)
4930                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           if (LocaleCompare(attribute,"directory") == 0)
4935             {
4936               if (image && image->directory)
4937                 s=newSVpv(image->directory,0);
4938               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4939               continue;
4940             }
4941           if (LocaleCompare(attribute,"dispose") == 0)
4942             {
4943               if (image == (Image *) NULL)
4944                 break;
4945
4946               s=newSViv(image->dispose);
4947               (void) sv_setpv(s,
4948                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4949               SvIOK_on(s);
4950               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4951               continue;
4952             }
4953           if (LocaleCompare(attribute,"disk") == 0)
4954             {
4955               s=newSViv(GetMagickResource(DiskResource));
4956               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4957               continue;
4958             }
4959           if (LocaleCompare(attribute,"dither") == 0)
4960             {
4961               if (info)
4962                 s=newSViv((ssize_t) info->image_info->dither);
4963               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4964               continue;
4965             }
4966           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4967             {
4968               if (info && info->image_info->server_name)
4969                 s=newSVpv(info->image_info->server_name,0);
4970               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4971               continue;
4972             }
4973           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4974             attribute);
4975           break;
4976         }
4977         case 'E':
4978         case 'e':
4979         {
4980           if (LocaleCompare(attribute,"elapsed-time") == 0)
4981             {
4982               if (image != (Image *) NULL)
4983                 s=newSVnv(GetElapsedTime(&image->timer));
4984               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4985               continue;
4986             }
4987           if (LocaleCompare(attribute,"endian") == 0)
4988             {
4989               j=info ? info->image_info->endian : image ? image->endian :
4990                 UndefinedEndian;
4991               s=newSViv(j);
4992               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4993               SvIOK_on(s);
4994               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4995               continue;
4996             }
4997           if (LocaleCompare(attribute,"error") == 0)
4998             {
4999               if (image != (Image *) NULL)
5000                 s=newSVnv(image->error.mean_error_per_pixel);
5001               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002               continue;
5003             }
5004           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5005             attribute);
5006           break;
5007         }
5008         case 'F':
5009         case 'f':
5010         {
5011           if (LocaleCompare(attribute,"filesize") == 0)
5012             {
5013               if (image != (Image *) NULL)
5014                 s=newSViv((ssize_t) GetBlobSize(image));
5015               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5016               continue;
5017             }
5018           if (LocaleCompare(attribute,"filename") == 0)
5019             {
5020               if (info && info->image_info->filename &&
5021                   *info->image_info->filename)
5022                 s=newSVpv(info->image_info->filename,0);
5023               if (image != (Image *) NULL)
5024                 s=newSVpv(image->filename,0);
5025               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5026               continue;
5027             }
5028           if (LocaleCompare(attribute,"filter") == 0)
5029             {
5030               s=image ? newSViv(image->filter) : newSViv(0);
5031               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5032                 image->filter));
5033               SvIOK_on(s);
5034               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5035               continue;
5036             }
5037           if (LocaleCompare(attribute,"font") == 0)
5038             {
5039               if (info && info->image_info->font)
5040                 s=newSVpv(info->image_info->font,0);
5041               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5042               continue;
5043             }
5044           if (LocaleCompare(attribute,"foreground") == 0)
5045             continue;
5046           if (LocaleCompare(attribute,"format") == 0)
5047             {
5048               const MagickInfo
5049                 *magick_info;
5050
5051               magick_info=(const MagickInfo *) NULL;
5052               if (info && (*info->image_info->magick != '\0'))
5053                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5054               if (image != (Image *) NULL)
5055                 magick_info=GetMagickInfo(image->magick,exception);
5056               if ((magick_info != (const MagickInfo *) NULL) &&
5057                   (*magick_info->description != '\0'))
5058                 s=newSVpv((char *) magick_info->description,0);
5059               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5060               continue;
5061             }
5062           if (LocaleCompare(attribute,"fuzz") == 0)
5063             {
5064               if (info)
5065                 s=newSVnv(info->image_info->fuzz);
5066               if (image != (Image *) NULL)
5067                 s=newSVnv(image->fuzz);
5068               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5069               continue;
5070             }
5071           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5072             attribute);
5073           break;
5074         }
5075         case 'G':
5076         case 'g':
5077         {
5078           if (LocaleCompare(attribute,"gamma") == 0)
5079             {
5080               if (image != (Image *) NULL)
5081                 s=newSVnv(image->gamma);
5082               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5083               continue;
5084             }
5085           if (LocaleCompare(attribute,"geometry") == 0)
5086             {
5087               if (image && image->geometry)
5088                 s=newSVpv(image->geometry,0);
5089               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5090               continue;
5091             }
5092           if (LocaleCompare(attribute,"gravity") == 0)
5093             {
5094               s=image ? newSViv(image->gravity) : newSViv(0);
5095               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5096                 image->gravity));
5097               SvIOK_on(s);
5098               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5099               continue;
5100             }
5101           if (LocaleCompare(attribute,"green-primary") == 0)
5102             {
5103               if (image == (Image *) NULL)
5104                 break;
5105               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5106                 image->chromaticity.green_primary.x,
5107                 image->chromaticity.green_primary.y);
5108               s=newSVpv(color,0);
5109               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5110               continue;
5111             }
5112           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5113             attribute);
5114           break;
5115         }
5116         case 'H':
5117         case 'h':
5118         {
5119           if (LocaleCompare(attribute,"height") == 0)
5120             {
5121               if (image != (Image *) NULL)
5122                 s=newSViv((ssize_t) image->rows);
5123               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5124               continue;
5125             }
5126           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5127             attribute);
5128           break;
5129         }
5130         case 'I':
5131         case 'i':
5132         {
5133           if (LocaleCompare(attribute,"icc") == 0)
5134             {
5135               if (image != (Image *) NULL)
5136                 {
5137                   const StringInfo
5138                     *profile;
5139
5140                   profile=GetImageProfile(image,"icc");
5141                   if (profile != (StringInfo *) NULL)
5142                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5143                       GetStringInfoLength(profile));
5144                 }
5145               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5146               continue;
5147             }
5148           if (LocaleCompare(attribute,"icm") == 0)
5149             {
5150               if (image != (Image *) NULL)
5151                 {
5152                   const StringInfo
5153                     *profile;
5154
5155                   profile=GetImageProfile(image,"icm");
5156                   if (profile != (const StringInfo *) NULL)
5157                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5158                       GetStringInfoLength(profile));
5159                 }
5160               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5161               continue;
5162             }
5163           if (LocaleCompare(attribute,"id") == 0)
5164             {
5165               if (image != (Image *) NULL)
5166                 {
5167                   char
5168                     key[MagickPathExtent];
5169
5170                   MagickBooleanType
5171                     status;
5172
5173                   static ssize_t
5174                     id = 0;
5175
5176                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5177                     id);
5178                   status=SetImageRegistry(ImageRegistryType,key,image,
5179                     exception);
5180                   (void) status;
5181                   s=newSViv(id++);
5182                 }
5183               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5184               continue;
5185             }
5186           if (LocaleNCompare(attribute,"index",5) == 0)
5187             {
5188               char
5189                 name[MagickPathExtent];
5190
5191               int
5192                 items;
5193
5194               long
5195                 x,
5196                 y;
5197
5198               register const Quantum
5199                 *p;
5200
5201               CacheView
5202                 *image_view;
5203
5204               if (image == (Image *) NULL)
5205                 break;
5206               if (image->storage_class != PseudoClass)
5207                 break;
5208               x=0;
5209               y=0;
5210               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5211               (void) items;
5212               image_view=AcquireVirtualCacheView(image,exception);
5213               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5214               if (p != (const Quantum *) NULL)
5215                 {
5216                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5217                     GetPixelIndex(image,p));
5218                   s=newSVpv(name,0);
5219                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220                 }
5221               image_view=DestroyCacheView(image_view);
5222               continue;
5223             }
5224           if (LocaleCompare(attribute,"iptc") == 0)
5225             {
5226               if (image != (Image *) NULL)
5227                 {
5228                   const StringInfo
5229                     *profile;
5230
5231                   profile=GetImageProfile(image,"iptc");
5232                   if (profile != (const StringInfo *) NULL)
5233                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5234                       GetStringInfoLength(profile));
5235                 }
5236               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5237               continue;
5238             }
5239           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5240             {
5241               if (image != (Image *) NULL)
5242                 s=newSViv((ssize_t) image->iterations);
5243               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5244               continue;
5245             }
5246           if (LocaleCompare(attribute,"interlace") == 0)
5247             {
5248               j=info ? info->image_info->interlace : image ? image->interlace :
5249                 UndefinedInterlace;
5250               s=newSViv(j);
5251               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5252                 j));
5253               SvIOK_on(s);
5254               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5255               continue;
5256             }
5257           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5258             attribute);
5259           break;
5260         }
5261         case 'L':
5262         case 'l':
5263         {
5264           if (LocaleCompare(attribute,"label") == 0)
5265             {
5266               const char
5267                 *value;
5268
5269               if (image == (Image *) NULL)
5270                 break;
5271               value=GetImageProperty(image,"Label",exception);
5272               if (value != (const char *) NULL)
5273                 s=newSVpv(value,0);
5274               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5275               continue;
5276             }
5277           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5278             {
5279               if (image != (Image *) NULL)
5280                 s=newSViv((ssize_t) image->iterations);
5281               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5282               continue;
5283             }
5284           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5285             attribute);
5286           break;
5287         }
5288         case 'M':
5289         case 'm':
5290         {
5291           if (LocaleCompare(attribute,"magick") == 0)
5292             {
5293               if (info && *info->image_info->magick)
5294                 s=newSVpv(info->image_info->magick,0);
5295               if (image != (Image *) NULL)
5296                 s=newSVpv(image->magick,0);
5297               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5298               continue;
5299             }
5300           if (LocaleCompare(attribute,"map") == 0)
5301             {
5302               s=newSViv(GetMagickResource(MapResource));
5303               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5304               continue;
5305             }
5306           if (LocaleCompare(attribute,"maximum-error") == 0)
5307             {
5308               if (image != (Image *) NULL)
5309                 s=newSVnv(image->error.normalized_maximum_error);
5310               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5311               continue;
5312             }
5313           if (LocaleCompare(attribute,"memory") == 0)
5314             {
5315               s=newSViv(GetMagickResource(MemoryResource));
5316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5317               continue;
5318             }
5319           if (LocaleCompare(attribute,"mean-error") == 0)
5320             {
5321               if (image != (Image *) NULL)
5322                 s=newSVnv(image->error.normalized_mean_error);
5323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5324               continue;
5325             }
5326           if (LocaleCompare(attribute,"mime") == 0)
5327             {
5328               if (info && *info->image_info->magick)
5329                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5330               if (image != (Image *) NULL)
5331                 s=newSVpv(MagickToMime(image->magick),0);
5332               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5333               continue;
5334             }
5335           if (LocaleCompare(attribute,"mattecolor") == 0)
5336             {
5337               if (image == (Image *) NULL)
5338                 break;
5339               (void) FormatLocaleString(color,MagickPathExtent,
5340                 "%.20g,%.20g,%.20g,%.20g",(double) image->alpha_color.red,
5341                 (double) image->alpha_color.green,
5342                 (double) image->alpha_color.blue,
5343                 (double) image->alpha_color.alpha);
5344               s=newSVpv(color,0);
5345               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5346               continue;
5347             }
5348           if (LocaleCompare(attribute,"matte") == 0)
5349             {
5350               if (image != (Image *) NULL)
5351                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5352                   1 : 0);
5353               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5354               continue;
5355             }
5356           if (LocaleCompare(attribute,"mime") == 0)
5357             {
5358               const char
5359                 *magick;
5360
5361               magick=NULL;
5362               if (info && *info->image_info->magick)
5363                 magick=info->image_info->magick;
5364               if (image != (Image *) NULL)
5365                 magick=image->magick;
5366               if (magick)
5367                 {
5368                   char
5369                     *mime;
5370
5371                   mime=MagickToMime(magick);
5372                   s=newSVpv(mime,0);
5373                   mime=(char *) RelinquishMagickMemory(mime);
5374                 }
5375               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5376               continue;
5377             }
5378           if (LocaleCompare(attribute,"monochrome") == 0)
5379             {
5380               if (image == (Image *) NULL)
5381                 continue;
5382               j=info ? info->image_info->monochrome :
5383                 SetImageMonochrome(image,exception);
5384               s=newSViv(j);
5385               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5386               continue;
5387             }
5388           if (LocaleCompare(attribute,"montage") == 0)
5389             {
5390               if (image && image->montage)
5391                 s=newSVpv(image->montage,0);
5392               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5393               continue;
5394             }
5395           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5396             attribute);
5397           break;
5398         }
5399         case 'O':
5400         case 'o':
5401         {
5402           if (LocaleCompare(attribute,"orientation") == 0)
5403             {
5404               j=info ? info->image_info->orientation : image ?
5405                 image->orientation : UndefinedOrientation;
5406               s=newSViv(j);
5407               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5408                 j));
5409               SvIOK_on(s);
5410               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5411               continue;
5412             }
5413           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5414             attribute);
5415           break;
5416         }
5417         case 'P':
5418         case 'p':
5419         {
5420           if (LocaleCompare(attribute,"page") == 0)
5421             {
5422               if (info && info->image_info->page)
5423                 s=newSVpv(info->image_info->page,0);
5424               if (image != (Image *) NULL)
5425                 {
5426                   char
5427                     geometry[MagickPathExtent];
5428
5429                   (void) FormatLocaleString(geometry,MagickPathExtent,
5430                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5431                     (double) image->page.height,(double) image->page.x,(double)
5432                     image->page.y);
5433                   s=newSVpv(geometry,0);
5434                 }
5435               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5436               continue;
5437             }
5438           if (LocaleCompare(attribute,"page.x") == 0)
5439             {
5440               if (image != (Image *) NULL)
5441                 s=newSViv((ssize_t) image->page.x);
5442               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5443               continue;
5444             }
5445           if (LocaleCompare(attribute,"page.y") == 0)
5446             {
5447               if (image != (Image *) NULL)
5448                 s=newSViv((ssize_t) image->page.y);
5449               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5450               continue;
5451             }
5452           if (LocaleNCompare(attribute,"pixel",5) == 0)
5453             {
5454               char
5455                 tuple[MagickPathExtent];
5456
5457               int
5458                 items;
5459
5460               long
5461                 x,
5462                 y;
5463
5464               register const Quantum
5465                 *p;
5466
5467               if (image == (Image *) NULL)
5468                 break;
5469               x=0;
5470               y=0;
5471               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5472               (void) items;
5473               p=GetVirtualPixels(image,x,y,1,1,exception);
5474               if (image->colorspace != CMYKColorspace)
5475                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5476                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5477                   GetPixelRed(image,p),GetPixelGreen(image,p),
5478                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5479               else
5480                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5481                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5482                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5483                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5484                   GetPixelAlpha(image,p));
5485               s=newSVpv(tuple,0);
5486               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5487               continue;
5488             }
5489           if (LocaleCompare(attribute,"pointsize") == 0)
5490             {
5491               if (info)
5492                 s=newSViv((ssize_t) info->image_info->pointsize);
5493               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5494               continue;
5495             }
5496           if (LocaleCompare(attribute,"preview") == 0)
5497             {
5498               s=newSViv(info->image_info->preview_type);
5499               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5500                 info->image_info->preview_type));
5501               SvIOK_on(s);
5502               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5503               continue;
5504             }
5505           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5506             attribute);
5507           break;
5508         }
5509         case 'Q':
5510         case 'q':
5511         {
5512           if (LocaleCompare(attribute,"quality") == 0)
5513             {
5514               if (info)
5515                 s=newSViv((ssize_t) info->image_info->quality);
5516               if (image != (Image *) NULL)
5517                 s=newSViv((ssize_t) image->quality);
5518               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5519               continue;
5520             }
5521           if (LocaleCompare(attribute,"quantum") == 0)
5522             {
5523               if (info)
5524                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5525               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5526               continue;
5527             }
5528           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5529             attribute);
5530           break;
5531         }
5532         case 'R':
5533         case 'r':
5534         {
5535           if (LocaleCompare(attribute,"rendering-intent") == 0)
5536             {
5537               s=newSViv(image->rendering_intent);
5538               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5539                 image->rendering_intent));
5540               SvIOK_on(s);
5541               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5542               continue;
5543             }
5544           if (LocaleCompare(attribute,"red-primary") == 0)
5545             {
5546               if (image == (Image *) NULL)
5547                 break;
5548               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5549                 image->chromaticity.red_primary.x,
5550                 image->chromaticity.red_primary.y);
5551               s=newSVpv(color,0);
5552               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5553               continue;
5554             }
5555           if (LocaleCompare(attribute,"rows") == 0)
5556             {
5557               if (image != (Image *) NULL)
5558                 s=newSViv((ssize_t) image->rows);
5559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5560               continue;
5561             }
5562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5563             attribute);
5564           break;
5565         }
5566         case 'S':
5567         case 's':
5568         {
5569           if (LocaleCompare(attribute,"sampling-factor") == 0)
5570             {
5571               if (info && info->image_info->sampling_factor)
5572                 s=newSVpv(info->image_info->sampling_factor,0);
5573               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5574               continue;
5575             }
5576           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5577             {
5578               if (info && info->image_info->server_name)
5579                 s=newSVpv(info->image_info->server_name,0);
5580               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5581               continue;
5582             }
5583           if (LocaleCompare(attribute,"size") == 0)
5584             {
5585               if (info && info->image_info->size)
5586                 s=newSVpv(info->image_info->size,0);
5587               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5588               continue;
5589             }
5590           if (LocaleCompare(attribute,"scene") == 0)
5591             {
5592               if (image != (Image *) NULL)
5593                 s=newSViv((ssize_t) image->scene);
5594               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5595               continue;
5596             }
5597           if (LocaleCompare(attribute,"scenes") == 0)
5598             {
5599               if (image != (Image *) NULL)
5600                 s=newSViv((ssize_t) info->image_info->number_scenes);
5601               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5602               continue;
5603             }
5604           if (LocaleCompare(attribute,"signature") == 0)
5605             {
5606               const char
5607                 *value;
5608
5609               if (image == (Image *) NULL)
5610                 break;
5611               (void) SignatureImage(image,exception);
5612               value=GetImageProperty(image,"Signature",exception);
5613               if (value != (const char *) NULL)
5614                 s=newSVpv(value,0);
5615               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5616               continue;
5617             }
5618           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5619             attribute);
5620           break;
5621         }
5622         case 'T':
5623         case 't':
5624         {
5625           if (LocaleCompare(attribute,"taint") == 0)
5626             {
5627               if (image != (Image *) NULL)
5628                 s=newSViv((ssize_t) IsTaintImage(image));
5629               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5630               continue;
5631             }
5632           if (LocaleCompare(attribute,"texture") == 0)
5633             {
5634               if (info && info->image_info->texture)
5635                 s=newSVpv(info->image_info->texture,0);
5636               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5637               continue;
5638             }
5639           if (LocaleCompare(attribute,"total-ink-density") == 0)
5640             {
5641               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5642               if (image != (Image *) NULL)
5643                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5644               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5645               continue;
5646             }
5647           if (LocaleCompare(attribute,"transparent-color") == 0)
5648             {
5649               if (image == (Image *) NULL)
5650                 break;
5651               (void) FormatLocaleString(color,MagickPathExtent,
5652                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5653                 (double) image->transparent_color.green,
5654                 (double) image->transparent_color.blue,
5655                 (double) image->transparent_color.alpha);
5656               s=newSVpv(color,0);
5657               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5658               continue;
5659             }
5660           if (LocaleCompare(attribute,"type") == 0)
5661             {
5662               if (image == (Image *) NULL)
5663                 break;
5664               j=(ssize_t) GetImageType(image);
5665               s=newSViv(j);
5666               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5667               SvIOK_on(s);
5668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5669               continue;
5670             }
5671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5672             attribute);
5673           break;
5674         }
5675         case 'U':
5676         case 'u':
5677         {
5678           if (LocaleCompare(attribute,"units") == 0)
5679             {
5680               j=info ? info->image_info->units : image ? image->units :
5681                 UndefinedResolution;
5682               if (info && (info->image_info->units == UndefinedResolution))
5683                 if (image)
5684                   j=image->units;
5685               if (j == UndefinedResolution)
5686                 s=newSVpv("undefined units",0);
5687               else
5688                 if (j == PixelsPerInchResolution)
5689                   s=newSVpv("pixels / inch",0);
5690                 else
5691                   s=newSVpv("pixels / centimeter",0);
5692               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5693               continue;
5694             }
5695           if (LocaleCompare(attribute,"user-time") == 0)
5696             {
5697               if (image != (Image *) NULL)
5698                 s=newSVnv(GetUserTime(&image->timer));
5699               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5700               continue;
5701             }
5702           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5703             attribute);
5704           break;
5705         }
5706         case 'V':
5707         case 'v':
5708         {
5709           if (LocaleCompare(attribute,"verbose") == 0)
5710             {
5711               if (info)
5712                 s=newSViv((ssize_t) info->image_info->verbose);
5713               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5714               continue;
5715             }
5716           if (LocaleCompare(attribute,"version") == 0)
5717             {
5718               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5719               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5720               continue;
5721             }
5722           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5723             {
5724               if (image == (Image *) NULL)
5725                 break;
5726               j=(ssize_t) GetImageVirtualPixelMethod(image);
5727               s=newSViv(j);
5728               (void) sv_setpv(s,CommandOptionToMnemonic(
5729                 MagickVirtualPixelOptions,j));
5730               SvIOK_on(s);
5731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5732               continue;
5733             }
5734           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5735             attribute);
5736           break;
5737         }
5738         case 'W':
5739         case 'w':
5740         {
5741           if (LocaleCompare(attribute,"white-point") == 0)
5742             {
5743               if (image == (Image *) NULL)
5744                 break;
5745               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5746                 image->chromaticity.white_point.x,
5747                 image->chromaticity.white_point.y);
5748               s=newSVpv(color,0);
5749               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5750               continue;
5751             }
5752           if (LocaleCompare(attribute,"width") == 0)
5753             {
5754               if (image != (Image *) NULL)
5755                 s=newSViv((ssize_t) image->columns);
5756               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5757               continue;
5758             }
5759           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5760              attribute);
5761           break;
5762         }
5763         case 'X':
5764         case 'x':
5765         {
5766           if (LocaleCompare(attribute,"xmp") == 0)
5767             {
5768               if (image != (Image *) NULL)
5769                 {
5770                   const StringInfo
5771                     *profile;
5772
5773                   profile=GetImageProfile(image,"xmp");
5774                   if (profile != (StringInfo *) NULL)
5775                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5776                       GetStringInfoLength(profile));
5777                 }
5778               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5779               continue;
5780             }
5781           if (LocaleCompare(attribute,"x-resolution") == 0)
5782             {
5783               if (image != (Image *) NULL)
5784                 s=newSVnv(image->resolution.x);
5785               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5786               continue;
5787             }
5788           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5789             attribute);
5790           break;
5791         }
5792         case 'Y':
5793         case 'y':
5794         {
5795           if (LocaleCompare(attribute,"y-resolution") == 0)
5796             {
5797               if (image != (Image *) NULL)
5798                 s=newSVnv(image->resolution.y);
5799               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5800               continue;
5801             }
5802           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5803             attribute);
5804           break;
5805         }
5806         default:
5807           break;
5808       }
5809       if (image == (Image *) NULL)
5810         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5811           attribute)
5812       else
5813         {
5814           value=GetImageProperty(image,attribute,exception);
5815           if (value != (const char *) NULL)
5816             {
5817               s=newSVpv(value,0);
5818               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5819             }
5820           else
5821             if (*attribute != '%')
5822               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5823                 attribute)
5824             else
5825               {
5826                  char
5827                    *meta;
5828
5829                  meta=InterpretImageProperties(info ? info->image_info :
5830                    (ImageInfo *) NULL,image,attribute,exception);
5831                  s=newSVpv(meta,0);
5832                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5833                  meta=(char *) RelinquishMagickMemory(meta);
5834               }
5835         }
5836     }
5837     exception=DestroyExceptionInfo(exception);
5838     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5839   }
5840 \f
5841 #
5842 ###############################################################################
5843 #                                                                             #
5844 #                                                                             #
5845 #                                                                             #
5846 #   G e t A u t h e n t i c P i x e l s                                       #
5847 #                                                                             #
5848 #                                                                             #
5849 #                                                                             #
5850 ###############################################################################
5851 #
5852 #
5853 void *
5854 GetAuthenticPixels(ref,...)
5855   Image::Magick ref = NO_INIT
5856   ALIAS:
5857     getauthenticpixels = 1
5858     GetImagePixels = 2
5859     getimagepixels = 3
5860   CODE:
5861   {
5862     char
5863       *attribute;
5864
5865     ExceptionInfo
5866       *exception;
5867
5868     Image
5869       *image;
5870
5871     RectangleInfo
5872       region;
5873
5874     ssize_t
5875       i;
5876
5877     struct PackageInfo
5878       *info;
5879
5880     SV
5881       *perl_exception,
5882       *reference;
5883
5884     void
5885       *blob = NULL;
5886
5887     PERL_UNUSED_VAR(ref);
5888     PERL_UNUSED_VAR(ix);
5889     exception=AcquireExceptionInfo();
5890     perl_exception=newSVpv("",0);
5891     if (sv_isobject(ST(0)) == 0)
5892       {
5893         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5894           PackageName);
5895         goto PerlException;
5896       }
5897     reference=SvRV(ST(0));
5898
5899     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5900     if (image == (Image *) NULL)
5901       {
5902         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5903           PackageName);
5904         goto PerlException;
5905       }
5906
5907     region.x=0;
5908     region.y=0;
5909     region.width=image->columns;
5910     region.height=1;
5911     if (items == 1)
5912       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5913     for (i=2; i < items; i+=2)
5914     {
5915       attribute=(char *) SvPV(ST(i-1),na);
5916       switch (*attribute)
5917       {
5918         case 'g':
5919         case 'G':
5920         {
5921           if (LocaleCompare(attribute,"geometry") == 0)
5922             {
5923               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5924               break;
5925             }
5926           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5927             attribute);
5928           break;
5929         }
5930         case 'H':
5931         case 'h':
5932         {
5933           if (LocaleCompare(attribute,"height") == 0)
5934             {
5935               region.height=SvIV(ST(i));
5936               continue;
5937             }
5938           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5939             attribute);
5940           break;
5941         }
5942         case 'X':
5943         case 'x':
5944         {
5945           if (LocaleCompare(attribute,"x") == 0)
5946             {
5947               region.x=SvIV(ST(i));
5948               continue;
5949             }
5950           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5951             attribute);
5952           break;
5953         }
5954         case 'Y':
5955         case 'y':
5956         {
5957           if (LocaleCompare(attribute,"y") == 0)
5958             {
5959               region.y=SvIV(ST(i));
5960               continue;
5961             }
5962           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5963             attribute);
5964           break;
5965         }
5966         case 'W':
5967         case 'w':
5968         {
5969           if (LocaleCompare(attribute,"width") == 0)
5970             {
5971               region.width=SvIV(ST(i));
5972               continue;
5973             }
5974           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5975             attribute);
5976           break;
5977         }
5978       }
5979     }
5980     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5981       region.height,exception);
5982     if (blob != (void *) NULL)
5983       goto PerlEnd;
5984
5985   PerlException:
5986     InheritPerlException(exception,perl_exception);
5987     exception=DestroyExceptionInfo(exception);
5988     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5989
5990   PerlEnd:
5991     RETVAL = blob;
5992   }
5993   OUTPUT:
5994     RETVAL
5995 \f
5996 #
5997 ###############################################################################
5998 #                                                                             #
5999 #                                                                             #
6000 #                                                                             #
6001 #   G e t V i r t u a l P i x e l s                                           #
6002 #                                                                             #
6003 #                                                                             #
6004 #                                                                             #
6005 ###############################################################################
6006 #
6007 #
6008 void *
6009 GetVirtualPixels(ref,...)
6010   Image::Magick ref = NO_INIT
6011   ALIAS:
6012     getvirtualpixels = 1
6013     AcquireImagePixels = 2
6014     acquireimagepixels = 3
6015   CODE:
6016   {
6017     char
6018       *attribute;
6019
6020     const void
6021       *blob = NULL;
6022
6023     ExceptionInfo
6024       *exception;
6025
6026     Image
6027       *image;
6028
6029     RectangleInfo
6030       region;
6031
6032     ssize_t
6033       i;
6034
6035     struct PackageInfo
6036       *info;
6037
6038     SV
6039       *perl_exception,
6040       *reference;
6041
6042     PERL_UNUSED_VAR(ref);
6043     PERL_UNUSED_VAR(ix);
6044     exception=AcquireExceptionInfo();
6045     perl_exception=newSVpv("",0);
6046     if (sv_isobject(ST(0)) == 0)
6047       {
6048         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6049           PackageName);
6050         goto PerlException;
6051       }
6052     reference=SvRV(ST(0));
6053
6054     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6055     if (image == (Image *) NULL)
6056       {
6057         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6058           PackageName);
6059         goto PerlException;
6060       }
6061
6062     region.x=0;
6063     region.y=0;
6064     region.width=image->columns;
6065     region.height=1;
6066     if (items == 1)
6067       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6068     for (i=2; i < items; i+=2)
6069     {
6070       attribute=(char *) SvPV(ST(i-1),na);
6071       switch (*attribute)
6072       {
6073         case 'g':
6074         case 'G':
6075         {
6076           if (LocaleCompare(attribute,"geometry") == 0)
6077             {
6078               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6079               break;
6080             }
6081           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6082             attribute);
6083           break;
6084         }
6085         case 'H':
6086         case 'h':
6087         {
6088           if (LocaleCompare(attribute,"height") == 0)
6089             {
6090               region.height=SvIV(ST(i));
6091               continue;
6092             }
6093           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6094             attribute);
6095           break;
6096         }
6097         case 'X':
6098         case 'x':
6099         {
6100           if (LocaleCompare(attribute,"x") == 0)
6101             {
6102               region.x=SvIV(ST(i));
6103               continue;
6104             }
6105           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6106             attribute);
6107           break;
6108         }
6109         case 'Y':
6110         case 'y':
6111         {
6112           if (LocaleCompare(attribute,"y") == 0)
6113             {
6114               region.y=SvIV(ST(i));
6115               continue;
6116             }
6117           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6118             attribute);
6119           break;
6120         }
6121         case 'W':
6122         case 'w':
6123         {
6124           if (LocaleCompare(attribute,"width") == 0)
6125             {
6126               region.width=SvIV(ST(i));
6127               continue;
6128             }
6129           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6130             attribute);
6131           break;
6132         }
6133       }
6134     }
6135     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6136       region.height,exception);
6137     if (blob != (void *) NULL)
6138       goto PerlEnd;
6139
6140   PerlException:
6141     InheritPerlException(exception,perl_exception);
6142     exception=DestroyExceptionInfo(exception);
6143     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6144
6145   PerlEnd:
6146     RETVAL = (void *) blob;
6147   }
6148   OUTPUT:
6149     RETVAL
6150 \f
6151 #
6152 ###############################################################################
6153 #                                                                             #
6154 #                                                                             #
6155 #                                                                             #
6156 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6157 #                                                                             #
6158 #                                                                             #
6159 #                                                                             #
6160 ###############################################################################
6161 #
6162 #
6163 void *
6164 GetAuthenticMetacontent(ref,...)
6165   Image::Magick ref = NO_INIT
6166   ALIAS:
6167     getauthenticmetacontent = 1
6168     GetMetacontent = 2
6169     getmetacontent = 3
6170   CODE:
6171   {
6172     ExceptionInfo
6173       *exception;
6174
6175     Image
6176       *image;
6177
6178     struct PackageInfo
6179       *info;
6180
6181     SV
6182       *perl_exception,
6183       *reference;
6184
6185     void
6186       *blob = NULL;
6187
6188     PERL_UNUSED_VAR(ref);
6189     PERL_UNUSED_VAR(ix);
6190     exception=AcquireExceptionInfo();
6191     perl_exception=newSVpv("",0);
6192     if (sv_isobject(ST(0)) == 0)
6193       {
6194         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6195           PackageName);
6196         goto PerlException;
6197       }
6198     reference=SvRV(ST(0));
6199
6200     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6201     if (image == (Image *) NULL)
6202       {
6203         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6204           PackageName);
6205         goto PerlException;
6206       }
6207
6208     blob=(void *) GetAuthenticMetacontent(image);
6209     if (blob != (void *) NULL)
6210       goto PerlEnd;
6211
6212   PerlException:
6213     InheritPerlException(exception,perl_exception);
6214     exception=DestroyExceptionInfo(exception);
6215     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6216
6217   PerlEnd:
6218     RETVAL = blob;
6219   }
6220   OUTPUT:
6221     RETVAL
6222 \f
6223 #
6224 ###############################################################################
6225 #                                                                             #
6226 #                                                                             #
6227 #                                                                             #
6228 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6229 #                                                                             #
6230 #                                                                             #
6231 #                                                                             #
6232 ###############################################################################
6233 #
6234 #
6235 void *
6236 GetVirtualMetacontent(ref,...)
6237   Image::Magick ref = NO_INIT
6238   ALIAS:
6239     getvirtualmetacontent = 1
6240   CODE:
6241   {
6242     ExceptionInfo
6243       *exception;
6244
6245     Image
6246       *image;
6247
6248     struct PackageInfo
6249       *info;
6250
6251     SV
6252       *perl_exception,
6253       *reference;
6254
6255     void
6256       *blob = NULL;
6257
6258     PERL_UNUSED_VAR(ref);
6259     PERL_UNUSED_VAR(ix);
6260     exception=AcquireExceptionInfo();
6261     perl_exception=newSVpv("",0);
6262     if (sv_isobject(ST(0)) == 0)
6263       {
6264         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6265           PackageName);
6266         goto PerlException;
6267       }
6268     reference=SvRV(ST(0));
6269
6270     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6271     if (image == (Image *) NULL)
6272       {
6273         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6274           PackageName);
6275         goto PerlException;
6276       }
6277
6278     blob=(void *) GetVirtualMetacontent(image);
6279     if (blob != (void *) NULL)
6280       goto PerlEnd;
6281
6282   PerlException:
6283     InheritPerlException(exception,perl_exception);
6284     exception=DestroyExceptionInfo(exception);
6285     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6286
6287   PerlEnd:
6288     RETVAL = blob;
6289   }
6290   OUTPUT:
6291     RETVAL
6292 \f
6293 #
6294 ###############################################################################
6295 #                                                                             #
6296 #                                                                             #
6297 #                                                                             #
6298 #   H i s t o g r a m                                                         #
6299 #                                                                             #
6300 #                                                                             #
6301 #                                                                             #
6302 ###############################################################################
6303 #
6304 #
6305 void
6306 Histogram(ref,...)
6307   Image::Magick ref=NO_INIT
6308   ALIAS:
6309     HistogramImage = 1
6310     histogram      = 2
6311     histogramimage = 3
6312   PPCODE:
6313   {
6314     AV
6315       *av;
6316
6317     char
6318       message[MagickPathExtent];
6319
6320     PixelInfo
6321       *histogram;
6322
6323     ExceptionInfo
6324       *exception;
6325
6326     Image
6327       *image;
6328
6329     register ssize_t
6330       i;
6331
6332     ssize_t
6333       count;
6334
6335     struct PackageInfo
6336       *info;
6337
6338     SV
6339       *perl_exception,
6340       *reference;
6341
6342     size_t
6343       number_colors;
6344
6345     PERL_UNUSED_VAR(ref);
6346     PERL_UNUSED_VAR(ix);
6347     exception=AcquireExceptionInfo();
6348     perl_exception=newSVpv("",0);
6349     av=NULL;
6350     if (sv_isobject(ST(0)) == 0)
6351       {
6352         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6353           PackageName);
6354         goto PerlException;
6355       }
6356     reference=SvRV(ST(0));
6357     av=newAV();
6358     SvREFCNT_dec(av);
6359     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6360     if (image == (Image *) NULL)
6361       {
6362         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6363           PackageName);
6364         goto PerlException;
6365       }
6366     count=0;
6367     for ( ; image; image=image->next)
6368     {
6369       histogram=GetImageHistogram(image,&number_colors,exception);
6370       if (histogram == (PixelInfo *) NULL)
6371         continue;
6372       count+=(ssize_t) number_colors;
6373       EXTEND(sp,6*count);
6374       for (i=0; i < (ssize_t) number_colors; i++)
6375       {
6376         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6377           histogram[i].red);
6378         PUSHs(sv_2mortal(newSVpv(message,0)));
6379         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6380           histogram[i].green);
6381         PUSHs(sv_2mortal(newSVpv(message,0)));
6382         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6383           histogram[i].blue);
6384         PUSHs(sv_2mortal(newSVpv(message,0)));
6385         if (image->colorspace == CMYKColorspace)
6386           {
6387             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6388               histogram[i].black);
6389             PUSHs(sv_2mortal(newSVpv(message,0)));
6390           }
6391         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6392           histogram[i].alpha);
6393         PUSHs(sv_2mortal(newSVpv(message,0)));
6394         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6395           histogram[i].count);
6396         PUSHs(sv_2mortal(newSVpv(message,0)));
6397       }
6398       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6399     }
6400
6401   PerlException:
6402     InheritPerlException(exception,perl_exception);
6403     exception=DestroyExceptionInfo(exception);
6404     SvREFCNT_dec(perl_exception);
6405   }
6406 \f
6407 #
6408 ###############################################################################
6409 #                                                                             #
6410 #                                                                             #
6411 #                                                                             #
6412 #   G e t P i x e l                                                           #
6413 #                                                                             #
6414 #                                                                             #
6415 #                                                                             #
6416 ###############################################################################
6417 #
6418 #
6419 void
6420 GetPixel(ref,...)
6421   Image::Magick ref=NO_INIT
6422   ALIAS:
6423     getpixel = 1
6424     getPixel = 2
6425   PPCODE:
6426   {
6427     AV
6428       *av;
6429
6430     char
6431       *attribute;
6432
6433     ExceptionInfo
6434       *exception;
6435
6436     Image
6437       *image;
6438
6439     MagickBooleanType
6440       normalize;
6441
6442     RectangleInfo
6443       region;
6444
6445     register const Quantum
6446       *p;
6447
6448     register ssize_t
6449       i;
6450
6451     ssize_t
6452       option;
6453
6454     struct PackageInfo
6455       *info;
6456
6457     SV
6458       *perl_exception,
6459       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6460
6461     PERL_UNUSED_VAR(ref);
6462     PERL_UNUSED_VAR(ix);
6463     exception=AcquireExceptionInfo();
6464     perl_exception=newSVpv("",0);
6465     reference=SvRV(ST(0));
6466     av=(AV *) reference;
6467     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6468       exception);
6469     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6470     if (image == (Image *) NULL)
6471       {
6472         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6473           PackageName);
6474         goto PerlException;
6475       }
6476     normalize=MagickTrue;
6477     region.x=0;
6478     region.y=0;
6479     region.width=image->columns;
6480     region.height=1;
6481     if (items == 1)
6482       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6483     for (i=2; i < items; i+=2)
6484     {
6485       attribute=(char *) SvPV(ST(i-1),na);
6486       switch (*attribute)
6487       {
6488         case 'C':
6489         case 'c':
6490         {
6491           if (LocaleCompare(attribute,"channel") == 0)
6492             {
6493               ssize_t
6494                 option;
6495
6496               option=ParseChannelOption(SvPV(ST(i),na));
6497               if (option < 0)
6498                 {
6499                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6500                     SvPV(ST(i),na));
6501                   return;
6502                 }
6503               (void) SetPixelChannelMask(image,(ChannelType) option);
6504               break;
6505             }
6506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6507             attribute);
6508           break;
6509         }
6510         case 'g':
6511         case 'G':
6512         {
6513           if (LocaleCompare(attribute,"geometry") == 0)
6514             {
6515               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6516               break;
6517             }
6518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6519             attribute);
6520           break;
6521         }
6522         case 'N':
6523         case 'n':
6524         {
6525           if (LocaleCompare(attribute,"normalize") == 0)
6526             {
6527               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6528                 SvPV(ST(i),na));
6529               if (option < 0)
6530                 {
6531                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6532                     SvPV(ST(i),na));
6533                   break;
6534                 }
6535              normalize=option != 0 ? MagickTrue : MagickFalse;
6536              break;
6537             }
6538           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6539             attribute);
6540           break;
6541         }
6542         case 'x':
6543         case 'X':
6544         {
6545           if (LocaleCompare(attribute,"x") == 0)
6546             {
6547               region.x=SvIV(ST(i));
6548               break;
6549             }
6550           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6551             attribute);
6552           break;
6553         }
6554         case 'y':
6555         case 'Y':
6556         {
6557           if (LocaleCompare(attribute,"y") == 0)
6558             {
6559               region.y=SvIV(ST(i));
6560               break;
6561             }
6562           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6563             attribute);
6564           break;
6565         }
6566         default:
6567         {
6568           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6569             attribute);
6570           break;
6571         }
6572       }
6573     }
6574     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6575     if (p == (const Quantum *) NULL)
6576       PUSHs(&sv_undef);
6577     else
6578       {
6579         double
6580           scale;
6581
6582         scale=1.0;
6583         if (normalize != MagickFalse)
6584           scale=1.0/QuantumRange;
6585         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6586           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6587         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6588           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6589         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6590           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6591         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6592             (image->colorspace == CMYKColorspace))
6593           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6594         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6595           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6596       }
6597
6598   PerlException:
6599     InheritPerlException(exception,perl_exception);
6600     exception=DestroyExceptionInfo(exception);
6601     SvREFCNT_dec(perl_exception);
6602   }
6603 \f
6604 #
6605 ###############################################################################
6606 #                                                                             #
6607 #                                                                             #
6608 #                                                                             #
6609 #   G e t P i x e l s                                                         #
6610 #                                                                             #
6611 #                                                                             #
6612 #                                                                             #
6613 ###############################################################################
6614 #
6615 #
6616 void
6617 GetPixels(ref,...)
6618   Image::Magick ref=NO_INIT
6619   ALIAS:
6620     getpixels = 1
6621     getPixels = 2
6622   PPCODE:
6623   {
6624     AV
6625       *av;
6626
6627     char
6628       *attribute;
6629
6630     const char
6631       *map;
6632
6633     ExceptionInfo
6634       *exception;
6635
6636     Image
6637       *image;
6638
6639     MagickBooleanType
6640       normalize,
6641       status;
6642
6643     RectangleInfo
6644       region;
6645
6646     register ssize_t
6647       i;
6648
6649     ssize_t
6650       option;
6651
6652     struct PackageInfo
6653       *info;
6654
6655     SV
6656       *perl_exception,
6657       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6658
6659     PERL_UNUSED_VAR(ref);
6660     PERL_UNUSED_VAR(ix);
6661     exception=AcquireExceptionInfo();
6662     perl_exception=newSVpv("",0);
6663     reference=SvRV(ST(0));
6664     av=(AV *) reference;
6665     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6666       exception);
6667     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6668     if (image == (Image *) NULL)
6669       {
6670         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6671           PackageName);
6672         goto PerlException;
6673       }
6674     map="RGB";
6675     if (image->alpha_trait != UndefinedPixelTrait)
6676       map="RGBA";
6677     if (image->colorspace == CMYKColorspace)
6678       {
6679         map="CMYK";
6680         if (image->alpha_trait != UndefinedPixelTrait)
6681           map="CMYKA";
6682       }
6683     normalize=MagickFalse;
6684     region.x=0;
6685     region.y=0;
6686     region.width=image->columns;
6687     region.height=1;
6688     if (items == 1)
6689       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6690     for (i=2; i < items; i+=2)
6691     {
6692       attribute=(char *) SvPV(ST(i-1),na);
6693       switch (*attribute)
6694       {
6695         case 'g':
6696         case 'G':
6697         {
6698           if (LocaleCompare(attribute,"geometry") == 0)
6699             {
6700               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6701               break;
6702             }
6703           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6704             attribute);
6705           break;
6706         }
6707         case 'H':
6708         case 'h':
6709         {
6710           if (LocaleCompare(attribute,"height") == 0)
6711             {
6712               region.height=SvIV(ST(i));
6713               break;
6714             }
6715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6716             attribute);
6717           break;
6718         }
6719         case 'M':
6720         case 'm':
6721         {
6722           if (LocaleCompare(attribute,"map") == 0)
6723             {
6724               map=SvPV(ST(i),na);
6725               break;
6726             }
6727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6728             attribute);
6729           break;
6730         }
6731         case 'N':
6732         case 'n':
6733         {
6734           if (LocaleCompare(attribute,"normalize") == 0)
6735             {
6736               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6737                 SvPV(ST(i),na));
6738               if (option < 0)
6739                 {
6740                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6741                     SvPV(ST(i),na));
6742                   break;
6743                 }
6744              normalize=option != 0 ? MagickTrue : MagickFalse;
6745              break;
6746             }
6747           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6748             attribute);
6749           break;
6750         }
6751         case 'W':
6752         case 'w':
6753         {
6754           if (LocaleCompare(attribute,"width") == 0)
6755             {
6756               region.width=SvIV(ST(i));
6757               break;
6758             }
6759           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6760             attribute);
6761           break;
6762         }
6763         case 'x':
6764         case 'X':
6765         {
6766           if (LocaleCompare(attribute,"x") == 0)
6767             {
6768               region.x=SvIV(ST(i));
6769               break;
6770             }
6771           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6772             attribute);
6773           break;
6774         }
6775         case 'y':
6776         case 'Y':
6777         {
6778           if (LocaleCompare(attribute,"y") == 0)
6779             {
6780               region.y=SvIV(ST(i));
6781               break;
6782             }
6783           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6784             attribute);
6785           break;
6786         }
6787         default:
6788         {
6789           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6790             attribute);
6791           break;
6792         }
6793       }
6794     }
6795     if (normalize != MagickFalse)
6796       {
6797         float
6798           *pixels;
6799
6800         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6801           region.height*sizeof(*pixels));
6802         if (pixels == (float *) NULL)
6803           {
6804             ThrowPerlException(exception,ResourceLimitError,
6805               "MemoryAllocationFailed",PackageName);
6806             goto PerlException;
6807           }
6808         status=ExportImagePixels(image,region.x,region.y,region.width,
6809           region.height,map,FloatPixel,pixels,exception);
6810         if (status == MagickFalse)
6811           PUSHs(&sv_undef);
6812         else
6813           {
6814             EXTEND(sp,strlen(map)*region.width*region.height);
6815             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6816               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6817           }
6818         pixels=(float *) RelinquishMagickMemory(pixels);
6819       }
6820     else
6821       {
6822         Quantum
6823           *pixels;
6824
6825         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6826           region.height*sizeof(*pixels));
6827         if (pixels == (Quantum *) NULL)
6828           {
6829             ThrowPerlException(exception,ResourceLimitError,
6830               "MemoryAllocationFailed",PackageName);
6831             goto PerlException;
6832           }
6833         status=ExportImagePixels(image,region.x,region.y,region.width,
6834           region.height,map,QuantumPixel,pixels,exception);
6835         if (status == MagickFalse)
6836           PUSHs(&sv_undef);
6837         else
6838           {
6839             EXTEND(sp,strlen(map)*region.width*region.height);
6840             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6841               PUSHs(sv_2mortal(newSViv(pixels[i])));
6842           }
6843         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6844       }
6845
6846   PerlException:
6847     InheritPerlException(exception,perl_exception);
6848     exception=DestroyExceptionInfo(exception);
6849     SvREFCNT_dec(perl_exception);
6850   }
6851 \f
6852 #
6853 ###############################################################################
6854 #                                                                             #
6855 #                                                                             #
6856 #                                                                             #
6857 #   I m a g e T o B l o b                                                     #
6858 #                                                                             #
6859 #                                                                             #
6860 #                                                                             #
6861 ###############################################################################
6862 #
6863 #
6864 void
6865 ImageToBlob(ref,...)
6866   Image::Magick ref=NO_INIT
6867   ALIAS:
6868     ImageToBlob  = 1
6869     imagetoblob  = 2
6870     toblob       = 3
6871     blob         = 4
6872   PPCODE:
6873   {
6874     char
6875       filename[MagickPathExtent];
6876
6877     ExceptionInfo
6878       *exception;
6879
6880     Image
6881       *image,
6882       *next;
6883
6884     register ssize_t
6885       i;
6886
6887     struct PackageInfo
6888       *info,
6889       *package_info;
6890
6891     size_t
6892       length;
6893
6894     ssize_t
6895       scene;
6896
6897     SV
6898       *perl_exception,
6899       *reference;
6900
6901     void
6902       *blob;
6903
6904     PERL_UNUSED_VAR(ref);
6905     PERL_UNUSED_VAR(ix);
6906     exception=AcquireExceptionInfo();
6907     perl_exception=newSVpv("",0);
6908     package_info=(struct PackageInfo *) NULL;
6909     if (sv_isobject(ST(0)) == 0)
6910       {
6911         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6912           PackageName);
6913         goto PerlException;
6914       }
6915     reference=SvRV(ST(0));
6916     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6917     if (image == (Image *) NULL)
6918       {
6919         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6920           PackageName);
6921         goto PerlException;
6922       }
6923     package_info=ClonePackageInfo(info,exception);
6924     for (i=2; i < items; i+=2)
6925       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6926     (void) CopyMagickString(filename,package_info->image_info->filename,
6927       MagickPathExtent);
6928     scene=0;
6929     for (next=image; next; next=next->next)
6930     {
6931       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6932       next->scene=scene++;
6933     }
6934     SetImageInfo(package_info->image_info,(unsigned int)
6935       GetImageListLength(image),exception);
6936     EXTEND(sp,(ssize_t) GetImageListLength(image));
6937     for ( ; image; image=image->next)
6938     {
6939       length=0;
6940       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6941       if (blob != (char *) NULL)
6942         {
6943           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6944           blob=(unsigned char *) RelinquishMagickMemory(blob);
6945         }
6946       if (package_info->image_info->adjoin)
6947         break;
6948     }
6949
6950   PerlException:
6951     if (package_info != (struct PackageInfo *) NULL)
6952       DestroyPackageInfo(package_info);
6953     InheritPerlException(exception,perl_exception);
6954     exception=DestroyExceptionInfo(exception);
6955     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6956   }
6957 \f
6958 #
6959 ###############################################################################
6960 #                                                                             #
6961 #                                                                             #
6962 #                                                                             #
6963 #   L a y e r s                                                               #
6964 #                                                                             #
6965 #                                                                             #
6966 #                                                                             #
6967 ###############################################################################
6968 #
6969 #
6970 void
6971 Layers(ref,...)
6972   Image::Magick ref=NO_INIT
6973   ALIAS:
6974     Layers                = 1
6975     layers           = 2
6976     OptimizeImageLayers   = 3
6977     optimizelayers        = 4
6978     optimizeimagelayers   = 5
6979   PPCODE:
6980   {
6981     AV
6982       *av;
6983
6984     char
6985       *attribute;
6986
6987     CompositeOperator
6988       compose;
6989
6990     ExceptionInfo
6991       *exception;
6992
6993     HV
6994       *hv;
6995
6996     Image
6997       *image,
6998       *layers;
6999
7000     LayerMethod
7001       method;
7002
7003     register ssize_t
7004       i;
7005
7006     ssize_t
7007       option,
7008       sp;
7009
7010     struct PackageInfo
7011       *info;
7012
7013     SV
7014       *av_reference,
7015       *perl_exception,
7016       *reference,
7017       *rv,
7018       *sv;
7019
7020     PERL_UNUSED_VAR(ref);
7021     PERL_UNUSED_VAR(ix);
7022     exception=AcquireExceptionInfo();
7023     perl_exception=newSVpv("",0);
7024     sv=NULL;
7025     if (sv_isobject(ST(0)) == 0)
7026       {
7027         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7028           PackageName);
7029         goto PerlException;
7030       }
7031     reference=SvRV(ST(0));
7032     hv=SvSTASH(reference);
7033     av=newAV();
7034     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7035     SvREFCNT_dec(av);
7036     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7037     if (image == (Image *) NULL)
7038       {
7039         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7040           PackageName);
7041         goto PerlException;
7042       }
7043     compose=image->compose;
7044     method=OptimizeLayer;
7045     for (i=2; i < items; i+=2)
7046     {
7047       attribute=(char *) SvPV(ST(i-1),na);
7048       switch (*attribute)
7049       {
7050         case 'C':
7051         case 'c':
7052         {
7053           if (LocaleCompare(attribute,"compose") == 0)
7054             {
7055               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7056                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7057               if (sp < 0)
7058                 {
7059                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7060                     SvPV(ST(i),na));
7061                   break;
7062                 }
7063               compose=(CompositeOperator) sp;
7064               break;
7065             }
7066           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7067             attribute);
7068           break;
7069         }
7070         case 'M':
7071         case 'm':
7072         {
7073           if (LocaleCompare(attribute,"method") == 0)
7074             {
7075               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7076                 SvPV(ST(i),na));
7077               if (option < 0)
7078                 {
7079                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7080                     SvPV(ST(i),na));
7081                   break;
7082                 }
7083               method=(LayerMethod) option;
7084               break;
7085             }
7086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7087             attribute);
7088           break;
7089         }
7090         default:
7091         {
7092           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7093             attribute);
7094           break;
7095         }
7096       }
7097     }
7098     layers=(Image *) NULL;
7099     switch (method)
7100     {
7101       case CompareAnyLayer:
7102       case CompareClearLayer:
7103       case CompareOverlayLayer:
7104       default:
7105       {
7106         layers=CompareImagesLayers(image,method,exception);
7107         break;
7108       }
7109       case MergeLayer:
7110       case FlattenLayer:
7111       case MosaicLayer:
7112       {
7113         layers=MergeImageLayers(image,method,exception);
7114         break;
7115       }
7116       case DisposeLayer:
7117       {
7118         layers=DisposeImages(image,exception);
7119         break;
7120       }
7121       case OptimizeImageLayer:
7122       {
7123         layers=OptimizeImageLayers(image,exception);
7124         break;
7125       }
7126       case OptimizePlusLayer:
7127       {
7128         layers=OptimizePlusImageLayers(image,exception);
7129         break;
7130       }
7131       case OptimizeTransLayer:
7132       {
7133         OptimizeImageTransparency(image,exception);
7134         break;
7135       }
7136       case RemoveDupsLayer:
7137       {
7138         RemoveDuplicateLayers(&image,exception);
7139         break;
7140       }
7141       case RemoveZeroLayer:
7142       {
7143         RemoveZeroDelayLayers(&image,exception);
7144         break;
7145       }
7146       case OptimizeLayer:
7147       {
7148         QuantizeInfo
7149           *quantize_info;
7150
7151         /*
7152           General Purpose, GIF Animation Optimizer.
7153         */
7154         layers=CoalesceImages(image,exception);
7155         if (layers == (Image *) NULL)
7156           break;
7157         image=layers;
7158         layers=OptimizeImageLayers(image,exception);
7159         if (layers == (Image *) NULL)
7160           break;
7161         image=DestroyImageList(image);
7162         image=layers;
7163         layers=(Image *) NULL;
7164         OptimizeImageTransparency(image,exception);
7165         quantize_info=AcquireQuantizeInfo(info->image_info);
7166         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7167         quantize_info=DestroyQuantizeInfo(quantize_info);
7168         break;
7169       }
7170       case CompositeLayer:
7171       {
7172         Image
7173           *source;
7174
7175         RectangleInfo
7176           geometry;
7177
7178         /*
7179           Split image sequence at the first 'NULL:' image.
7180         */
7181         source=image;
7182         while (source != (Image *) NULL)
7183         {
7184           source=GetNextImageInList(source);
7185           if ((source != (Image *) NULL) &&
7186               (LocaleCompare(source->magick,"NULL") == 0))
7187             break;
7188         }
7189         if (source != (Image *) NULL)
7190           {
7191             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7192                 (GetNextImageInList(source) == (Image *) NULL))
7193               source=(Image *) NULL;
7194             else
7195               {
7196                 /*
7197                   Separate the two lists, junk the null: image.
7198                 */
7199                 source=SplitImageList(source->previous);
7200                 DeleteImageFromList(&source);
7201               }
7202           }
7203         if (source == (Image *) NULL)
7204           {
7205             (void) ThrowMagickException(exception,GetMagickModule(),
7206               OptionError,"MissingNullSeparator","layers Composite");
7207             break;
7208           }
7209         /*
7210           Adjust offset with gravity and virtual canvas.
7211         */
7212         SetGeometry(image,&geometry);
7213         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7214         geometry.width=source->page.width != 0 ? source->page.width :
7215           source->columns;
7216         geometry.height=source->page.height != 0 ? source->page.height :
7217           source->rows;
7218         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7219           image->columns,image->page.height != 0 ? image->page.height :
7220           image->rows,image->gravity,&geometry);
7221         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7222         source=DestroyImageList(source);
7223         break;
7224       }
7225     }
7226     if (layers != (Image *) NULL)
7227       image=layers;
7228     else
7229       image=CloneImage(image,0,0,MagickTrue,exception);
7230     if (image == (Image *) NULL)
7231       goto PerlException;
7232     for ( ; image; image=image->next)
7233     {
7234       AddImageToRegistry(sv,image);
7235       rv=newRV(sv);
7236       av_push(av,sv_bless(rv,hv));
7237       SvREFCNT_dec(sv);
7238     }
7239     exception=DestroyExceptionInfo(exception);
7240     ST(0)=av_reference;
7241     SvREFCNT_dec(perl_exception);
7242     XSRETURN(1);
7243
7244   PerlException:
7245     InheritPerlException(exception,perl_exception);
7246     exception=DestroyExceptionInfo(exception);
7247     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7248     SvPOK_on(perl_exception);
7249     ST(0)=sv_2mortal(perl_exception);
7250     XSRETURN(1);
7251   }
7252 \f
7253 #
7254 ###############################################################################
7255 #                                                                             #
7256 #                                                                             #
7257 #                                                                             #
7258 #   M a g i c k T o M i m e                                                   #
7259 #                                                                             #
7260 #                                                                             #
7261 #                                                                             #
7262 ###############################################################################
7263 #
7264 #
7265 SV *
7266 MagickToMime(ref,name)
7267   Image::Magick ref=NO_INIT
7268   char *name
7269   ALIAS:
7270     magicktomime = 1
7271   CODE:
7272   {
7273     char
7274       *mime;
7275
7276     PERL_UNUSED_VAR(ref);
7277     PERL_UNUSED_VAR(ix);
7278     mime=MagickToMime(name);
7279     RETVAL=newSVpv(mime,0);
7280     mime=(char *) RelinquishMagickMemory(mime);
7281   }
7282   OUTPUT:
7283     RETVAL
7284 \f
7285 #
7286 ###############################################################################
7287 #                                                                             #
7288 #                                                                             #
7289 #                                                                             #
7290 #   M o g r i f y                                                             #
7291 #                                                                             #
7292 #                                                                             #
7293 #                                                                             #
7294 ###############################################################################
7295 #
7296 #
7297 void
7298 Mogrify(ref,...)
7299   Image::Magick ref=NO_INIT
7300   ALIAS:
7301     Comment            =   1
7302     CommentImage       =   2
7303     Label              =   3
7304     LabelImage         =   4
7305     AddNoise           =   5
7306     AddNoiseImage      =   6
7307     Colorize           =   7
7308     ColorizeImage      =   8
7309     Border             =   9
7310     BorderImage        =  10
7311     Blur               =  11
7312     BlurImage          =  12
7313     Chop               =  13
7314     ChopImage          =  14
7315     Crop               =  15
7316     CropImage          =  16
7317     Despeckle          =  17
7318     DespeckleImage     =  18
7319     Edge               =  19
7320     EdgeImage          =  20
7321     Emboss             =  21
7322     EmbossImage        =  22
7323     Enhance            =  23
7324     EnhanceImage       =  24
7325     Flip               =  25
7326     FlipImage          =  26
7327     Flop               =  27
7328     FlopImage          =  28
7329     Frame              =  29
7330     FrameImage         =  30
7331     Implode            =  31
7332     ImplodeImage       =  32
7333     Magnify            =  33
7334     MagnifyImage       =  34
7335     MedianFilter       =  35
7336     MedianConvolveImage  =  36
7337     Minify             =  37
7338     MinifyImage        =  38
7339     OilPaint           =  39
7340     OilPaintImage      =  40
7341     ReduceNoise        =  41
7342     ReduceNoiseImage   =  42
7343     Roll               =  43
7344     RollImage          =  44
7345     Rotate             =  45
7346     RotateImage        =  46
7347     Sample             =  47
7348     SampleImage        =  48
7349     Scale              =  49
7350     ScaleImage         =  50
7351     Shade              =  51
7352     ShadeImage         =  52
7353     Sharpen            =  53
7354     SharpenImage       =  54
7355     Shear              =  55
7356     ShearImage         =  56
7357     Spread             =  57
7358     SpreadImage        =  58
7359     Swirl              =  59
7360     SwirlImage         =  60
7361     Resize             =  61
7362     ResizeImage        =  62
7363     Zoom               =  63
7364     ZoomImage          =  64
7365     Annotate           =  65
7366     AnnotateImage      =  66
7367     ColorFloodfill     =  67
7368     ColorFloodfillImage=  68
7369     Composite          =  69
7370     CompositeImage     =  70
7371     Contrast           =  71
7372     ContrastImage      =  72
7373     CycleColormap      =  73
7374     CycleColormapImage =  74
7375     Draw               =  75
7376     DrawImage          =  76
7377     Equalize           =  77
7378     EqualizeImage      =  78
7379     Gamma              =  79
7380     GammaImage         =  80
7381     Map                =  81
7382     MapImage           =  82
7383     MatteFloodfill     =  83
7384     MatteFloodfillImage=  84
7385     Modulate           =  85
7386     ModulateImage      =  86
7387     Negate             =  87
7388     NegateImage        =  88
7389     Normalize          =  89
7390     NormalizeImage     =  90
7391     NumberColors       =  91
7392     NumberColorsImage  =  92
7393     Opaque             =  93
7394     OpaqueImage        =  94
7395     Quantize           =  95
7396     QuantizeImage      =  96
7397     Raise              =  97
7398     RaiseImage         =  98
7399     Segment            =  99
7400     SegmentImage       = 100
7401     Signature          = 101
7402     SignatureImage     = 102
7403     Solarize           = 103
7404     SolarizeImage      = 104
7405     Sync               = 105
7406     SyncImage          = 106
7407     Texture            = 107
7408     TextureImage       = 108
7409     Evaluate           = 109
7410     EvaluateImage      = 110
7411     Transparent        = 111
7412     TransparentImage   = 112
7413     Threshold          = 113
7414     ThresholdImage     = 114
7415     Charcoal           = 115
7416     CharcoalImage      = 116
7417     Trim               = 117
7418     TrimImage          = 118
7419     Wave               = 119
7420     WaveImage          = 120
7421     Separate           = 121
7422     SeparateImage      = 122
7423     Stereo             = 125
7424     StereoImage        = 126
7425     Stegano            = 127
7426     SteganoImage       = 128
7427     Deconstruct        = 129
7428     DeconstructImage   = 130
7429     GaussianBlur       = 131
7430     GaussianBlurImage  = 132
7431     Convolve           = 133
7432     ConvolveImage      = 134
7433     Profile            = 135
7434     ProfileImage       = 136
7435     UnsharpMask        = 137
7436     UnsharpMaskImage   = 138
7437     MotionBlur         = 139
7438     MotionBlurImage    = 140
7439     OrderedDither      = 141
7440     OrderedDitherImage = 142
7441     Shave              = 143
7442     ShaveImage         = 144
7443     Level              = 145
7444     LevelImage         = 146
7445     Clip               = 147
7446     ClipImage          = 148
7447     AffineTransform    = 149
7448     AffineTransformImage = 150
7449     Difference         = 151
7450     DifferenceImage    = 152
7451     AdaptiveThreshold  = 153
7452     AdaptiveThresholdImage = 154
7453     Resample           = 155
7454     ResampleImage      = 156
7455     Describe           = 157
7456     DescribeImage      = 158
7457     BlackThreshold     = 159
7458     BlackThresholdImage= 160
7459     WhiteThreshold     = 161
7460     WhiteThresholdImage= 162
7461     RotationalBlur     = 163
7462     RotationalBlurImage= 164
7463     Thumbnail          = 165
7464     ThumbnailImage     = 166
7465     Strip              = 167
7466     StripImage         = 168
7467     Tint               = 169
7468     TintImage          = 170
7469     Channel            = 171
7470     ChannelImage       = 172
7471     Splice             = 173
7472     SpliceImage        = 174
7473     Posterize          = 175
7474     PosterizeImage     = 176
7475     Shadow             = 177
7476     ShadowImage        = 178
7477     Identify           = 179
7478     IdentifyImage      = 180
7479     SepiaTone          = 181
7480     SepiaToneImage     = 182
7481     SigmoidalContrast  = 183
7482     SigmoidalContrastImage = 184
7483     Extent             = 185
7484     ExtentImage        = 186
7485     Vignette           = 187
7486     VignetteImage      = 188
7487     ContrastStretch    = 189
7488     ContrastStretchImage = 190
7489     Sans0              = 191
7490     Sans0Image         = 192
7491     Sans1              = 193
7492     Sans1Image         = 194
7493     AdaptiveSharpen    = 195
7494     AdaptiveSharpenImage = 196
7495     Transpose          = 197
7496     TransposeImage     = 198
7497     Transverse         = 199
7498     TransverseImage    = 200
7499     AutoOrient         = 201
7500     AutoOrientImage    = 202
7501     AdaptiveBlur       = 203
7502     AdaptiveBlurImage  = 204
7503     Sketch             = 205
7504     SketchImage        = 206
7505     UniqueColors       = 207
7506     UniqueColorsImage  = 208
7507     AdaptiveResize     = 209
7508     AdaptiveResizeImage= 210
7509     ClipMask           = 211
7510     ClipMaskImage      = 212
7511     LinearStretch      = 213
7512     LinearStretchImage = 214
7513     ColorMatrix        = 215
7514     ColorMatrixImage   = 216
7515     Mask               = 217
7516     MaskImage          = 218
7517     Polaroid           = 219
7518     PolaroidImage      = 220
7519     FloodfillPaint     = 221
7520     FloodfillPaintImage= 222
7521     Distort            = 223
7522     DistortImage       = 224
7523     Clut               = 225
7524     ClutImage          = 226
7525     LiquidRescale      = 227
7526     LiquidRescaleImage = 228
7527     Encipher           = 229
7528     EncipherImage      = 230
7529     Decipher           = 231
7530     DecipherImage      = 232
7531     Deskew             = 233
7532     DeskewImage        = 234
7533     Remap              = 235
7534     RemapImage         = 236
7535     SparseColor        = 237
7536     SparseColorImage   = 238
7537     Function           = 239
7538     FunctionImage      = 240
7539     SelectiveBlur      = 241
7540     SelectiveBlurImage = 242
7541     HaldClut           = 243
7542     HaldClutImage      = 244
7543     BlueShift          = 245
7544     BlueShiftImage     = 246
7545     ForwardFourierTransform  = 247
7546     ForwardFourierTransformImage = 248
7547     InverseFourierTransform = 249
7548     InverseFourierTransformImage = 250
7549     ColorDecisionList  = 251
7550     ColorDecisionListImage = 252
7551     AutoGamma          = 253
7552     AutoGammaImage     = 254
7553     AutoLevel          = 255
7554     AutoLevelImage     = 256
7555     LevelColors        = 257
7556     LevelImageColors   = 258
7557     Clamp              = 259
7558     ClampImage         = 260
7559     BrightnessContrast = 261
7560     BrightnessContrastImage = 262
7561     Morphology         = 263
7562     MorphologyImage    = 264
7563     Mode               = 265
7564     ModeImage          = 266
7565     Statistic          = 267
7566     StatisticImage     = 268
7567     Perceptible        = 269
7568     PerceptibleImage   = 270
7569     Poly               = 271
7570     PolyImage          = 272
7571     Grayscale          = 273
7572     GrayscaleImage     = 274
7573     CannyEdge          = 275
7574     CannyEdgeImage     = 276
7575     HoughLine          = 277
7576     HoughLineImage     = 278
7577     MeanShift          = 279
7578     MeanShiftImage     = 280
7579     Kuwahara           = 281
7580     KuwaharaImage      = 282
7581     ConnectedComponent = 283
7582     ConnectedComponentImage = 284
7583     CopyPixels         = 285
7584     CopyImagePixels    = 286
7585     Color              = 287
7586     ColorImage         = 288
7587     WaveletDenoise     = 289
7588     WaveletDenoiseImage= 290
7589     MogrifyRegion      = 666
7590   PPCODE:
7591   {
7592     AffineMatrix
7593       affine,
7594       current;
7595
7596     char
7597       attribute_flag[MaxArguments],
7598       message[MagickPathExtent];
7599
7600     ChannelType
7601       channel,
7602       channel_mask;
7603
7604     CompositeOperator
7605       compose;
7606
7607     const char
7608       *attribute,
7609       *value;
7610
7611     double
7612       angle;
7613
7614     ExceptionInfo
7615       *exception;
7616
7617     GeometryInfo
7618       geometry_info;
7619
7620     Image
7621       *image,
7622       *next,
7623       *region_image;
7624
7625     MagickBooleanType
7626       status;
7627
7628     MagickStatusType
7629       flags;
7630
7631     PixelInfo
7632       fill_color;
7633
7634     RectangleInfo
7635       geometry,
7636       region_info;
7637
7638     register ssize_t
7639       i;
7640
7641     ssize_t
7642       base,
7643       j,
7644       number_images;
7645
7646     struct Methods
7647       *rp;
7648
7649     struct PackageInfo
7650       *info;
7651
7652     SV
7653       *perl_exception,
7654       **pv,
7655       *reference,
7656       **reference_vector;
7657
7658     struct ArgumentList
7659       argument_list[MaxArguments];
7660
7661     PERL_UNUSED_VAR(ref);
7662     PERL_UNUSED_VAR(ix);
7663     exception=AcquireExceptionInfo();
7664     perl_exception=newSVpv("",0);
7665     reference_vector=NULL;
7666     region_image=NULL;
7667     number_images=0;
7668     base=2;
7669     if (sv_isobject(ST(0)) == 0)
7670       {
7671         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7672           PackageName);
7673         goto PerlException;
7674       }
7675     reference=SvRV(ST(0));
7676     region_info.width=0;
7677     region_info.height=0;
7678     region_info.x=0;
7679     region_info.y=0;
7680     region_image=(Image *) NULL;
7681     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7682     if (ix && (ix != 666))
7683       {
7684         /*
7685           Called as Method(...)
7686         */
7687         ix=(ix+1)/2;
7688         rp=(&Methods[ix-1]);
7689         attribute=rp->name;
7690       }
7691     else
7692       {
7693         /*
7694           Called as Mogrify("Method",...)
7695         */
7696         attribute=(char *) SvPV(ST(1),na);
7697         if (ix)
7698           {
7699             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7700             attribute=(char *) SvPV(ST(2),na);
7701             base++;
7702           }
7703         for (rp=Methods; ; rp++)
7704         {
7705           if (rp >= EndOf(Methods))
7706             {
7707               ThrowPerlException(exception,OptionError,
7708                 "UnrecognizedPerlMagickMethod",attribute);
7709               goto PerlException;
7710             }
7711           if (strEQcase(attribute,rp->name))
7712             break;
7713         }
7714         ix=rp-Methods+1;
7715         base++;
7716       }
7717     if (image == (Image *) NULL)
7718       {
7719         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7720         goto PerlException;
7721       }
7722     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7723     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7724     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7725     {
7726       Arguments
7727         *pp,
7728         *qq;
7729
7730       ssize_t
7731         ssize_test;
7732
7733       struct ArgumentList
7734         *al;
7735
7736       SV
7737         *sv;
7738
7739       sv=NULL;
7740       ssize_test=0;
7741       pp=(Arguments *) NULL;
7742       qq=rp->arguments;
7743       if (i == items)
7744         {
7745           pp=rp->arguments,
7746           sv=ST(i-1);
7747         }
7748       else
7749         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7750         {
7751           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7752             break;
7753           if (strEQcase(attribute,qq->method) > ssize_test)
7754             {
7755               pp=qq;
7756               ssize_test=strEQcase(attribute,qq->method);
7757             }
7758         }
7759       if (pp == (Arguments *) NULL)
7760         {
7761           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7762             attribute);
7763           goto continue_outer_loop;
7764         }
7765       al=(&argument_list[pp-rp->arguments]);
7766       switch (pp->type)
7767       {
7768         case ArrayReference:
7769         {
7770           if (SvTYPE(sv) != SVt_RV)
7771             {
7772               (void) FormatLocaleString(message,MagickPathExtent,
7773                 "invalid %.60s value",pp->method);
7774               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7775               goto continue_outer_loop;
7776             }
7777           al->array_reference=SvRV(sv);
7778           break;
7779         }
7780         case RealReference:
7781         {
7782           al->real_reference=SvNV(sv);
7783           break;
7784         }
7785         case FileReference:
7786         {
7787           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7788           break;
7789         }
7790         case ImageReference:
7791         {
7792           if (!sv_isobject(sv) ||
7793               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7794                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7795             {
7796               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7797                 PackageName);
7798               goto PerlException;
7799             }
7800           break;
7801         }
7802         case IntegerReference:
7803         {
7804           al->integer_reference=SvIV(sv);
7805           break;
7806         }
7807         case StringReference:
7808         {
7809           al->string_reference=(char *) SvPV(sv,al->length);
7810           if (sv_isobject(sv))
7811             al->image_reference=SetupList(aTHX_ SvRV(sv),
7812               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7813           break;
7814         }
7815         default:
7816         {
7817           /*
7818             Is a string; look up name.
7819           */
7820           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7821             {
7822               al->string_reference=(char *) SvPV(sv,al->length);
7823               al->integer_reference=(-1);
7824               break;
7825             }
7826           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7827             MagickFalse,SvPV(sv,na));
7828           if (pp->type == MagickChannelOptions)
7829             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7830           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7831             {
7832               (void) FormatLocaleString(message,MagickPathExtent,
7833                 "invalid %.60s value",pp->method);
7834               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7835               goto continue_outer_loop;
7836             }
7837           break;
7838         }
7839       }
7840       attribute_flag[pp-rp->arguments]++;
7841       continue_outer_loop: ;
7842     }
7843     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7844     pv=reference_vector;
7845     SetGeometryInfo(&geometry_info);
7846     channel=DefaultChannels;
7847     for (next=image; next; next=next->next)
7848     {
7849       image=next;
7850       SetGeometry(image,&geometry);
7851       if ((region_info.width*region_info.height) != 0)
7852         {
7853           region_image=image;
7854           image=CropImage(image,&region_info,exception);
7855         }
7856       switch (ix)
7857       {
7858         default:
7859         {
7860           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7861           ThrowPerlException(exception,OptionError,
7862             "UnrecognizedPerlMagickMethod",message);
7863           goto PerlException;
7864         }
7865         case 1:  /* Comment */
7866         {
7867           if (attribute_flag[0] == 0)
7868             argument_list[0].string_reference=(char *) NULL;
7869           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7870             info ? info->image_info : (ImageInfo *) NULL,image,
7871             argument_list[0].string_reference,exception),exception);
7872           break;
7873         }
7874         case 2:  /* Label */
7875         {
7876           if (attribute_flag[0] == 0)
7877             argument_list[0].string_reference=(char *) NULL;
7878           (void) SetImageProperty(image,"label",InterpretImageProperties(
7879             info ? info->image_info : (ImageInfo *) NULL,image,
7880             argument_list[0].string_reference,exception),exception);
7881           break;
7882         }
7883         case 3:  /* AddNoise */
7884         {
7885           double
7886             attenuate;
7887
7888           if (attribute_flag[0] == 0)
7889             argument_list[0].integer_reference=UniformNoise;
7890           attenuate=1.0;
7891           if (attribute_flag[1] != 0)
7892             attenuate=argument_list[1].real_reference;
7893           if (attribute_flag[2] != 0)
7894             channel=(ChannelType) argument_list[2].integer_reference;
7895           channel_mask=SetImageChannelMask(image,channel);
7896           image=AddNoiseImage(image,(NoiseType)
7897             argument_list[0].integer_reference,attenuate,exception);
7898           if (image != (Image *) NULL)
7899             (void) SetImageChannelMask(image,channel_mask);
7900           break;
7901         }
7902         case 4:  /* Colorize */
7903         {
7904           PixelInfo
7905             target;
7906
7907           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7908             0,0,&target,exception);
7909           if (attribute_flag[0] != 0)
7910             (void) QueryColorCompliance(argument_list[0].string_reference,
7911               AllCompliance,&target,exception);
7912           if (attribute_flag[1] == 0)
7913             argument_list[1].string_reference="100%";
7914           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7915             exception);
7916           break;
7917         }
7918         case 5:  /* Border */
7919         {
7920           CompositeOperator
7921             compose;
7922
7923           geometry.width=0;
7924           geometry.height=0;
7925           if (attribute_flag[0] != 0)
7926             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7927               &geometry,exception);
7928           if (attribute_flag[1] != 0)
7929             geometry.width=argument_list[1].integer_reference;
7930           if (attribute_flag[2] != 0)
7931             geometry.height=argument_list[2].integer_reference;
7932           if (attribute_flag[3] != 0)
7933             QueryColorCompliance(argument_list[3].string_reference,
7934               AllCompliance,&image->border_color,exception);
7935           if (attribute_flag[4] != 0)
7936             QueryColorCompliance(argument_list[4].string_reference,
7937               AllCompliance,&image->border_color,exception);
7938           if (attribute_flag[5] != 0)
7939             QueryColorCompliance(argument_list[5].string_reference,
7940               AllCompliance,&image->border_color,exception);
7941           compose=image->compose;
7942           if (attribute_flag[6] != 0)
7943             compose=(CompositeOperator) argument_list[6].integer_reference;
7944           image=BorderImage(image,&geometry,compose,exception);
7945           break;
7946         }
7947         case 6:  /* Blur */
7948         {
7949           if (attribute_flag[0] != 0)
7950             {
7951               flags=ParseGeometry(argument_list[0].string_reference,
7952                 &geometry_info);
7953               if ((flags & SigmaValue) == 0)
7954                 geometry_info.sigma=1.0;
7955             }
7956           if (attribute_flag[1] != 0)
7957             geometry_info.rho=argument_list[1].real_reference;
7958           if (attribute_flag[2] != 0)
7959             geometry_info.sigma=argument_list[2].real_reference;
7960           if (attribute_flag[3] != 0)
7961             channel=(ChannelType) argument_list[3].integer_reference;
7962           channel_mask=SetImageChannelMask(image,channel);
7963           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7964             exception);
7965           if (image != (Image *) NULL)
7966             (void) SetImageChannelMask(image,channel_mask);
7967           break;
7968         }
7969         case 7:  /* Chop */
7970         {
7971           if (attribute_flag[5] != 0)
7972             image->gravity=(GravityType) argument_list[5].integer_reference;
7973           if (attribute_flag[0] != 0)
7974             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7975               &geometry,exception);
7976           if (attribute_flag[1] != 0)
7977             geometry.width=argument_list[1].integer_reference;
7978           if (attribute_flag[2] != 0)
7979             geometry.height=argument_list[2].integer_reference;
7980           if (attribute_flag[3] != 0)
7981             geometry.x=argument_list[3].integer_reference;
7982           if (attribute_flag[4] != 0)
7983             geometry.y=argument_list[4].integer_reference;
7984           image=ChopImage(image,&geometry,exception);
7985           break;
7986         }
7987         case 8:  /* Crop */
7988         {
7989           if (attribute_flag[6] != 0)
7990             image->gravity=(GravityType) argument_list[6].integer_reference;
7991           if (attribute_flag[0] != 0)
7992             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7993               &geometry,exception);
7994           if (attribute_flag[1] != 0)
7995             geometry.width=argument_list[1].integer_reference;
7996           if (attribute_flag[2] != 0)
7997             geometry.height=argument_list[2].integer_reference;
7998           if (attribute_flag[3] != 0)
7999             geometry.x=argument_list[3].integer_reference;
8000           if (attribute_flag[4] != 0)
8001             geometry.y=argument_list[4].integer_reference;
8002           if (attribute_flag[5] != 0)
8003             image->fuzz=StringToDoubleInterval(
8004               argument_list[5].string_reference,(double) QuantumRange+1.0);
8005           image=CropImage(image,&geometry,exception);
8006           break;
8007         }
8008         case 9:  /* Despeckle */
8009         {
8010           image=DespeckleImage(image,exception);
8011           break;
8012         }
8013         case 10:  /* Edge */
8014         {
8015           if (attribute_flag[0] != 0)
8016             geometry_info.rho=argument_list[0].real_reference;
8017           image=EdgeImage(image,geometry_info.rho,exception);
8018           break;
8019         }
8020         case 11:  /* Emboss */
8021         {
8022           if (attribute_flag[0] != 0)
8023             {
8024               flags=ParseGeometry(argument_list[0].string_reference,
8025                 &geometry_info);
8026               if ((flags & SigmaValue) == 0)
8027                 geometry_info.sigma=1.0;
8028             }
8029           if (attribute_flag[1] != 0)
8030             geometry_info.rho=argument_list[1].real_reference;
8031           if (attribute_flag[2] != 0)
8032             geometry_info.sigma=argument_list[2].real_reference;
8033           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
8034             exception);
8035           break;
8036         }
8037         case 12:  /* Enhance */
8038         {
8039           image=EnhanceImage(image,exception);
8040           break;
8041         }
8042         case 13:  /* Flip */
8043         {
8044           image=FlipImage(image,exception);
8045           break;
8046         }
8047         case 14:  /* Flop */
8048         {
8049           image=FlopImage(image,exception);
8050           break;
8051         }
8052         case 15:  /* Frame */
8053         {
8054           CompositeOperator
8055             compose;
8056
8057           FrameInfo
8058             frame_info;
8059
8060           if (attribute_flag[0] != 0)
8061             {
8062               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8063                 &geometry,exception);
8064               frame_info.width=geometry.width;
8065               frame_info.height=geometry.height;
8066               frame_info.outer_bevel=geometry.x;
8067               frame_info.inner_bevel=geometry.y;
8068             }
8069           if (attribute_flag[1] != 0)
8070             frame_info.width=argument_list[1].integer_reference;
8071           if (attribute_flag[2] != 0)
8072             frame_info.height=argument_list[2].integer_reference;
8073           if (attribute_flag[3] != 0)
8074             frame_info.inner_bevel=argument_list[3].integer_reference;
8075           if (attribute_flag[4] != 0)
8076             frame_info.outer_bevel=argument_list[4].integer_reference;
8077           if (attribute_flag[5] != 0)
8078             QueryColorCompliance(argument_list[5].string_reference,
8079               AllCompliance,&fill_color,exception);
8080           if (attribute_flag[6] != 0)
8081             QueryColorCompliance(argument_list[6].string_reference,
8082               AllCompliance,&fill_color,exception);
8083           frame_info.x=(ssize_t) frame_info.width;
8084           frame_info.y=(ssize_t) frame_info.height;
8085           frame_info.width=image->columns+2*frame_info.x;
8086           frame_info.height=image->rows+2*frame_info.y;
8087           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8088             image->alpha_color=fill_color;
8089           compose=image->compose;
8090           if (attribute_flag[7] != 0)
8091             compose=(CompositeOperator) argument_list[7].integer_reference;
8092           image=FrameImage(image,&frame_info,compose,exception);
8093           break;
8094         }
8095         case 16:  /* Implode */
8096         {
8097           PixelInterpolateMethod
8098             method;
8099
8100           if (attribute_flag[0] == 0)
8101             argument_list[0].real_reference=0.5;
8102           method=UndefinedInterpolatePixel;
8103           if (attribute_flag[1] != 0)
8104             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8105           image=ImplodeImage(image,argument_list[0].real_reference,
8106             method,exception);
8107           break;
8108         }
8109         case 17:  /* Magnify */
8110         {
8111           image=MagnifyImage(image,exception);
8112           break;
8113         }
8114         case 18:  /* MedianFilter */
8115         {
8116           if (attribute_flag[0] != 0)
8117             {
8118               flags=ParseGeometry(argument_list[0].string_reference,
8119                 &geometry_info);
8120               if ((flags & SigmaValue) == 0)
8121                 geometry_info.sigma=geometry_info.rho;
8122             }
8123           if (attribute_flag[1] != 0)
8124             geometry_info.rho=argument_list[1].real_reference;
8125           if (attribute_flag[2] != 0)
8126             geometry_info.sigma=argument_list[2].real_reference;
8127           if (attribute_flag[3] != 0)
8128             channel=(ChannelType) argument_list[3].integer_reference;
8129           channel_mask=SetImageChannelMask(image,channel);
8130           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8131             (size_t) geometry_info.sigma,exception);
8132           if (image != (Image *) NULL)
8133             (void) SetImageChannelMask(image,channel_mask);
8134           break;
8135         }
8136         case 19:  /* Minify */
8137         {
8138           image=MinifyImage(image,exception);
8139           break;
8140         }
8141         case 20:  /* OilPaint */
8142         {
8143           if (attribute_flag[0] == 0)
8144             argument_list[0].real_reference=0.0;
8145           if (attribute_flag[1] == 0)
8146             argument_list[1].real_reference=1.0;
8147           image=OilPaintImage(image,argument_list[0].real_reference,
8148             argument_list[1].real_reference,exception);
8149           break;
8150         }
8151         case 21:  /* ReduceNoise */
8152         {
8153           if (attribute_flag[0] != 0)
8154             {
8155               flags=ParseGeometry(argument_list[0].string_reference,
8156                 &geometry_info);
8157               if ((flags & SigmaValue) == 0)
8158                 geometry_info.sigma=1.0;
8159             }
8160           if (attribute_flag[1] != 0)
8161             geometry_info.rho=argument_list[1].real_reference;
8162           if (attribute_flag[2] != 0)
8163             geometry_info.sigma=argument_list[2].real_reference;
8164           if (attribute_flag[3] != 0)
8165             channel=(ChannelType) argument_list[3].integer_reference;
8166           channel_mask=SetImageChannelMask(image,channel);
8167           image=StatisticImage(image,NonpeakStatistic,(size_t)
8168             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8169           if (image != (Image *) NULL)
8170             (void) SetImageChannelMask(image,channel_mask);
8171           break;
8172         }
8173         case 22:  /* Roll */
8174         {
8175           if (attribute_flag[0] != 0)
8176             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8177               &geometry,exception);
8178           if (attribute_flag[1] != 0)
8179             geometry.x=argument_list[1].integer_reference;
8180           if (attribute_flag[2] != 0)
8181             geometry.y=argument_list[2].integer_reference;
8182           image=RollImage(image,geometry.x,geometry.y,exception);
8183           break;
8184         }
8185         case 23:  /* Rotate */
8186         {
8187           if (attribute_flag[0] == 0)
8188             argument_list[0].real_reference=90.0;
8189           if (attribute_flag[1] != 0)
8190             {
8191               QueryColorCompliance(argument_list[1].string_reference,
8192                 AllCompliance,&image->background_color,exception);
8193               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8194                   (image->alpha_trait == UndefinedPixelTrait))
8195                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8196             }
8197           image=RotateImage(image,argument_list[0].real_reference,exception);
8198           break;
8199         }
8200         case 24:  /* Sample */
8201         {
8202           if (attribute_flag[0] != 0)
8203             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8204               &geometry,exception);
8205           if (attribute_flag[1] != 0)
8206             geometry.width=argument_list[1].integer_reference;
8207           if (attribute_flag[2] != 0)
8208             geometry.height=argument_list[2].integer_reference;
8209           image=SampleImage(image,geometry.width,geometry.height,exception);
8210           break;
8211         }
8212         case 25:  /* Scale */
8213         {
8214           if (attribute_flag[0] != 0)
8215             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8216               &geometry,exception);
8217           if (attribute_flag[1] != 0)
8218             geometry.width=argument_list[1].integer_reference;
8219           if (attribute_flag[2] != 0)
8220             geometry.height=argument_list[2].integer_reference;
8221           image=ScaleImage(image,geometry.width,geometry.height,exception);
8222           break;
8223         }
8224         case 26:  /* Shade */
8225         {
8226           if (attribute_flag[0] != 0)
8227             {
8228               flags=ParseGeometry(argument_list[0].string_reference,
8229                 &geometry_info);
8230               if ((flags & SigmaValue) == 0)
8231                 geometry_info.sigma=0.0;
8232             }
8233           if (attribute_flag[1] != 0)
8234             geometry_info.rho=argument_list[1].real_reference;
8235           if (attribute_flag[2] != 0)
8236             geometry_info.sigma=argument_list[2].real_reference;
8237           image=ShadeImage(image,
8238             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8239             geometry_info.rho,geometry_info.sigma,exception);
8240           break;
8241         }
8242         case 27:  /* Sharpen */
8243         {
8244           if (attribute_flag[0] != 0)
8245             {
8246               flags=ParseGeometry(argument_list[0].string_reference,
8247                 &geometry_info);
8248               if ((flags & SigmaValue) == 0)
8249                 geometry_info.sigma=1.0;
8250             }
8251           if (attribute_flag[1] != 0)
8252             geometry_info.rho=argument_list[1].real_reference;
8253           if (attribute_flag[2] != 0)
8254             geometry_info.sigma=argument_list[2].real_reference;
8255           if (attribute_flag[3] != 0)
8256             channel=(ChannelType) argument_list[3].integer_reference;
8257           channel_mask=SetImageChannelMask(image,channel);
8258           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8259             exception);
8260           if (image != (Image *) NULL)
8261             (void) SetImageChannelMask(image,channel_mask);
8262           break;
8263         }
8264         case 28:  /* Shear */
8265         {
8266           if (attribute_flag[0] != 0)
8267             {
8268               flags=ParseGeometry(argument_list[0].string_reference,
8269                 &geometry_info);
8270               if ((flags & SigmaValue) == 0)
8271                 geometry_info.sigma=geometry_info.rho;
8272             }
8273           if (attribute_flag[1] != 0)
8274             geometry_info.rho=argument_list[1].real_reference;
8275           if (attribute_flag[2] != 0)
8276             geometry_info.sigma=argument_list[2].real_reference;
8277           if (attribute_flag[3] != 0)
8278             QueryColorCompliance(argument_list[3].string_reference,
8279               AllCompliance,&image->background_color,exception);
8280           if (attribute_flag[4] != 0)
8281             QueryColorCompliance(argument_list[4].string_reference,
8282               AllCompliance,&image->background_color,exception);
8283           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8284             exception);
8285           break;
8286         }
8287         case 29:  /* Spread */
8288         {
8289           PixelInterpolateMethod
8290             method;
8291
8292           if (attribute_flag[0] == 0)
8293             argument_list[0].real_reference=1.0;
8294           method=UndefinedInterpolatePixel;
8295           if (attribute_flag[1] != 0)
8296             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8297           image=SpreadImage(image,method,argument_list[0].real_reference,
8298             exception);
8299           break;
8300         }
8301         case 30:  /* Swirl */
8302         {
8303           PixelInterpolateMethod
8304             method;
8305
8306           if (attribute_flag[0] == 0)
8307             argument_list[0].real_reference=50.0;
8308           method=UndefinedInterpolatePixel;
8309           if (attribute_flag[1] != 0)
8310             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8311           image=SwirlImage(image,argument_list[0].real_reference,
8312             method,exception);
8313           break;
8314         }
8315         case 31:  /* Resize */
8316         case 32:  /* Zoom */
8317         {
8318           if (attribute_flag[0] != 0)
8319             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8320               &geometry,exception);
8321           if (attribute_flag[1] != 0)
8322             geometry.width=argument_list[1].integer_reference;
8323           if (attribute_flag[2] != 0)
8324             geometry.height=argument_list[2].integer_reference;
8325           if (attribute_flag[3] == 0)
8326             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8327           if (attribute_flag[4] != 0)
8328             SetImageArtifact(image,"filter:support",
8329               argument_list[4].string_reference);
8330           image=ResizeImage(image,geometry.width,geometry.height,
8331             (FilterType) argument_list[3].integer_reference,
8332             exception);
8333           break;
8334         }
8335         case 33:  /* Annotate */
8336         {
8337           DrawInfo
8338             *draw_info;
8339
8340           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8341             (DrawInfo *) NULL);
8342           if (attribute_flag[0] != 0)
8343             {
8344               char
8345                 *text;
8346
8347               text=InterpretImageProperties(info ? info->image_info :
8348                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8349                 exception);
8350               (void) CloneString(&draw_info->text,text);
8351               text=DestroyString(text);
8352             }
8353           if (attribute_flag[1] != 0)
8354             (void) CloneString(&draw_info->font,
8355               argument_list[1].string_reference);
8356           if (attribute_flag[2] != 0)
8357             draw_info->pointsize=argument_list[2].real_reference;
8358           if (attribute_flag[3] != 0)
8359             (void) CloneString(&draw_info->density,
8360               argument_list[3].string_reference);
8361           if (attribute_flag[4] != 0)
8362             (void) QueryColorCompliance(argument_list[4].string_reference,
8363               AllCompliance,&draw_info->undercolor,exception);
8364           if (attribute_flag[5] != 0)
8365             {
8366               (void) QueryColorCompliance(argument_list[5].string_reference,
8367                 AllCompliance,&draw_info->stroke,exception);
8368               if (argument_list[5].image_reference != (Image *) NULL)
8369                 draw_info->stroke_pattern=CloneImage(
8370                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8371             }
8372           if (attribute_flag[6] != 0)
8373             {
8374               (void) QueryColorCompliance(argument_list[6].string_reference,
8375                 AllCompliance,&draw_info->fill,exception);
8376               if (argument_list[6].image_reference != (Image *) NULL)
8377                 draw_info->fill_pattern=CloneImage(
8378                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8379             }
8380           if (attribute_flag[7] != 0)
8381             {
8382               (void) CloneString(&draw_info->geometry,
8383                 argument_list[7].string_reference);
8384               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8385                 &geometry,exception);
8386               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8387                 geometry_info.sigma=geometry_info.xi;
8388             }
8389           if (attribute_flag[8] != 0)
8390             (void) QueryColorCompliance(argument_list[8].string_reference,
8391               AllCompliance,&draw_info->fill,exception);
8392           if (attribute_flag[11] != 0)
8393             draw_info->gravity=(GravityType)
8394               argument_list[11].integer_reference;
8395           if (attribute_flag[25] != 0)
8396             {
8397               AV
8398                 *av;
8399
8400               av=(AV *) argument_list[25].array_reference;
8401               if ((av_len(av) != 3) && (av_len(av) != 5))
8402                 {
8403                   ThrowPerlException(exception,OptionError,
8404                     "affine matrix must have 4 or 6 elements",PackageName);
8405                   goto PerlException;
8406                 }
8407               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8408               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8409               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8410               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8411               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8412                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8413                 {
8414                   ThrowPerlException(exception,OptionError,
8415                     "affine matrix is singular",PackageName);
8416                    goto PerlException;
8417                 }
8418               if (av_len(av) == 5)
8419                 {
8420                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8421                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8422                 }
8423             }
8424           for (j=12; j < 17; j++)
8425           {
8426             if (attribute_flag[j] == 0)
8427               continue;
8428             value=argument_list[j].string_reference;
8429             angle=argument_list[j].real_reference;
8430             current=draw_info->affine;
8431             GetAffineMatrix(&affine);
8432             switch (j)
8433             {
8434               case 12:
8435               {
8436                 /*
8437                   Translate.
8438                 */
8439                 flags=ParseGeometry(value,&geometry_info);
8440                 affine.tx=geometry_info.xi;
8441                 affine.ty=geometry_info.psi;
8442                 if ((flags & PsiValue) == 0)
8443                   affine.ty=affine.tx;
8444                 break;
8445               }
8446               case 13:
8447               {
8448                 /*
8449                   Scale.
8450                 */
8451                 flags=ParseGeometry(value,&geometry_info);
8452                 affine.sx=geometry_info.rho;
8453                 affine.sy=geometry_info.sigma;
8454                 if ((flags & SigmaValue) == 0)
8455                   affine.sy=affine.sx;
8456                 break;
8457               }
8458               case 14:
8459               {
8460                 /*
8461                   Rotate.
8462                 */
8463                 if (angle == 0.0)
8464                   break;
8465                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8466                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8467                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8468                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8469                 break;
8470               }
8471               case 15:
8472               {
8473                 /*
8474                   SkewX.
8475                 */
8476                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8477                 break;
8478               }
8479               case 16:
8480               {
8481                 /*
8482                   SkewY.
8483                 */
8484                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8485                 break;
8486               }
8487             }
8488             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8489             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8490             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8491             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8492             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8493               current.tx;
8494             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8495               current.ty;
8496           }
8497           if (attribute_flag[9] == 0)
8498             argument_list[9].real_reference=0.0;
8499           if (attribute_flag[10] == 0)
8500             argument_list[10].real_reference=0.0;
8501           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8502             {
8503               char
8504                 geometry[MagickPathExtent];
8505
8506               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8507                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8508                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8509               (void) CloneString(&draw_info->geometry,geometry);
8510             }
8511           if (attribute_flag[17] != 0)
8512             draw_info->stroke_width=argument_list[17].real_reference;
8513           if (attribute_flag[18] != 0)
8514             {
8515               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8516                 MagickTrue : MagickFalse;
8517               draw_info->stroke_antialias=draw_info->text_antialias;
8518             }
8519           if (attribute_flag[19] != 0)
8520             (void) CloneString(&draw_info->family,
8521               argument_list[19].string_reference);
8522           if (attribute_flag[20] != 0)
8523             draw_info->style=(StyleType) argument_list[20].integer_reference;
8524           if (attribute_flag[21] != 0)
8525             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8526           if (attribute_flag[22] != 0)
8527             draw_info->weight=argument_list[22].integer_reference;
8528           if (attribute_flag[23] != 0)
8529             draw_info->align=(AlignType) argument_list[23].integer_reference;
8530           if (attribute_flag[24] != 0)
8531             (void) CloneString(&draw_info->encoding,
8532               argument_list[24].string_reference);
8533           if (attribute_flag[25] != 0)
8534             draw_info->fill_pattern=CloneImage(
8535               argument_list[25].image_reference,0,0,MagickTrue,exception);
8536           if (attribute_flag[26] != 0)
8537             draw_info->fill_pattern=CloneImage(
8538               argument_list[26].image_reference,0,0,MagickTrue,exception);
8539           if (attribute_flag[27] != 0)
8540             draw_info->stroke_pattern=CloneImage(
8541               argument_list[27].image_reference,0,0,MagickTrue,exception);
8542           if (attribute_flag[29] != 0)
8543             draw_info->kerning=argument_list[29].real_reference;
8544           if (attribute_flag[30] != 0)
8545             draw_info->interline_spacing=argument_list[30].real_reference;
8546           if (attribute_flag[31] != 0)
8547             draw_info->interword_spacing=argument_list[31].real_reference;
8548           if (attribute_flag[32] != 0)
8549             draw_info->direction=(DirectionType)
8550               argument_list[32].integer_reference;
8551           (void) AnnotateImage(image,draw_info,exception);
8552           draw_info=DestroyDrawInfo(draw_info);
8553           break;
8554         }
8555         case 34:  /* ColorFloodfill */
8556         {
8557           DrawInfo
8558             *draw_info;
8559
8560           MagickBooleanType
8561             invert;
8562
8563           PixelInfo
8564             target;
8565
8566           draw_info=CloneDrawInfo(info ? info->image_info :
8567             (ImageInfo *) NULL,(DrawInfo *) NULL);
8568           if (attribute_flag[0] != 0)
8569             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8570               &geometry,exception);
8571           if (attribute_flag[1] != 0)
8572             geometry.x=argument_list[1].integer_reference;
8573           if (attribute_flag[2] != 0)
8574             geometry.y=argument_list[2].integer_reference;
8575           if (attribute_flag[3] != 0)
8576             (void) QueryColorCompliance(argument_list[3].string_reference,
8577               AllCompliance,&draw_info->fill,exception);
8578           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8579             geometry.x,geometry.y,&target,exception);
8580           invert=MagickFalse;
8581           if (attribute_flag[4] != 0)
8582             {
8583               QueryColorCompliance(argument_list[4].string_reference,
8584                 AllCompliance,&target,exception);
8585               invert=MagickTrue;
8586             }
8587           if (attribute_flag[5] != 0)
8588             image->fuzz=StringToDoubleInterval(
8589               argument_list[5].string_reference,(double) QuantumRange+1.0);
8590           if (attribute_flag[6] != 0)
8591             invert=(MagickBooleanType) argument_list[6].integer_reference;
8592           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8593             geometry.y,invert,exception);
8594           draw_info=DestroyDrawInfo(draw_info);
8595           break;
8596         }
8597         case 35:  /* Composite */
8598         {
8599           char
8600             composite_geometry[MagickPathExtent];
8601
8602           Image
8603             *composite_image,
8604             *rotate_image;
8605
8606           MagickBooleanType
8607             clip_to_self;
8608
8609           compose=OverCompositeOp;
8610           if (attribute_flag[0] != 0)
8611             composite_image=argument_list[0].image_reference;
8612           else
8613             {
8614               ThrowPerlException(exception,OptionError,
8615                 "CompositeImageRequired",PackageName);
8616               goto PerlException;
8617             }
8618           /*
8619             Parameter Handling used for BOTH normal and tiled composition.
8620           */
8621           if (attribute_flag[1] != 0) /* compose */
8622             compose=(CompositeOperator) argument_list[1].integer_reference;
8623           if (attribute_flag[6] != 0) /* opacity  */
8624             {
8625               if (compose != DissolveCompositeOp)
8626                 (void) SetImageAlpha(composite_image,(Quantum)
8627                   StringToDoubleInterval(argument_list[6].string_reference,
8628                   (double) QuantumRange+1.0),exception);
8629               else
8630                 {
8631                   CacheView
8632                     *composite_view;
8633
8634                   double
8635                     opacity;
8636
8637                   MagickBooleanType
8638                     sync;
8639
8640                   register ssize_t
8641                     x;
8642
8643                   register Quantum
8644                     *q;
8645
8646                   ssize_t
8647                     y;
8648
8649                   /*
8650                     Handle dissolve composite operator (patch by
8651                     Kevin A. McGrail).
8652                   */
8653                   (void) CloneString(&image->geometry,
8654                     argument_list[6].string_reference);
8655                   opacity=(Quantum) StringToDoubleInterval(
8656                     argument_list[6].string_reference,(double) QuantumRange+
8657                     1.0);
8658                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8659                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8660                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8661                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8662                   {
8663                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8664                       composite_image->columns,1,exception);
8665                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8666                     {
8667                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8668                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8669                           q);
8670                       q+=GetPixelChannels(composite_image);
8671                     }
8672                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8673                     if (sync == MagickFalse)
8674                       break;
8675                   }
8676                   composite_view=DestroyCacheView(composite_view);
8677                 }
8678             }
8679           if (attribute_flag[9] != 0)    /* "color=>" */
8680             QueryColorCompliance(argument_list[9].string_reference,
8681               AllCompliance,&composite_image->background_color,exception);
8682           if (attribute_flag[12] != 0) /* "interpolate=>" */
8683             image->interpolate=(PixelInterpolateMethod)
8684               argument_list[12].integer_reference;
8685           if (attribute_flag[13] != 0)   /* "args=>" */
8686             (void) SetImageArtifact(composite_image,"compose:args",
8687               argument_list[13].string_reference);
8688           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8689             (void) SetImageArtifact(composite_image,"compose:args",
8690               argument_list[14].string_reference);
8691           clip_to_self=MagickTrue;
8692           if (attribute_flag[15] != 0)
8693             clip_to_self=(MagickBooleanType)
8694               argument_list[15].integer_reference;
8695           /*
8696             Tiling Composition (with orthogonal rotate).
8697           */
8698           rotate_image=(Image *) NULL;
8699           if (attribute_flag[8] != 0)   /* "rotate=>" */
8700             {
8701                /*
8702                  Rotate image.
8703                */
8704                rotate_image=RotateImage(composite_image,
8705                  argument_list[8].real_reference,exception);
8706                if (rotate_image == (Image *) NULL)
8707                  break;
8708             }
8709           if ((attribute_flag[7] != 0) &&
8710               (argument_list[7].integer_reference != 0)) /* tile */
8711             {
8712               ssize_t
8713                 x,
8714                 y;
8715
8716               /*
8717                 Tile the composite image.
8718               */
8719              if (attribute_flag[8] != 0)   /* "tile=>" */
8720                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8721                  "false");
8722              else
8723                (void) SetImageArtifact(composite_image,
8724                  "compose:outside-overlay","false");
8725              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8726                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8727                 {
8728                   if (attribute_flag[8] != 0) /* rotate */
8729                     (void) CompositeImage(image,rotate_image,compose,
8730                       MagickTrue,x,y,exception);
8731                   else
8732                     (void) CompositeImage(image,composite_image,compose,
8733                       MagickTrue,x,y,exception);
8734                 }
8735               if (attribute_flag[8] != 0) /* rotate */
8736                 rotate_image=DestroyImage(rotate_image);
8737               break;
8738             }
8739           /*
8740             Parameter Handling used used ONLY for normal composition.
8741           */
8742           if (attribute_flag[5] != 0) /* gravity */
8743             image->gravity=(GravityType) argument_list[5].integer_reference;
8744           if (attribute_flag[2] != 0) /* geometry offset */
8745             {
8746               SetGeometry(image,&geometry);
8747               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8748                 &geometry);
8749               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8750                 &geometry);
8751             }
8752           if (attribute_flag[3] != 0) /* x offset */
8753             geometry.x=argument_list[3].integer_reference;
8754           if (attribute_flag[4] != 0) /* y offset */
8755             geometry.y=argument_list[4].integer_reference;
8756           if (attribute_flag[10] != 0) /* mask */
8757             {
8758               if ((image->compose == DisplaceCompositeOp) ||
8759                   (image->compose == DistortCompositeOp))
8760                 {
8761                   /*
8762                     Merge Y displacement into X displacement image.
8763                   */
8764                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8765                     exception);
8766                   (void) CompositeImage(composite_image,
8767                     argument_list[10].image_reference,CopyGreenCompositeOp,
8768                     MagickTrue,0,0,exception);
8769                 }
8770               else
8771                 {
8772                   Image
8773                     *mask_image;
8774
8775                   /*
8776                     Set a blending mask for the composition.
8777                   */
8778                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8779                     MagickTrue,exception);
8780                   (void) SetImageMask(composite_image,ReadPixelMask,mask_image,
8781                     exception);
8782                   mask_image=DestroyImage(mask_image);
8783                 }
8784             }
8785           if (attribute_flag[11] != 0) /* channel */
8786             channel=(ChannelType) argument_list[11].integer_reference;
8787           /*
8788             Composite two images (normal composition).
8789           */
8790           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8791             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8792             (double) composite_image->rows,(double) geometry.x,(double)
8793             geometry.y);
8794           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8795             exception);
8796           channel_mask=SetImageChannelMask(image,channel);
8797           if (attribute_flag[8] == 0) /* no rotate */
8798             CompositeImage(image,composite_image,compose,clip_to_self,
8799               geometry.x,geometry.y,exception);
8800           else
8801             {
8802               /*
8803                 Position adjust rotated image then composite.
8804               */
8805               geometry.x-=(ssize_t) (rotate_image->columns-
8806                 composite_image->columns)/2;
8807               geometry.y-=(ssize_t) (rotate_image->rows-
8808                 composite_image->rows)/2;
8809               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8810                 geometry.y,exception);
8811               rotate_image=DestroyImage(rotate_image);
8812             }
8813           if (attribute_flag[10] != 0) /* mask */
8814             {
8815               if ((image->compose == DisplaceCompositeOp) ||
8816                   (image->compose == DistortCompositeOp))
8817                 composite_image=DestroyImage(composite_image);
8818               else
8819                 (void) SetImageMask(image,ReadPixelMask,(Image *) NULL,
8820                   exception);
8821             }
8822           (void) SetImageChannelMask(image,channel_mask);
8823           break;
8824         }
8825         case 36:  /* Contrast */
8826         {
8827           if (attribute_flag[0] == 0)
8828             argument_list[0].integer_reference=0;
8829           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8830             MagickTrue : MagickFalse,exception);
8831           break;
8832         }
8833         case 37:  /* CycleColormap */
8834         {
8835           if (attribute_flag[0] == 0)
8836             argument_list[0].integer_reference=6;
8837           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8838             exception);
8839           break;
8840         }
8841         case 38:  /* Draw */
8842         {
8843           DrawInfo
8844             *draw_info;
8845
8846           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8847             (DrawInfo *) NULL);
8848           (void) CloneString(&draw_info->primitive,"point");
8849           if (attribute_flag[0] != 0)
8850             {
8851               if (argument_list[0].integer_reference < 0)
8852                 (void) CloneString(&draw_info->primitive,
8853                   argument_list[0].string_reference);
8854               else
8855                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8856                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8857             }
8858           if (attribute_flag[1] != 0)
8859             {
8860               if (LocaleCompare(draw_info->primitive,"path") == 0)
8861                 {
8862                   (void) ConcatenateString(&draw_info->primitive," '");
8863                   ConcatenateString(&draw_info->primitive,
8864                     argument_list[1].string_reference);
8865                   (void) ConcatenateString(&draw_info->primitive,"'");
8866                 }
8867               else
8868                 {
8869                   (void) ConcatenateString(&draw_info->primitive," ");
8870                   ConcatenateString(&draw_info->primitive,
8871                     argument_list[1].string_reference);
8872                 }
8873             }
8874           if (attribute_flag[2] != 0)
8875             {
8876               (void) ConcatenateString(&draw_info->primitive," ");
8877               (void) ConcatenateString(&draw_info->primitive,
8878                 CommandOptionToMnemonic(MagickMethodOptions,
8879                 argument_list[2].integer_reference));
8880             }
8881           if (attribute_flag[3] != 0)
8882             {
8883               (void) QueryColorCompliance(argument_list[3].string_reference,
8884                 AllCompliance,&draw_info->stroke,exception);
8885               if (argument_list[3].image_reference != (Image *) NULL)
8886                 draw_info->stroke_pattern=CloneImage(
8887                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8888             }
8889           if (attribute_flag[4] != 0)
8890             {
8891               (void) QueryColorCompliance(argument_list[4].string_reference,
8892                 AllCompliance,&draw_info->fill,exception);
8893               if (argument_list[4].image_reference != (Image *) NULL)
8894                 draw_info->fill_pattern=CloneImage(
8895                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8896             }
8897           if (attribute_flag[5] != 0)
8898             draw_info->stroke_width=argument_list[5].real_reference;
8899           if (attribute_flag[6] != 0)
8900             (void) CloneString(&draw_info->font,
8901               argument_list[6].string_reference);
8902           if (attribute_flag[7] != 0)
8903             (void) QueryColorCompliance(argument_list[7].string_reference,
8904               AllCompliance,&draw_info->border_color,exception);
8905           if (attribute_flag[8] != 0)
8906             draw_info->affine.tx=argument_list[8].real_reference;
8907           if (attribute_flag[9] != 0)
8908             draw_info->affine.ty=argument_list[9].real_reference;
8909           if (attribute_flag[20] != 0)
8910             {
8911               AV
8912                 *av;
8913
8914               av=(AV *) argument_list[20].array_reference;
8915               if ((av_len(av) != 3) && (av_len(av) != 5))
8916                 {
8917                   ThrowPerlException(exception,OptionError,
8918                     "affine matrix must have 4 or 6 elements",PackageName);
8919                   goto PerlException;
8920                 }
8921               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8922               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8923               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8924               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8925               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8926                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8927                 {
8928                   ThrowPerlException(exception,OptionError,
8929                     "affine matrix is singular",PackageName);
8930                    goto PerlException;
8931                 }
8932               if (av_len(av) == 5)
8933                 {
8934                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8935                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8936                 }
8937             }
8938           for (j=10; j < 15; j++)
8939           {
8940             if (attribute_flag[j] == 0)
8941               continue;
8942             value=argument_list[j].string_reference;
8943             angle=argument_list[j].real_reference;
8944             current=draw_info->affine;
8945             GetAffineMatrix(&affine);
8946             switch (j)
8947             {
8948               case 10:
8949               {
8950                 /*
8951                   Translate.
8952                 */
8953                 flags=ParseGeometry(value,&geometry_info);
8954                 affine.tx=geometry_info.xi;
8955                 affine.ty=geometry_info.psi;
8956                 if ((flags & PsiValue) == 0)
8957                   affine.ty=affine.tx;
8958                 break;
8959               }
8960               case 11:
8961               {
8962                 /*
8963                   Scale.
8964                 */
8965                 flags=ParseGeometry(value,&geometry_info);
8966                 affine.sx=geometry_info.rho;
8967                 affine.sy=geometry_info.sigma;
8968                 if ((flags & SigmaValue) == 0)
8969                   affine.sy=affine.sx;
8970                 break;
8971               }
8972               case 12:
8973               {
8974                 /*
8975                   Rotate.
8976                 */
8977                 if (angle == 0.0)
8978                   break;
8979                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8980                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8981                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8982                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8983                 break;
8984               }
8985               case 13:
8986               {
8987                 /*
8988                   SkewX.
8989                 */
8990                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8991                 break;
8992               }
8993               case 14:
8994               {
8995                 /*
8996                   SkewY.
8997                 */
8998                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8999                 break;
9000               }
9001             }
9002             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9003             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9004             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9005             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9006             draw_info->affine.tx=
9007               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9008             draw_info->affine.ty=
9009               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9010           }
9011           if (attribute_flag[15] != 0)
9012             draw_info->fill_pattern=CloneImage(
9013               argument_list[15].image_reference,0,0,MagickTrue,exception);
9014           if (attribute_flag[16] != 0)
9015             draw_info->pointsize=argument_list[16].real_reference;
9016           if (attribute_flag[17] != 0)
9017             {
9018               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
9019                 ? MagickTrue : MagickFalse;
9020               draw_info->text_antialias=draw_info->stroke_antialias;
9021             }
9022           if (attribute_flag[18] != 0)
9023             (void) CloneString(&draw_info->density,
9024               argument_list[18].string_reference);
9025           if (attribute_flag[19] != 0)
9026             draw_info->stroke_width=argument_list[19].real_reference;
9027           if (attribute_flag[21] != 0)
9028             draw_info->dash_offset=argument_list[21].real_reference;
9029           if (attribute_flag[22] != 0)
9030             {
9031               AV
9032                 *av;
9033
9034               av=(AV *) argument_list[22].array_reference;
9035               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
9036                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
9037               if (draw_info->dash_pattern != (double *) NULL)
9038                 {
9039                   for (i=0; i <= av_len(av); i++)
9040                     draw_info->dash_pattern[i]=(double)
9041                       SvNV(*(av_fetch(av,i,0)));
9042                   draw_info->dash_pattern[i]=0.0;
9043                 }
9044             }
9045           if (attribute_flag[23] != 0)
9046             image->interpolate=(PixelInterpolateMethod)
9047               argument_list[23].integer_reference;
9048           if ((attribute_flag[24] != 0) &&
9049               (draw_info->fill_pattern != (Image *) NULL))
9050             flags=ParsePageGeometry(draw_info->fill_pattern,
9051               argument_list[24].string_reference,
9052               &draw_info->fill_pattern->tile_offset,exception);
9053           if (attribute_flag[25] != 0)
9054             {
9055               (void) ConcatenateString(&draw_info->primitive," '");
9056               (void) ConcatenateString(&draw_info->primitive,
9057                 argument_list[25].string_reference);
9058               (void) ConcatenateString(&draw_info->primitive,"'");
9059             }
9060           if (attribute_flag[26] != 0)
9061             draw_info->fill_pattern=CloneImage(
9062               argument_list[26].image_reference,0,0,MagickTrue,exception);
9063           if (attribute_flag[27] != 0)
9064             draw_info->stroke_pattern=CloneImage(
9065               argument_list[27].image_reference,0,0,MagickTrue,exception);
9066           if (attribute_flag[28] != 0)
9067             (void) CloneString(&draw_info->primitive,
9068               argument_list[28].string_reference);
9069           if (attribute_flag[29] != 0)
9070             draw_info->kerning=argument_list[29].real_reference;
9071           if (attribute_flag[30] != 0)
9072             draw_info->interline_spacing=argument_list[30].real_reference;
9073           if (attribute_flag[31] != 0)
9074             draw_info->interword_spacing=argument_list[31].real_reference;
9075           if (attribute_flag[32] != 0)
9076             draw_info->direction=(DirectionType)
9077               argument_list[32].integer_reference;
9078           DrawImage(image,draw_info,exception);
9079           draw_info=DestroyDrawInfo(draw_info);
9080           break;
9081         }
9082         case 39:  /* Equalize */
9083         {
9084           if (attribute_flag[0] != 0)
9085             channel=(ChannelType) argument_list[0].integer_reference;
9086           channel_mask=SetImageChannelMask(image,channel);
9087           EqualizeImage(image,exception);
9088           (void) SetImageChannelMask(image,channel_mask);
9089           break;
9090         }
9091         case 40:  /* Gamma */
9092         {
9093           if (attribute_flag[1] != 0)
9094             channel=(ChannelType) argument_list[1].integer_reference;
9095           if (attribute_flag[2] == 0)
9096             argument_list[2].real_reference=1.0;
9097           if (attribute_flag[3] == 0)
9098             argument_list[3].real_reference=1.0;
9099           if (attribute_flag[4] == 0)
9100             argument_list[4].real_reference=1.0;
9101           if (attribute_flag[0] == 0)
9102             {
9103               (void) FormatLocaleString(message,MagickPathExtent,
9104                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9105                 (double) argument_list[3].real_reference,
9106                 (double) argument_list[4].real_reference);
9107               argument_list[0].string_reference=message;
9108             }
9109           (void) GammaImage(image,StringToDouble(
9110             argument_list[0].string_reference,(char **) NULL),exception);
9111           break;
9112         }
9113         case 41:  /* Map */
9114         {
9115           QuantizeInfo
9116             *quantize_info;
9117
9118           if (attribute_flag[0] == 0)
9119             {
9120               ThrowPerlException(exception,OptionError,"MapImageRequired",
9121                 PackageName);
9122               goto PerlException;
9123             }
9124           quantize_info=AcquireQuantizeInfo(info->image_info);
9125           if (attribute_flag[1] != 0)
9126             quantize_info->dither_method=(DitherMethod)
9127               argument_list[1].integer_reference;
9128           (void) RemapImages(quantize_info,image,
9129             argument_list[0].image_reference,exception);
9130           quantize_info=DestroyQuantizeInfo(quantize_info);
9131           break;
9132         }
9133         case 42:  /* MatteFloodfill */
9134         {
9135           DrawInfo
9136             *draw_info;
9137
9138           MagickBooleanType
9139             invert;
9140
9141           PixelInfo
9142             target;
9143
9144           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9145             (DrawInfo *) NULL);
9146           if (attribute_flag[0] != 0)
9147             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9148               &geometry,exception);
9149           if (attribute_flag[1] != 0)
9150             geometry.x=argument_list[1].integer_reference;
9151           if (attribute_flag[2] != 0)
9152             geometry.y=argument_list[2].integer_reference;
9153           if (image->alpha_trait == UndefinedPixelTrait)
9154             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9155           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9156             geometry.x,geometry.y,&target,exception);
9157           if (attribute_flag[4] != 0)
9158             QueryColorCompliance(argument_list[4].string_reference,
9159               AllCompliance,&target,exception);
9160           if (attribute_flag[3] != 0)
9161             target.alpha=StringToDoubleInterval(
9162               argument_list[3].string_reference,(double) (double) QuantumRange+
9163               1.0);
9164           if (attribute_flag[5] != 0)
9165             image->fuzz=StringToDoubleInterval(
9166               argument_list[5].string_reference,(double) QuantumRange+1.0);
9167           invert=MagickFalse;
9168           if (attribute_flag[6] != 0)
9169             invert=(MagickBooleanType) argument_list[6].integer_reference;
9170           channel_mask=SetImageChannelMask(image,AlphaChannel);
9171           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9172             geometry.y,invert,exception);
9173           (void) SetImageChannelMask(image,channel_mask);
9174           draw_info=DestroyDrawInfo(draw_info);
9175           break;
9176         }
9177         case 43:  /* Modulate */
9178         {
9179           char
9180             modulate[MagickPathExtent];
9181
9182           geometry_info.rho=100.0;
9183           geometry_info.sigma=100.0;
9184           geometry_info.xi=100.0;
9185           if (attribute_flag[0] != 0)
9186             (void)ParseGeometry(argument_list[0].string_reference,
9187               &geometry_info);
9188           if (attribute_flag[1] != 0)
9189             geometry_info.xi=argument_list[1].real_reference;
9190           if (attribute_flag[2] != 0)
9191             geometry_info.sigma=argument_list[2].real_reference;
9192           if (attribute_flag[3] != 0)
9193             {
9194               geometry_info.sigma=argument_list[3].real_reference;
9195               SetImageArtifact(image,"modulate:colorspace","HWB");
9196             }
9197           if (attribute_flag[4] != 0)
9198             {
9199               geometry_info.rho=argument_list[4].real_reference;
9200               SetImageArtifact(image,"modulate:colorspace","HSB");
9201             }
9202           if (attribute_flag[5] != 0)
9203             {
9204               geometry_info.sigma=argument_list[5].real_reference;
9205               SetImageArtifact(image,"modulate:colorspace","HSL");
9206             }
9207           if (attribute_flag[6] != 0)
9208             {
9209               geometry_info.rho=argument_list[6].real_reference;
9210               SetImageArtifact(image,"modulate:colorspace","HWB");
9211             }
9212           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9213             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9214           (void) ModulateImage(image,modulate,exception);
9215           break;
9216         }
9217         case 44:  /* Negate */
9218         {
9219           if (attribute_flag[0] == 0)
9220             argument_list[0].integer_reference=0;
9221           if (attribute_flag[1] != 0)
9222             channel=(ChannelType) argument_list[1].integer_reference;
9223           channel_mask=SetImageChannelMask(image,channel);
9224           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9225             MagickTrue : MagickFalse,exception);
9226           (void) SetImageChannelMask(image,channel_mask);
9227           break;
9228         }
9229         case 45:  /* Normalize */
9230         {
9231           if (attribute_flag[0] != 0)
9232             channel=(ChannelType) argument_list[0].integer_reference;
9233           channel_mask=SetImageChannelMask(image,channel);
9234           NormalizeImage(image,exception);
9235           (void) SetImageChannelMask(image,channel_mask);
9236           break;
9237         }
9238         case 46:  /* NumberColors */
9239           break;
9240         case 47:  /* Opaque */
9241         {
9242           MagickBooleanType
9243             invert;
9244
9245           PixelInfo
9246             fill_color,
9247             target;
9248
9249           (void) QueryColorCompliance("none",AllCompliance,&target,
9250              exception);
9251           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9252             exception);
9253           if (attribute_flag[0] != 0)
9254             (void) QueryColorCompliance(argument_list[0].string_reference,
9255               AllCompliance,&target,exception);
9256           if (attribute_flag[1] != 0)
9257             (void) QueryColorCompliance(argument_list[1].string_reference,
9258               AllCompliance,&fill_color,exception);
9259           if (attribute_flag[2] != 0)
9260             image->fuzz=StringToDoubleInterval(
9261               argument_list[2].string_reference,(double) QuantumRange+1.0);
9262           if (attribute_flag[3] != 0)
9263             channel=(ChannelType) argument_list[3].integer_reference;
9264           invert=MagickFalse;
9265           if (attribute_flag[4] != 0)
9266             invert=(MagickBooleanType) argument_list[4].integer_reference;
9267           channel_mask=SetImageChannelMask(image,channel);
9268           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9269           (void) SetImageChannelMask(image,channel_mask);
9270           break;
9271         }
9272         case 48:  /* Quantize */
9273         {
9274           QuantizeInfo
9275             *quantize_info;
9276
9277           quantize_info=AcquireQuantizeInfo(info->image_info);
9278           if (attribute_flag[0] != 0)
9279             quantize_info->number_colors=(size_t)
9280               argument_list[0].integer_reference;
9281           if (attribute_flag[1] != 0)
9282             quantize_info->tree_depth=(size_t)
9283               argument_list[1].integer_reference;
9284           if (attribute_flag[2] != 0)
9285             quantize_info->colorspace=(ColorspaceType)
9286               argument_list[2].integer_reference;
9287           if (attribute_flag[3] != 0)
9288             quantize_info->dither_method=(DitherMethod)
9289               argument_list[3].integer_reference;
9290           if (attribute_flag[4] != 0)
9291             quantize_info->measure_error=
9292               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9293           if (attribute_flag[6] != 0)
9294             (void) QueryColorCompliance(argument_list[6].string_reference,
9295               AllCompliance,&image->transparent_color,exception);
9296           if (attribute_flag[7] != 0)
9297             quantize_info->dither_method=(DitherMethod)
9298               argument_list[7].integer_reference;
9299           if (attribute_flag[5] && argument_list[5].integer_reference)
9300             (void) QuantizeImages(quantize_info,image,exception);
9301           else
9302             if ((image->storage_class == DirectClass) ||
9303                (image->colors > quantize_info->number_colors) ||
9304                (quantize_info->colorspace == GRAYColorspace))
9305              (void) QuantizeImage(quantize_info,image,exception);
9306            else
9307              CompressImageColormap(image,exception);
9308           quantize_info=DestroyQuantizeInfo(quantize_info);
9309           break;
9310         }
9311         case 49:  /* Raise */
9312         {
9313           if (attribute_flag[0] != 0)
9314             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9315               &geometry,exception);
9316           if (attribute_flag[1] != 0)
9317             geometry.width=argument_list[1].integer_reference;
9318           if (attribute_flag[2] != 0)
9319             geometry.height=argument_list[2].integer_reference;
9320           if (attribute_flag[3] == 0)
9321             argument_list[3].integer_reference=1;
9322           (void) RaiseImage(image,&geometry,
9323             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9324             exception);
9325           break;
9326         }
9327         case 50:  /* Segment */
9328         {
9329           ColorspaceType
9330             colorspace;
9331
9332           double
9333             cluster_threshold,
9334             smoothing_threshold;
9335
9336           MagickBooleanType
9337             verbose;
9338
9339           cluster_threshold=1.0;
9340           smoothing_threshold=1.5;
9341           colorspace=sRGBColorspace;
9342           verbose=MagickFalse;
9343           if (attribute_flag[0] != 0)
9344             {
9345               flags=ParseGeometry(argument_list[0].string_reference,
9346                 &geometry_info);
9347               cluster_threshold=geometry_info.rho;
9348               if (flags & SigmaValue)
9349                 smoothing_threshold=geometry_info.sigma;
9350             }
9351           if (attribute_flag[1] != 0)
9352             cluster_threshold=argument_list[1].real_reference;
9353           if (attribute_flag[2] != 0)
9354             smoothing_threshold=argument_list[2].real_reference;
9355           if (attribute_flag[3] != 0)
9356             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9357           if (attribute_flag[4] != 0)
9358             verbose=argument_list[4].integer_reference != 0 ?
9359               MagickTrue : MagickFalse;
9360           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9361             smoothing_threshold,exception);
9362           break;
9363         }
9364         case 51:  /* Signature */
9365         {
9366           (void) SignatureImage(image,exception);
9367           break;
9368         }
9369         case 52:  /* Solarize */
9370         {
9371           geometry_info.rho=QuantumRange/2.0;
9372           if (attribute_flag[0] != 0)
9373             flags=ParseGeometry(argument_list[0].string_reference,
9374               &geometry_info);
9375           if (attribute_flag[1] != 0)
9376             geometry_info.rho=StringToDoubleInterval(
9377               argument_list[1].string_reference,(double) QuantumRange+1.0);
9378           (void) SolarizeImage(image,geometry_info.rho,exception);
9379           break;
9380         }
9381         case 53:  /* Sync */
9382         {
9383           (void) SyncImage(image,exception);
9384           break;
9385         }
9386         case 54:  /* Texture */
9387         {
9388           if (attribute_flag[0] == 0)
9389             break;
9390           TextureImage(image,argument_list[0].image_reference,exception);
9391           break;
9392         }
9393         case 55:  /* Evalute */
9394         {
9395           MagickEvaluateOperator
9396             op;
9397
9398           op=SetEvaluateOperator;
9399           if (attribute_flag[0] == MagickFalse)
9400             argument_list[0].real_reference=0.0;
9401           if (attribute_flag[1] != MagickFalse)
9402             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9403           if (attribute_flag[2] != MagickFalse)
9404             channel=(ChannelType) argument_list[2].integer_reference;
9405           channel_mask=SetImageChannelMask(image,channel);
9406           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9407             exception);
9408           (void) SetImageChannelMask(image,channel_mask);
9409           break;
9410         }
9411         case 56:  /* Transparent */
9412         {
9413           double
9414             opacity;
9415
9416           MagickBooleanType
9417             invert;
9418
9419           PixelInfo
9420             target;
9421
9422           (void) QueryColorCompliance("none",AllCompliance,&target,
9423             exception);
9424           if (attribute_flag[0] != 0)
9425             (void) QueryColorCompliance(argument_list[0].string_reference,
9426               AllCompliance,&target,exception);
9427           opacity=TransparentAlpha;
9428           if (attribute_flag[1] != 0)
9429             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9430               (double) QuantumRange+1.0);
9431           if (attribute_flag[2] != 0)
9432             image->fuzz=StringToDoubleInterval(
9433               argument_list[2].string_reference,(double) QuantumRange+1.0);
9434           if (attribute_flag[3] == 0)
9435             argument_list[3].integer_reference=0;
9436           invert=MagickFalse;
9437           if (attribute_flag[3] != 0)
9438             invert=(MagickBooleanType) argument_list[3].integer_reference;
9439           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9440             invert,exception);
9441           break;
9442         }
9443         case 57:  /* Threshold */
9444         {
9445           double
9446             threshold;
9447
9448           if (attribute_flag[0] == 0)
9449             argument_list[0].string_reference="50%";
9450           if (attribute_flag[1] != 0)
9451             channel=(ChannelType) argument_list[1].integer_reference;
9452           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9453             (double) QuantumRange+1.0);
9454           channel_mask=SetImageChannelMask(image,channel);
9455           (void) BilevelImage(image,threshold,exception);
9456           (void) SetImageChannelMask(image,channel_mask);
9457           break;
9458         }
9459         case 58:  /* Charcoal */
9460         {
9461           if (attribute_flag[0] != 0)
9462             {
9463               flags=ParseGeometry(argument_list[0].string_reference,
9464                 &geometry_info);
9465               if ((flags & SigmaValue) == 0)
9466                 geometry_info.sigma=1.0;
9467             }
9468           if (attribute_flag[1] != 0)
9469             geometry_info.rho=argument_list[1].real_reference;
9470           if (attribute_flag[2] != 0)
9471             geometry_info.sigma=argument_list[2].real_reference;
9472           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9473             exception);
9474           break;
9475         }
9476         case 59:  /* Trim */
9477         {
9478           if (attribute_flag[0] != 0)
9479             image->fuzz=StringToDoubleInterval(
9480               argument_list[0].string_reference,(double) QuantumRange+1.0);
9481           image=TrimImage(image,exception);
9482           break;
9483         }
9484         case 60:  /* Wave */
9485         {
9486           PixelInterpolateMethod
9487             method;
9488
9489           if (attribute_flag[0] != 0)
9490             {
9491               flags=ParseGeometry(argument_list[0].string_reference,
9492                 &geometry_info);
9493               if ((flags & SigmaValue) == 0)
9494                 geometry_info.sigma=1.0;
9495             }
9496           if (attribute_flag[1] != 0)
9497             geometry_info.rho=argument_list[1].real_reference;
9498           if (attribute_flag[2] != 0)
9499             geometry_info.sigma=argument_list[2].real_reference;
9500           method=UndefinedInterpolatePixel;
9501           if (attribute_flag[3] != 0)
9502             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9503           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9504             method,exception);
9505           break;
9506         }
9507         case 61:  /* Separate */
9508         {
9509           if (attribute_flag[0] != 0)
9510             channel=(ChannelType) argument_list[0].integer_reference;
9511           image=SeparateImage(image,channel,exception);
9512           break;
9513         }
9514         case 63:  /* Stereo */
9515         {
9516           if (attribute_flag[0] == 0)
9517             {
9518               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9519                 PackageName);
9520               goto PerlException;
9521             }
9522           if (attribute_flag[1] != 0)
9523             geometry.x=argument_list[1].integer_reference;
9524           if (attribute_flag[2] != 0)
9525             geometry.y=argument_list[2].integer_reference;
9526           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9527             geometry.x,geometry.y,exception);
9528           break;
9529         }
9530         case 64:  /* Stegano */
9531         {
9532           if (attribute_flag[0] == 0)
9533             {
9534               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9535                 PackageName);
9536               goto PerlException;
9537             }
9538           if (attribute_flag[1] == 0)
9539             argument_list[1].integer_reference=0;
9540           image->offset=argument_list[1].integer_reference;
9541           image=SteganoImage(image,argument_list[0].image_reference,exception);
9542           break;
9543         }
9544         case 65:  /* Deconstruct */
9545         {
9546           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9547           break;
9548         }
9549         case 66:  /* GaussianBlur */
9550         {
9551           if (attribute_flag[0] != 0)
9552             {
9553               flags=ParseGeometry(argument_list[0].string_reference,
9554                 &geometry_info);
9555               if ((flags & SigmaValue) == 0)
9556                 geometry_info.sigma=1.0;
9557             }
9558           if (attribute_flag[1] != 0)
9559             geometry_info.rho=argument_list[1].real_reference;
9560           if (attribute_flag[2] != 0)
9561             geometry_info.sigma=argument_list[2].real_reference;
9562           if (attribute_flag[3] != 0)
9563             channel=(ChannelType) argument_list[3].integer_reference;
9564           channel_mask=SetImageChannelMask(image,channel);
9565           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9566             exception);
9567           if (image != (Image *) NULL)
9568             (void) SetImageChannelMask(image,channel_mask);
9569           break;
9570         }
9571         case 67:  /* Convolve */
9572         {
9573           KernelInfo
9574             *kernel;
9575
9576           kernel=(KernelInfo *) NULL;
9577           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9578             break;
9579           if (attribute_flag[0] != 0)
9580             {
9581               AV
9582                 *av;
9583
9584               size_t
9585                 order;
9586
9587               kernel=AcquireKernelInfo((const char *) NULL,exception);
9588               if (kernel == (KernelInfo *) NULL)
9589                 break;
9590               av=(AV *) argument_list[0].array_reference;
9591               order=(size_t) sqrt(av_len(av)+1);
9592               kernel->width=order;
9593               kernel->height=order;
9594               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9595                 order*sizeof(*kernel->values));
9596               if (kernel->values == (MagickRealType *) NULL)
9597                 {
9598                   kernel=DestroyKernelInfo(kernel);
9599                   ThrowPerlException(exception,ResourceLimitFatalError,
9600                     "MemoryAllocationFailed",PackageName);
9601                   goto PerlException;
9602                 }
9603               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9604                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9605               for ( ; j < (ssize_t) (order*order); j++)
9606                 kernel->values[j]=0.0;
9607             }
9608           if (attribute_flag[1] != 0)
9609             channel=(ChannelType) argument_list[1].integer_reference;
9610           if (attribute_flag[2] != 0)
9611             SetImageArtifact(image,"filter:blur",
9612               argument_list[2].string_reference);
9613           if (attribute_flag[3] != 0)
9614             {
9615               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9616                 exception);
9617               if (kernel == (KernelInfo *) NULL)
9618                 break;
9619             }
9620           channel_mask=SetImageChannelMask(image,channel);
9621           image=ConvolveImage(image,kernel,exception);
9622           if (image != (Image *) NULL)
9623             (void) SetImageChannelMask(image,channel_mask);
9624           kernel=DestroyKernelInfo(kernel);
9625           break;
9626         }
9627         case 68:  /* Profile */
9628         {
9629           const char
9630             *name;
9631
9632           Image
9633             *profile_image;
9634
9635           ImageInfo
9636             *profile_info;
9637
9638           StringInfo
9639             *profile;
9640
9641           name="*";
9642           if (attribute_flag[0] != 0)
9643             name=argument_list[0].string_reference;
9644           if (attribute_flag[2] != 0)
9645             image->rendering_intent=(RenderingIntent)
9646               argument_list[2].integer_reference;
9647           if (attribute_flag[3] != 0)
9648             image->black_point_compensation=
9649               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9650           if (attribute_flag[1] != 0)
9651             {
9652               if (argument_list[1].length == 0)
9653                 {
9654                   /*
9655                     Remove a profile from the image.
9656                   */
9657                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9658                     exception);
9659                   break;
9660                 }
9661               /*
9662                 Associate user supplied profile with the image.
9663               */
9664               profile=AcquireStringInfo(argument_list[1].length);
9665               SetStringInfoDatum(profile,(const unsigned char *)
9666                 argument_list[1].string_reference);
9667               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9668                 (size_t) GetStringInfoLength(profile),exception);
9669               profile=DestroyStringInfo(profile);
9670               break;
9671             }
9672           /*
9673             Associate a profile with the image.
9674           */
9675           profile_info=CloneImageInfo(info ? info->image_info :
9676             (ImageInfo *) NULL);
9677           profile_image=ReadImages(profile_info,name,exception);
9678           if (profile_image == (Image *) NULL)
9679             break;
9680           ResetImageProfileIterator(profile_image);
9681           name=GetNextImageProfile(profile_image);
9682           while (name != (const char *) NULL)
9683           {
9684             const StringInfo
9685               *profile;
9686
9687             profile=GetImageProfile(profile_image,name);
9688             if (profile != (const StringInfo *) NULL)
9689               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9690                 (size_t) GetStringInfoLength(profile),exception);
9691             name=GetNextImageProfile(profile_image);
9692           }
9693           profile_image=DestroyImage(profile_image);
9694           profile_info=DestroyImageInfo(profile_info);
9695           break;
9696         }
9697         case 69:  /* UnsharpMask */
9698         {
9699           if (attribute_flag[0] != 0)
9700             {
9701               flags=ParseGeometry(argument_list[0].string_reference,
9702                 &geometry_info);
9703               if ((flags & SigmaValue) == 0)
9704                 geometry_info.sigma=1.0;
9705               if ((flags & XiValue) == 0)
9706                 geometry_info.xi=1.0;
9707               if ((flags & PsiValue) == 0)
9708                 geometry_info.psi=0.5;
9709             }
9710           if (attribute_flag[1] != 0)
9711             geometry_info.rho=argument_list[1].real_reference;
9712           if (attribute_flag[2] != 0)
9713             geometry_info.sigma=argument_list[2].real_reference;
9714           if (attribute_flag[3] != 0)
9715             geometry_info.xi=argument_list[3].real_reference;
9716           if (attribute_flag[4] != 0)
9717             geometry_info.psi=argument_list[4].real_reference;
9718           if (attribute_flag[5] != 0)
9719             channel=(ChannelType) argument_list[5].integer_reference;
9720           channel_mask=SetImageChannelMask(image,channel);
9721           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9722             geometry_info.xi,geometry_info.psi,exception);
9723           if (image != (Image *) NULL)
9724             (void) SetImageChannelMask(image,channel_mask);
9725           break;
9726         }
9727         case 70:  /* MotionBlur */
9728         {
9729           if (attribute_flag[0] != 0)
9730             {
9731               flags=ParseGeometry(argument_list[0].string_reference,
9732                 &geometry_info);
9733               if ((flags & SigmaValue) == 0)
9734                 geometry_info.sigma=1.0;
9735               if ((flags & XiValue) == 0)
9736                 geometry_info.xi=1.0;
9737             }
9738           if (attribute_flag[1] != 0)
9739             geometry_info.rho=argument_list[1].real_reference;
9740           if (attribute_flag[2] != 0)
9741             geometry_info.sigma=argument_list[2].real_reference;
9742           if (attribute_flag[3] != 0)
9743             geometry_info.xi=argument_list[3].real_reference;
9744           if (attribute_flag[4] != 0)
9745             channel=(ChannelType) argument_list[4].integer_reference;
9746           channel_mask=SetImageChannelMask(image,channel);
9747           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9748             geometry_info.xi,exception);
9749           if (image != (Image *) NULL)
9750             (void) SetImageChannelMask(image,channel_mask);
9751           break;
9752         }
9753         case 71:  /* OrderedDither */
9754         {
9755           if (attribute_flag[0] == 0)
9756             argument_list[0].string_reference="o8x8";
9757           if (attribute_flag[1] != 0)
9758             channel=(ChannelType) argument_list[1].integer_reference;
9759           channel_mask=SetImageChannelMask(image,channel);
9760           (void) OrderedDitherImage(image,argument_list[0].string_reference,
9761             exception);
9762           (void) SetImageChannelMask(image,channel_mask);
9763           break;
9764         }
9765         case 72:  /* Shave */
9766         {
9767           if (attribute_flag[0] != 0)
9768             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9769               &geometry,exception);
9770           if (attribute_flag[1] != 0)
9771             geometry.width=argument_list[1].integer_reference;
9772           if (attribute_flag[2] != 0)
9773             geometry.height=argument_list[2].integer_reference;
9774           image=ShaveImage(image,&geometry,exception);
9775           break;
9776         }
9777         case 73:  /* Level */
9778         {
9779           double
9780             black_point,
9781             gamma,
9782             white_point;
9783
9784           black_point=0.0;
9785           white_point=(double) image->columns*image->rows;
9786           gamma=1.0;
9787           if (attribute_flag[0] != 0)
9788             {
9789               flags=ParseGeometry(argument_list[0].string_reference,
9790                 &geometry_info);
9791               black_point=geometry_info.rho;
9792               if ((flags & SigmaValue) != 0)
9793                 white_point=geometry_info.sigma;
9794               if ((flags & XiValue) != 0)
9795                 gamma=geometry_info.xi;
9796               if ((flags & PercentValue) != 0)
9797                 {
9798                   black_point*=(double) (QuantumRange/100.0);
9799                   white_point*=(double) (QuantumRange/100.0);
9800                 }
9801               if ((flags & SigmaValue) == 0)
9802                 white_point=(double) QuantumRange-black_point;
9803             }
9804           if (attribute_flag[1] != 0)
9805             black_point=argument_list[1].real_reference;
9806           if (attribute_flag[2] != 0)
9807             white_point=argument_list[2].real_reference;
9808           if (attribute_flag[3] != 0)
9809             gamma=argument_list[3].real_reference;
9810           if (attribute_flag[4] != 0)
9811             channel=(ChannelType) argument_list[4].integer_reference;
9812           if (attribute_flag[5] != 0)
9813             {
9814               argument_list[0].real_reference=argument_list[5].real_reference;
9815               attribute_flag[0]=attribute_flag[5];
9816             }
9817           channel_mask=SetImageChannelMask(image,channel);
9818           (void) LevelImage(image,black_point,white_point,gamma,exception);
9819           (void) SetImageChannelMask(image,channel_mask);
9820           break;
9821         }
9822         case 74:  /* Clip */
9823         {
9824           if (attribute_flag[0] == 0)
9825             argument_list[0].string_reference="#1";
9826           if (attribute_flag[1] == 0)
9827             argument_list[1].integer_reference=MagickTrue;
9828           (void) ClipImagePath(image,argument_list[0].string_reference,
9829             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9830             exception);
9831           break;
9832         }
9833         case 75:  /* AffineTransform */
9834         {
9835           DrawInfo
9836             *draw_info;
9837
9838           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9839             (DrawInfo *) NULL);
9840           if (attribute_flag[0] != 0)
9841             {
9842               AV
9843                 *av;
9844
9845               av=(AV *) argument_list[0].array_reference;
9846               if ((av_len(av) != 3) && (av_len(av) != 5))
9847                 {
9848                   ThrowPerlException(exception,OptionError,
9849                     "affine matrix must have 4 or 6 elements",PackageName);
9850                   goto PerlException;
9851                 }
9852               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9853               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9854               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9855               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9856               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9857                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9858                 {
9859                   ThrowPerlException(exception,OptionError,
9860                     "affine matrix is singular",PackageName);
9861                    goto PerlException;
9862                 }
9863               if (av_len(av) == 5)
9864                 {
9865                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9866                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9867                 }
9868             }
9869           for (j=1; j < 6; j++)
9870           {
9871             if (attribute_flag[j] == 0)
9872               continue;
9873             value=argument_list[j].string_reference;
9874             angle=argument_list[j].real_reference;
9875             current=draw_info->affine;
9876             GetAffineMatrix(&affine);
9877             switch (j)
9878             {
9879               case 1:
9880               {
9881                 /*
9882                   Translate.
9883                 */
9884                 flags=ParseGeometry(value,&geometry_info);
9885                 affine.tx=geometry_info.xi;
9886                 affine.ty=geometry_info.psi;
9887                 if ((flags & PsiValue) == 0)
9888                   affine.ty=affine.tx;
9889                 break;
9890               }
9891               case 2:
9892               {
9893                 /*
9894                   Scale.
9895                 */
9896                 flags=ParseGeometry(value,&geometry_info);
9897                 affine.sx=geometry_info.rho;
9898                 affine.sy=geometry_info.sigma;
9899                 if ((flags & SigmaValue) == 0)
9900                   affine.sy=affine.sx;
9901                 break;
9902               }
9903               case 3:
9904               {
9905                 /*
9906                   Rotate.
9907                 */
9908                 if (angle == 0.0)
9909                   break;
9910                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9911                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9912                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9913                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9914                 break;
9915               }
9916               case 4:
9917               {
9918                 /*
9919                   SkewX.
9920                 */
9921                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9922                 break;
9923               }
9924               case 5:
9925               {
9926                 /*
9927                   SkewY.
9928                 */
9929                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9930                 break;
9931               }
9932             }
9933             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9934             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9935             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9936             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9937             draw_info->affine.tx=
9938               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9939             draw_info->affine.ty=
9940               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9941           }
9942           if (attribute_flag[6] != 0)
9943             image->interpolate=(PixelInterpolateMethod)
9944               argument_list[6].integer_reference;
9945           if (attribute_flag[7] != 0)
9946             QueryColorCompliance(argument_list[7].string_reference,
9947               AllCompliance,&image->background_color,exception);
9948           image=AffineTransformImage(image,&draw_info->affine,exception);
9949           draw_info=DestroyDrawInfo(draw_info);
9950           break;
9951         }
9952         case 76:  /* Difference */
9953         {
9954           if (attribute_flag[0] == 0)
9955             {
9956               ThrowPerlException(exception,OptionError,
9957                 "ReferenceImageRequired",PackageName);
9958               goto PerlException;
9959             }
9960           if (attribute_flag[1] != 0)
9961             image->fuzz=StringToDoubleInterval(
9962               argument_list[1].string_reference,(double) QuantumRange+1.0);
9963           (void) SetImageColorMetric(image,argument_list[0].image_reference,
9964             exception);
9965           break;
9966         }
9967         case 77:  /* AdaptiveThreshold */
9968         {
9969           if (attribute_flag[0] != 0)
9970             {
9971               flags=ParseGeometry(argument_list[0].string_reference,
9972                 &geometry_info);
9973               if ((flags & PercentValue) != 0)
9974                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9975             }
9976           if (attribute_flag[1] != 0)
9977             geometry_info.rho=argument_list[1].integer_reference;
9978           if (attribute_flag[2] != 0)
9979             geometry_info.sigma=argument_list[2].integer_reference;
9980           if (attribute_flag[3] != 0)
9981             geometry_info.xi=argument_list[3].integer_reference;;
9982           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9983             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9984           break;
9985         }
9986         case 78:  /* Resample */
9987         {
9988           size_t
9989             height,
9990             width;
9991
9992           if (attribute_flag[0] != 0)
9993             {
9994               flags=ParseGeometry(argument_list[0].string_reference,
9995                 &geometry_info);
9996               if ((flags & SigmaValue) == 0)
9997                 geometry_info.sigma=geometry_info.rho;
9998             }
9999           if (attribute_flag[1] != 0)
10000             geometry_info.rho=argument_list[1].real_reference;
10001           if (attribute_flag[2] != 0)
10002             geometry_info.sigma=argument_list[2].real_reference;
10003           if (attribute_flag[3] == 0)
10004             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
10005           if (attribute_flag[4] == 0)
10006             SetImageArtifact(image,"filter:support",
10007               argument_list[4].string_reference);
10008           width=(size_t) (geometry_info.rho*image->columns/
10009             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
10010           height=(size_t) (geometry_info.sigma*image->rows/
10011             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
10012           image=ResizeImage(image,width,height,(FilterType)
10013             argument_list[3].integer_reference,exception);
10014           if (image != (Image *) NULL)
10015             {
10016               image->resolution.x=geometry_info.rho;
10017               image->resolution.y=geometry_info.sigma;
10018             }
10019           break;
10020         }
10021         case 79:  /* Describe */
10022         {
10023           if (attribute_flag[0] == 0)
10024             argument_list[0].file_reference=(FILE *) NULL;
10025           if (attribute_flag[1] != 0)
10026             (void) SetImageArtifact(image,"identify:features",
10027               argument_list[1].string_reference);
10028           (void) IdentifyImage(image,argument_list[0].file_reference,
10029             MagickTrue,exception);
10030           break;
10031         }
10032         case 80:  /* BlackThreshold */
10033         {
10034           if (attribute_flag[0] == 0)
10035             argument_list[0].string_reference="50%";
10036           if (attribute_flag[2] != 0)
10037             channel=(ChannelType) argument_list[2].integer_reference;
10038           channel_mask=SetImageChannelMask(image,channel);
10039           BlackThresholdImage(image,argument_list[0].string_reference,
10040             exception);
10041           (void) SetImageChannelMask(image,channel_mask);
10042           break;
10043         }
10044         case 81:  /* WhiteThreshold */
10045         {
10046           if (attribute_flag[0] == 0)
10047             argument_list[0].string_reference="50%";
10048           if (attribute_flag[2] != 0)
10049             channel=(ChannelType) argument_list[2].integer_reference;
10050           channel_mask=SetImageChannelMask(image,channel);
10051           WhiteThresholdImage(image,argument_list[0].string_reference,
10052             exception);
10053           (void) SetImageChannelMask(image,channel_mask);
10054           break;
10055         }
10056         case 82:  /* RotationalBlur */
10057         {
10058           if (attribute_flag[0] != 0)
10059             {
10060               flags=ParseGeometry(argument_list[0].string_reference,
10061                 &geometry_info);
10062             }
10063           if (attribute_flag[1] != 0)
10064             geometry_info.rho=argument_list[1].real_reference;
10065           if (attribute_flag[2] != 0)
10066             channel=(ChannelType) argument_list[2].integer_reference;
10067           channel_mask=SetImageChannelMask(image,channel);
10068           image=RotationalBlurImage(image,geometry_info.rho,exception);
10069           if (image != (Image *) NULL)
10070             (void) SetImageChannelMask(image,channel_mask);
10071           break;
10072         }
10073         case 83:  /* Thumbnail */
10074         {
10075           if (attribute_flag[0] != 0)
10076             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10077               &geometry,exception);
10078           if (attribute_flag[1] != 0)
10079             geometry.width=argument_list[1].integer_reference;
10080           if (attribute_flag[2] != 0)
10081             geometry.height=argument_list[2].integer_reference;
10082           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10083           break;
10084         }
10085         case 84:  /* Strip */
10086         {
10087           (void) StripImage(image,exception);
10088           break;
10089         }
10090         case 85:  /* Tint */
10091         {
10092           PixelInfo
10093             tint;
10094
10095           GetPixelInfo(image,&tint);
10096           if (attribute_flag[0] != 0)
10097             (void) QueryColorCompliance(argument_list[0].string_reference,
10098               AllCompliance,&tint,exception);
10099           if (attribute_flag[1] == 0)
10100             argument_list[1].string_reference="100";
10101           image=TintImage(image,argument_list[1].string_reference,&tint,
10102             exception);
10103           break;
10104         }
10105         case 86:  /* Channel */
10106         {
10107           if (attribute_flag[0] != 0)
10108             channel=(ChannelType) argument_list[0].integer_reference;
10109           image=SeparateImage(image,channel,exception);
10110           break;
10111         }
10112         case 87:  /* Splice */
10113         {
10114           if (attribute_flag[7] != 0)
10115             image->gravity=(GravityType) argument_list[7].integer_reference;
10116           if (attribute_flag[0] != 0)
10117             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10118               &geometry,exception);
10119           if (attribute_flag[1] != 0)
10120             geometry.width=argument_list[1].integer_reference;
10121           if (attribute_flag[2] != 0)
10122             geometry.height=argument_list[2].integer_reference;
10123           if (attribute_flag[3] != 0)
10124             geometry.x=argument_list[3].integer_reference;
10125           if (attribute_flag[4] != 0)
10126             geometry.y=argument_list[4].integer_reference;
10127           if (attribute_flag[5] != 0)
10128             image->fuzz=StringToDoubleInterval(
10129               argument_list[5].string_reference,(double) QuantumRange+1.0);
10130           if (attribute_flag[6] != 0)
10131             (void) QueryColorCompliance(argument_list[6].string_reference,
10132               AllCompliance,&image->background_color,exception);
10133           image=SpliceImage(image,&geometry,exception);
10134           break;
10135         }
10136         case 88:  /* Posterize */
10137         {
10138           if (attribute_flag[0] == 0)
10139             argument_list[0].integer_reference=3;
10140           if (attribute_flag[1] == 0)
10141             argument_list[1].integer_reference=0;
10142           (void) PosterizeImage(image,argument_list[0].integer_reference,
10143             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10144             NoDitherMethod,exception);
10145           break;
10146         }
10147         case 89:  /* Shadow */
10148         {
10149           if (attribute_flag[0] != 0)
10150             {
10151               flags=ParseGeometry(argument_list[0].string_reference,
10152                 &geometry_info);
10153               if ((flags & SigmaValue) == 0)
10154                 geometry_info.sigma=1.0;
10155               if ((flags & XiValue) == 0)
10156                 geometry_info.xi=4.0;
10157               if ((flags & PsiValue) == 0)
10158                 geometry_info.psi=4.0;
10159             }
10160           if (attribute_flag[1] != 0)
10161             geometry_info.rho=argument_list[1].real_reference;
10162           if (attribute_flag[2] != 0)
10163             geometry_info.sigma=argument_list[2].real_reference;
10164           if (attribute_flag[3] != 0)
10165             geometry_info.xi=argument_list[3].integer_reference;
10166           if (attribute_flag[4] != 0)
10167             geometry_info.psi=argument_list[4].integer_reference;
10168           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10169             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10170             ceil(geometry_info.psi-0.5),exception);
10171           break;
10172         }
10173         case 90:  /* Identify */
10174         {
10175           if (attribute_flag[0] == 0)
10176             argument_list[0].file_reference=(FILE *) NULL;
10177           if (attribute_flag[1] != 0)
10178             (void) SetImageArtifact(image,"identify:features",
10179               argument_list[1].string_reference);
10180           if ((attribute_flag[2] != 0) &&
10181               (argument_list[2].integer_reference != 0))
10182             (void) SetImageArtifact(image,"identify:unique","true");
10183           (void) IdentifyImage(image,argument_list[0].file_reference,
10184             MagickTrue,exception);
10185           break;
10186         }
10187         case 91:  /* SepiaTone */
10188         {
10189           if (attribute_flag[0] == 0)
10190             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10191           image=SepiaToneImage(image,argument_list[0].real_reference,
10192             exception);
10193           break;
10194         }
10195         case 92:  /* SigmoidalContrast */
10196         {
10197           MagickBooleanType
10198             sharpen;
10199
10200           if (attribute_flag[0] != 0)
10201             {
10202               flags=ParseGeometry(argument_list[0].string_reference,
10203                 &geometry_info);
10204               if ((flags & SigmaValue) == 0)
10205                 geometry_info.sigma=QuantumRange/2.0;
10206               if ((flags & PercentValue) != 0)
10207                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10208             }
10209           if (attribute_flag[1] != 0)
10210             geometry_info.rho=argument_list[1].real_reference;
10211           if (attribute_flag[2] != 0)
10212             geometry_info.sigma=argument_list[2].real_reference;
10213           if (attribute_flag[3] != 0)
10214             channel=(ChannelType) argument_list[3].integer_reference;
10215           sharpen=MagickTrue;
10216           if (attribute_flag[4] != 0)
10217             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10218               MagickFalse;
10219           channel_mask=SetImageChannelMask(image,channel);
10220           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10221             geometry_info.sigma,exception);
10222           (void) SetImageChannelMask(image,channel_mask);
10223           break;
10224         }
10225         case 93:  /* Extent */
10226         {
10227           if (attribute_flag[7] != 0)
10228             image->gravity=(GravityType) argument_list[7].integer_reference;
10229           if (attribute_flag[0] != 0)
10230             {
10231               int
10232                 flags;
10233
10234               flags=ParseGravityGeometry(image,
10235                 argument_list[0].string_reference,&geometry,exception);
10236               (void) flags;
10237               if (geometry.width == 0)
10238                 geometry.width=image->columns;
10239               if (geometry.height == 0)
10240                 geometry.height=image->rows;
10241             }
10242           if (attribute_flag[1] != 0)
10243             geometry.width=argument_list[1].integer_reference;
10244           if (attribute_flag[2] != 0)
10245             geometry.height=argument_list[2].integer_reference;
10246           if (attribute_flag[3] != 0)
10247             geometry.x=argument_list[3].integer_reference;
10248           if (attribute_flag[4] != 0)
10249             geometry.y=argument_list[4].integer_reference;
10250           if (attribute_flag[5] != 0)
10251             image->fuzz=StringToDoubleInterval(
10252               argument_list[5].string_reference,(double) QuantumRange+1.0);
10253           if (attribute_flag[6] != 0)
10254             (void) QueryColorCompliance(argument_list[6].string_reference,
10255               AllCompliance,&image->background_color,exception);
10256           image=ExtentImage(image,&geometry,exception);
10257           break;
10258         }
10259         case 94:  /* Vignette */
10260         {
10261           if (attribute_flag[0] != 0)
10262             {
10263               flags=ParseGeometry(argument_list[0].string_reference,
10264                 &geometry_info);
10265               if ((flags & SigmaValue) == 0)
10266                 geometry_info.sigma=1.0;
10267               if ((flags & XiValue) == 0)
10268                 geometry_info.xi=0.1*image->columns;
10269               if ((flags & PsiValue) == 0)
10270                 geometry_info.psi=0.1*image->rows;
10271             }
10272           if (attribute_flag[1] != 0)
10273             geometry_info.rho=argument_list[1].real_reference;
10274           if (attribute_flag[2] != 0)
10275             geometry_info.sigma=argument_list[2].real_reference;
10276           if (attribute_flag[3] != 0)
10277             geometry_info.xi=argument_list[3].integer_reference;
10278           if (attribute_flag[4] != 0)
10279             geometry_info.psi=argument_list[4].integer_reference;
10280           if (attribute_flag[5] != 0)
10281             (void) QueryColorCompliance(argument_list[5].string_reference,
10282               AllCompliance,&image->background_color,exception);
10283           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10284             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10285             ceil(geometry_info.psi-0.5),exception);
10286           break;
10287         }
10288         case 95:  /* ContrastStretch */
10289         {
10290           double
10291             black_point,
10292             white_point;
10293
10294           black_point=0.0;
10295           white_point=(double) image->columns*image->rows;
10296           if (attribute_flag[0] != 0)
10297             {
10298               flags=ParseGeometry(argument_list[0].string_reference,
10299                 &geometry_info);
10300               black_point=geometry_info.rho;
10301               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10302                 black_point;
10303               if ((flags & PercentValue) != 0)
10304                 {
10305                   black_point*=(double) image->columns*image->rows/100.0;
10306                   white_point*=(double) image->columns*image->rows/100.0;
10307                 }
10308               white_point=(double) image->columns*image->rows-
10309                 white_point;
10310             }
10311           if (attribute_flag[1] != 0)
10312             black_point=argument_list[1].real_reference;
10313           if (attribute_flag[2] != 0)
10314             white_point=argument_list[2].real_reference;
10315           if (attribute_flag[4] != 0)
10316             channel=(ChannelType) argument_list[4].integer_reference;
10317           channel_mask=SetImageChannelMask(image,channel);
10318           (void) ContrastStretchImage(image,black_point,white_point,exception);
10319           (void) SetImageChannelMask(image,channel_mask);
10320           break;
10321         }
10322         case 96:  /* Sans0 */
10323         {
10324           break;
10325         }
10326         case 97:  /* Sans1 */
10327         {
10328           break;
10329         }
10330         case 98:  /* AdaptiveSharpen */
10331         {
10332           if (attribute_flag[0] != 0)
10333             {
10334               flags=ParseGeometry(argument_list[0].string_reference,
10335                 &geometry_info);
10336               if ((flags & SigmaValue) == 0)
10337                 geometry_info.sigma=1.0;
10338               if ((flags & XiValue) == 0)
10339                 geometry_info.xi=0.0;
10340             }
10341           if (attribute_flag[1] != 0)
10342             geometry_info.rho=argument_list[1].real_reference;
10343           if (attribute_flag[2] != 0)
10344             geometry_info.sigma=argument_list[2].real_reference;
10345           if (attribute_flag[3] != 0)
10346             geometry_info.xi=argument_list[3].real_reference;
10347           if (attribute_flag[4] != 0)
10348             channel=(ChannelType) argument_list[4].integer_reference;
10349           channel_mask=SetImageChannelMask(image,channel);
10350           image=AdaptiveSharpenImage(image,geometry_info.rho,
10351             geometry_info.sigma,exception);
10352           if (image != (Image *) NULL)
10353             (void) SetImageChannelMask(image,channel_mask);
10354           break;
10355         }
10356         case 99:  /* Transpose */
10357         {
10358           image=TransposeImage(image,exception);
10359           break;
10360         }
10361         case 100:  /* Tranverse */
10362         {
10363           image=TransverseImage(image,exception);
10364           break;
10365         }
10366         case 101:  /* AutoOrient */
10367         {
10368           image=AutoOrientImage(image,image->orientation,exception);
10369           break;
10370         }
10371         case 102:  /* AdaptiveBlur */
10372         {
10373           if (attribute_flag[0] != 0)
10374             {
10375               flags=ParseGeometry(argument_list[0].string_reference,
10376                 &geometry_info);
10377               if ((flags & SigmaValue) == 0)
10378                 geometry_info.sigma=1.0;
10379               if ((flags & XiValue) == 0)
10380                 geometry_info.xi=0.0;
10381             }
10382           if (attribute_flag[1] != 0)
10383             geometry_info.rho=argument_list[1].real_reference;
10384           if (attribute_flag[2] != 0)
10385             geometry_info.sigma=argument_list[2].real_reference;
10386           if (attribute_flag[3] != 0)
10387             channel=(ChannelType) argument_list[3].integer_reference;
10388           channel_mask=SetImageChannelMask(image,channel);
10389           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10390             exception);
10391           if (image != (Image *) NULL)
10392             (void) SetImageChannelMask(image,channel_mask);
10393           break;
10394         }
10395         case 103:  /* Sketch */
10396         {
10397           if (attribute_flag[0] != 0)
10398             {
10399               flags=ParseGeometry(argument_list[0].string_reference,
10400                 &geometry_info);
10401               if ((flags & SigmaValue) == 0)
10402                 geometry_info.sigma=1.0;
10403               if ((flags & XiValue) == 0)
10404                 geometry_info.xi=1.0;
10405             }
10406           if (attribute_flag[1] != 0)
10407             geometry_info.rho=argument_list[1].real_reference;
10408           if (attribute_flag[2] != 0)
10409             geometry_info.sigma=argument_list[2].real_reference;
10410           if (attribute_flag[3] != 0)
10411             geometry_info.xi=argument_list[3].real_reference;
10412           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10413             geometry_info.xi,exception);
10414           break;
10415         }
10416         case 104:  /* UniqueColors */
10417         {
10418           image=UniqueImageColors(image,exception);
10419           break;
10420         }
10421         case 105:  /* AdaptiveResize */
10422         {
10423           if (attribute_flag[0] != 0)
10424             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10425               &geometry,exception);
10426           if (attribute_flag[1] != 0)
10427             geometry.width=argument_list[1].integer_reference;
10428           if (attribute_flag[2] != 0)
10429             geometry.height=argument_list[2].integer_reference;
10430           if (attribute_flag[3] != 0)
10431             image->filter=(FilterType) argument_list[4].integer_reference;
10432           if (attribute_flag[4] != 0)
10433             SetImageArtifact(image,"filter:support",
10434               argument_list[4].string_reference);
10435           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10436             exception);
10437           break;
10438         }
10439         case 106:  /* ClipMask */
10440         {
10441           Image
10442             *mask_image;
10443
10444           if (attribute_flag[0] == 0)
10445             {
10446               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10447                 PackageName);
10448               goto PerlException;
10449             }
10450           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10451             exception);
10452           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10453           mask_image=DestroyImage(mask_image);
10454           break;
10455         }
10456         case 107:  /* LinearStretch */
10457         {
10458            double
10459              black_point,
10460              white_point;
10461
10462            black_point=0.0;
10463            white_point=(double) image->columns*image->rows;
10464            if (attribute_flag[0] != 0)
10465              {
10466                flags=ParseGeometry(argument_list[0].string_reference,
10467                  &geometry_info);
10468                if ((flags & SigmaValue) != 0)
10469                   white_point=geometry_info.sigma;
10470                if ((flags & PercentValue) != 0)
10471                  {
10472                    black_point*=(double) image->columns*image->rows/100.0;
10473                    white_point*=(double) image->columns*image->rows/100.0;
10474                  }
10475                if ((flags & SigmaValue) == 0)
10476                  white_point=(double) image->columns*image->rows-black_point;
10477              }
10478           if (attribute_flag[1] != 0)
10479             black_point=argument_list[1].real_reference;
10480           if (attribute_flag[2] != 0)
10481             white_point=argument_list[2].real_reference;
10482           (void) LinearStretchImage(image,black_point,white_point,exception);
10483           break;
10484         }
10485         case 108:  /* ColorMatrix */
10486         {
10487           AV
10488             *av;
10489
10490           double
10491             *color_matrix;
10492
10493           KernelInfo
10494             *kernel_info;
10495
10496           size_t
10497             order;
10498
10499           if (attribute_flag[0] == 0)
10500             break;
10501           av=(AV *) argument_list[0].array_reference;
10502           order=(size_t) sqrt(av_len(av)+1);
10503           color_matrix=(double *) AcquireQuantumMemory(order,order*
10504             sizeof(*color_matrix));
10505           if (color_matrix == (double *) NULL)
10506             {
10507               ThrowPerlException(exception,ResourceLimitFatalError,
10508                 "MemoryAllocationFailed",PackageName);
10509               goto PerlException;
10510            }
10511           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10512             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10513           for ( ; j < (ssize_t) (order*order); j++)
10514             color_matrix[j]=0.0;
10515           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10516           if (kernel_info == (KernelInfo *) NULL)
10517             break;
10518           kernel_info->width=order;
10519           kernel_info->height=order;
10520           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10521             order*sizeof(*kernel_info->values));
10522           if (kernel_info->values != (MagickRealType *) NULL)
10523             {
10524               for (i=0; i < (ssize_t) (order*order); i++)
10525                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10526               image=ColorMatrixImage(image,kernel_info,exception);
10527             }
10528           kernel_info=DestroyKernelInfo(kernel_info);
10529           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10530           break;
10531         }
10532         case 109:  /* Mask */
10533         {
10534           Image
10535             *mask_image;
10536
10537           if (attribute_flag[0] == 0)
10538             {
10539               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10540                 PackageName);
10541               goto PerlException;
10542             }
10543           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10544             MagickTrue,exception);
10545           (void) SetImageMask(image,ReadPixelMask,mask_image,exception);
10546           mask_image=DestroyImage(mask_image);
10547           break;
10548         }
10549         case 110:  /* Polaroid */
10550         {
10551           char
10552             *caption;
10553
10554           DrawInfo
10555             *draw_info;
10556
10557           double
10558             angle;
10559
10560           PixelInterpolateMethod
10561             method;
10562
10563           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10564             (DrawInfo *) NULL);
10565           caption=(char *) NULL;
10566           if (attribute_flag[0] != 0)
10567             caption=InterpretImageProperties(info ? info->image_info :
10568               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10569               exception);
10570           angle=0.0;
10571           if (attribute_flag[1] != 0)
10572             angle=argument_list[1].real_reference;
10573           if (attribute_flag[2] != 0)
10574             (void) CloneString(&draw_info->font,
10575               argument_list[2].string_reference);
10576           if (attribute_flag[3] != 0)
10577             (void) QueryColorCompliance(argument_list[3].string_reference,
10578               AllCompliance,&draw_info->stroke,exception);
10579           if (attribute_flag[4] != 0)
10580             (void) QueryColorCompliance(argument_list[4].string_reference,
10581               AllCompliance,&draw_info->fill,exception);
10582           if (attribute_flag[5] != 0)
10583             draw_info->stroke_width=argument_list[5].real_reference;
10584           if (attribute_flag[6] != 0)
10585             draw_info->pointsize=argument_list[6].real_reference;
10586           if (attribute_flag[7] != 0)
10587             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10588           if (attribute_flag[8] != 0)
10589             (void) QueryColorCompliance(argument_list[8].string_reference,
10590               AllCompliance,&image->background_color,exception);
10591           method=UndefinedInterpolatePixel;
10592           if (attribute_flag[9] != 0)
10593             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10594           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10595           draw_info=DestroyDrawInfo(draw_info);
10596           if (caption != (char *) NULL)
10597             caption=DestroyString(caption);
10598           break;
10599         }
10600         case 111:  /* FloodfillPaint */
10601         {
10602           DrawInfo
10603             *draw_info;
10604
10605           MagickBooleanType
10606             invert;
10607
10608           PixelInfo
10609             target;
10610
10611           draw_info=CloneDrawInfo(info ? info->image_info :
10612             (ImageInfo *) NULL,(DrawInfo *) NULL);
10613           if (attribute_flag[0] != 0)
10614             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10615               &geometry,exception);
10616           if (attribute_flag[1] != 0)
10617             geometry.x=argument_list[1].integer_reference;
10618           if (attribute_flag[2] != 0)
10619             geometry.y=argument_list[2].integer_reference;
10620           if (attribute_flag[3] != 0)
10621             (void) QueryColorCompliance(argument_list[3].string_reference,
10622               AllCompliance,&draw_info->fill,exception);
10623           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10624             geometry.x,geometry.y,&target,exception);
10625           if (attribute_flag[4] != 0)
10626             QueryColorCompliance(argument_list[4].string_reference,
10627               AllCompliance,&target,exception);
10628           if (attribute_flag[5] != 0)
10629             image->fuzz=StringToDoubleInterval(
10630               argument_list[5].string_reference,(double) QuantumRange+1.0);
10631           if (attribute_flag[6] != 0)
10632             channel=(ChannelType) argument_list[6].integer_reference;
10633           invert=MagickFalse;
10634           if (attribute_flag[7] != 0)
10635             invert=(MagickBooleanType) argument_list[7].integer_reference;
10636           channel_mask=SetImageChannelMask(image,channel);
10637           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10638             geometry.y,invert,exception);
10639           (void) SetImageChannelMask(image,channel_mask);
10640           draw_info=DestroyDrawInfo(draw_info);
10641           break;
10642         }
10643         case 112:  /* Distort */
10644         {
10645           AV
10646             *av;
10647
10648           double
10649             *coordinates;
10650
10651           DistortMethod
10652             method;
10653
10654           size_t
10655             number_coordinates;
10656
10657           VirtualPixelMethod
10658             virtual_pixel;
10659
10660           if (attribute_flag[0] == 0)
10661             break;
10662           method=UndefinedDistortion;
10663           if (attribute_flag[1] != 0)
10664             method=(DistortMethod) argument_list[1].integer_reference;
10665           av=(AV *) argument_list[0].array_reference;
10666           number_coordinates=(size_t) av_len(av)+1;
10667           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10668             sizeof(*coordinates));
10669           if (coordinates == (double *) NULL)
10670             {
10671               ThrowPerlException(exception,ResourceLimitFatalError,
10672                 "MemoryAllocationFailed",PackageName);
10673               goto PerlException;
10674             }
10675           for (j=0; j < (ssize_t) number_coordinates; j++)
10676             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10677           virtual_pixel=UndefinedVirtualPixelMethod;
10678           if (attribute_flag[2] != 0)
10679             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10680               argument_list[2].integer_reference,exception);
10681           image=DistortImage(image,method,number_coordinates,coordinates,
10682             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10683             exception);
10684           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10685             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10686               exception);
10687           coordinates=(double *) RelinquishMagickMemory(coordinates);
10688           break;
10689         }
10690         case 113:  /* Clut */
10691         {
10692           PixelInterpolateMethod
10693             method;
10694
10695           if (attribute_flag[0] == 0)
10696             {
10697               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10698                 PackageName);
10699               goto PerlException;
10700             }
10701           method=UndefinedInterpolatePixel;
10702           if (attribute_flag[1] != 0)
10703             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10704           if (attribute_flag[2] != 0)
10705             channel=(ChannelType) argument_list[2].integer_reference;
10706           channel_mask=SetImageChannelMask(image,channel);
10707           (void) ClutImage(image,argument_list[0].image_reference,method,
10708             exception);
10709           (void) SetImageChannelMask(image,channel_mask);
10710           break;
10711         }
10712         case 114:  /* LiquidRescale */
10713         {
10714           if (attribute_flag[0] != 0)
10715             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10716               &geometry,exception);
10717           if (attribute_flag[1] != 0)
10718             geometry.width=argument_list[1].integer_reference;
10719           if (attribute_flag[2] != 0)
10720             geometry.height=argument_list[2].integer_reference;
10721           if (attribute_flag[3] == 0)
10722             argument_list[3].real_reference=1.0;
10723           if (attribute_flag[4] == 0)
10724             argument_list[4].real_reference=0.0;
10725           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10726             argument_list[3].real_reference,argument_list[4].real_reference,
10727             exception);
10728           break;
10729         }
10730         case 115:  /* EncipherImage */
10731         {
10732           (void) EncipherImage(image,argument_list[0].string_reference,
10733             exception);
10734           break;
10735         }
10736         case 116:  /* DecipherImage */
10737         {
10738           (void) DecipherImage(image,argument_list[0].string_reference,
10739             exception);
10740           break;
10741         }
10742         case 117:  /* Deskew */
10743         {
10744           geometry_info.rho=QuantumRange/2.0;
10745           if (attribute_flag[0] != 0)
10746             flags=ParseGeometry(argument_list[0].string_reference,
10747               &geometry_info);
10748           if (attribute_flag[1] != 0)
10749             geometry_info.rho=StringToDoubleInterval(
10750               argument_list[1].string_reference,(double) QuantumRange+1.0);
10751           image=DeskewImage(image,geometry_info.rho,exception);
10752           break;
10753         }
10754         case 118:  /* Remap */
10755         {
10756           QuantizeInfo
10757             *quantize_info;
10758
10759           if (attribute_flag[0] == 0)
10760             {
10761               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10762                 PackageName);
10763               goto PerlException;
10764             }
10765           quantize_info=AcquireQuantizeInfo(info->image_info);
10766           if (attribute_flag[1] != 0)
10767             quantize_info->dither_method=(DitherMethod)
10768               argument_list[1].integer_reference;
10769           (void) RemapImages(quantize_info,image,
10770             argument_list[0].image_reference,exception);
10771           quantize_info=DestroyQuantizeInfo(quantize_info);
10772           break;
10773         }
10774         case 119:  /* SparseColor */
10775         {
10776           AV
10777             *av;
10778
10779           double
10780             *coordinates;
10781
10782           SparseColorMethod
10783             method;
10784
10785           size_t
10786             number_coordinates;
10787
10788           VirtualPixelMethod
10789             virtual_pixel;
10790
10791           if (attribute_flag[0] == 0)
10792             break;
10793           method=UndefinedColorInterpolate;
10794           if (attribute_flag[1] != 0)
10795             method=(SparseColorMethod) argument_list[1].integer_reference;
10796           av=(AV *) argument_list[0].array_reference;
10797           number_coordinates=(size_t) av_len(av)+1;
10798           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10799             sizeof(*coordinates));
10800           if (coordinates == (double *) NULL)
10801             {
10802               ThrowPerlException(exception,ResourceLimitFatalError,
10803                 "MemoryAllocationFailed",PackageName);
10804               goto PerlException;
10805             }
10806           for (j=0; j < (ssize_t) number_coordinates; j++)
10807             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10808           virtual_pixel=UndefinedVirtualPixelMethod;
10809           if (attribute_flag[2] != 0)
10810             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10811               argument_list[2].integer_reference,exception);
10812           if (attribute_flag[3] != 0)
10813             channel=(ChannelType) argument_list[3].integer_reference;
10814           channel_mask=SetImageChannelMask(image,channel);
10815           image=SparseColorImage(image,method,number_coordinates,coordinates,
10816             exception);
10817           if (image != (Image *) NULL)
10818             (void) SetImageChannelMask(image,channel_mask);
10819           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10820             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10821               exception);
10822           coordinates=(double *) RelinquishMagickMemory(coordinates);
10823           break;
10824         }
10825         case 120:  /* Function */
10826         {
10827           AV
10828             *av;
10829
10830           double
10831             *parameters;
10832
10833           MagickFunction
10834             function;
10835
10836           size_t
10837             number_parameters;
10838
10839           VirtualPixelMethod
10840             virtual_pixel;
10841
10842           if (attribute_flag[0] == 0)
10843             break;
10844           function=UndefinedFunction;
10845           if (attribute_flag[1] != 0)
10846             function=(MagickFunction) argument_list[1].integer_reference;
10847           av=(AV *) argument_list[0].array_reference;
10848           number_parameters=(size_t) av_len(av)+1;
10849           parameters=(double *) AcquireQuantumMemory(number_parameters,
10850             sizeof(*parameters));
10851           if (parameters == (double *) NULL)
10852             {
10853               ThrowPerlException(exception,ResourceLimitFatalError,
10854                 "MemoryAllocationFailed",PackageName);
10855               goto PerlException;
10856             }
10857           for (j=0; j < (ssize_t) number_parameters; j++)
10858             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10859           virtual_pixel=UndefinedVirtualPixelMethod;
10860           if (attribute_flag[2] != 0)
10861             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10862               argument_list[2].integer_reference,exception);
10863           (void) FunctionImage(image,function,number_parameters,parameters,
10864             exception);
10865           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10866             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10867               exception);
10868           parameters=(double *) RelinquishMagickMemory(parameters);
10869           break;
10870         }
10871         case 121:  /* SelectiveBlur */
10872         {
10873           if (attribute_flag[0] != 0)
10874             {
10875               flags=ParseGeometry(argument_list[0].string_reference,
10876                 &geometry_info);
10877               if ((flags & SigmaValue) == 0)
10878                 geometry_info.sigma=1.0;
10879               if ((flags & PercentValue) != 0)
10880                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10881             }
10882           if (attribute_flag[1] != 0)
10883             geometry_info.rho=argument_list[1].real_reference;
10884           if (attribute_flag[2] != 0)
10885             geometry_info.sigma=argument_list[2].real_reference;
10886           if (attribute_flag[3] != 0)
10887             geometry_info.xi=argument_list[3].integer_reference;;
10888           if (attribute_flag[5] != 0)
10889             channel=(ChannelType) argument_list[5].integer_reference;
10890           channel_mask=SetImageChannelMask(image,channel);
10891           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10892             geometry_info.xi,exception);
10893           if (image != (Image *) NULL)
10894             (void) SetImageChannelMask(image,channel_mask);
10895           break;
10896         }
10897         case 122:  /* HaldClut */
10898         {
10899           if (attribute_flag[0] == 0)
10900             {
10901               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10902                 PackageName);
10903               goto PerlException;
10904             }
10905           if (attribute_flag[1] != 0)
10906             channel=(ChannelType) argument_list[1].integer_reference;
10907           channel_mask=SetImageChannelMask(image,channel);
10908           (void) HaldClutImage(image,argument_list[0].image_reference,
10909             exception);
10910           (void) SetImageChannelMask(image,channel_mask);
10911           break;
10912         }
10913         case 123:  /* BlueShift */
10914         {
10915           if (attribute_flag[0] != 0)
10916             (void) ParseGeometry(argument_list[0].string_reference,
10917               &geometry_info);
10918           image=BlueShiftImage(image,geometry_info.rho,exception);
10919           break;
10920         }
10921         case 124:  /* ForwardFourierTransformImage */
10922         {
10923           image=ForwardFourierTransformImage(image,
10924             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10925             exception);
10926           break;
10927         }
10928         case 125:  /* InverseFourierTransformImage */
10929         {
10930           image=InverseFourierTransformImage(image,image->next,
10931             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10932             exception);
10933           break;
10934         }
10935         case 126:  /* ColorDecisionList */
10936         {
10937           if (attribute_flag[0] == 0)
10938             argument_list[0].string_reference=(char *) NULL;
10939           (void) ColorDecisionListImage(image,
10940             argument_list[0].string_reference,exception);
10941           break;
10942         }
10943         case 127:  /* AutoGamma */
10944         {
10945           if (attribute_flag[0] != 0)
10946             channel=(ChannelType) argument_list[0].integer_reference;
10947           channel_mask=SetImageChannelMask(image,channel);
10948           (void) AutoGammaImage(image,exception);
10949           (void) SetImageChannelMask(image,channel_mask);
10950           break;
10951         }
10952         case 128:  /* AutoLevel */
10953         {
10954           if (attribute_flag[0] != 0)
10955             channel=(ChannelType) argument_list[0].integer_reference;
10956           channel_mask=SetImageChannelMask(image,channel);
10957           (void) AutoLevelImage(image,exception);
10958           (void) SetImageChannelMask(image,channel_mask);
10959           break;
10960         }
10961         case 129:  /* LevelColors */
10962         {
10963           PixelInfo
10964             black_point,
10965             white_point;
10966
10967           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10968             exception);
10969           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10970             exception);
10971           if (attribute_flag[1] != 0)
10972              (void) QueryColorCompliance(
10973                argument_list[1].string_reference,AllCompliance,&black_point,
10974                exception);
10975           if (attribute_flag[2] != 0)
10976              (void) QueryColorCompliance(
10977                argument_list[2].string_reference,AllCompliance,&white_point,
10978                exception);
10979           if (attribute_flag[3] != 0)
10980             channel=(ChannelType) argument_list[3].integer_reference;
10981           channel_mask=SetImageChannelMask(image,channel);
10982           (void) LevelImageColors(image,&black_point,&white_point,
10983             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10984             exception);
10985           (void) SetImageChannelMask(image,channel_mask);
10986           break;
10987         }
10988         case 130:  /* Clamp */
10989         {
10990           if (attribute_flag[0] != 0)
10991             channel=(ChannelType) argument_list[0].integer_reference;
10992           channel_mask=SetImageChannelMask(image,channel);
10993           (void) ClampImage(image,exception);
10994           (void) SetImageChannelMask(image,channel_mask);
10995           break;
10996         }
10997         case 131:  /* BrightnessContrast */
10998         {
10999           double
11000             brightness,
11001             contrast;
11002
11003           brightness=0.0;
11004           contrast=0.0;
11005           if (attribute_flag[0] != 0)
11006             {
11007               flags=ParseGeometry(argument_list[0].string_reference,
11008                 &geometry_info);
11009               brightness=geometry_info.rho;
11010               if ((flags & SigmaValue) == 0)
11011                 contrast=geometry_info.sigma;
11012             }
11013           if (attribute_flag[1] != 0)
11014             brightness=argument_list[1].real_reference;
11015           if (attribute_flag[2] != 0)
11016             contrast=argument_list[2].real_reference;
11017           if (attribute_flag[4] != 0)
11018             channel=(ChannelType) argument_list[4].integer_reference;
11019           channel_mask=SetImageChannelMask(image,channel);
11020           (void) BrightnessContrastImage(image,brightness,contrast,exception);
11021           (void) SetImageChannelMask(image,channel_mask);
11022           break;
11023         }
11024         case 132:  /* Morphology */
11025         {
11026           KernelInfo
11027             *kernel;
11028
11029           MorphologyMethod
11030             method;
11031
11032           ssize_t
11033             iterations;
11034
11035           if (attribute_flag[0] == 0)
11036             break;
11037           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11038           if (kernel == (KernelInfo *) NULL)
11039             break;
11040           if (attribute_flag[1] != 0)
11041             channel=(ChannelType) argument_list[1].integer_reference;
11042           method=UndefinedMorphology;
11043           if (attribute_flag[2] != 0)
11044             method=argument_list[2].integer_reference;
11045           iterations=1;
11046           if (attribute_flag[3] != 0)
11047             iterations=argument_list[3].integer_reference;
11048           channel_mask=SetImageChannelMask(image,channel);
11049           image=MorphologyImage(image,method,iterations,kernel,exception);
11050           if (image != (Image *) NULL)
11051             (void) SetImageChannelMask(image,channel_mask);
11052           kernel=DestroyKernelInfo(kernel);
11053           break;
11054         }
11055         case 133:  /* Mode */
11056         {
11057           if (attribute_flag[0] != 0)
11058             {
11059               flags=ParseGeometry(argument_list[0].string_reference,
11060                 &geometry_info);
11061               if ((flags & SigmaValue) == 0)
11062                 geometry_info.sigma=1.0;
11063             }
11064           if (attribute_flag[1] != 0)
11065             geometry_info.rho=argument_list[1].real_reference;
11066           if (attribute_flag[2] != 0)
11067             geometry_info.sigma=argument_list[2].real_reference;
11068           if (attribute_flag[3] != 0)
11069             channel=(ChannelType) argument_list[3].integer_reference;
11070           channel_mask=SetImageChannelMask(image,channel);
11071           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11072             (size_t) geometry_info.sigma,exception);
11073           if (image != (Image *) NULL)
11074             (void) SetImageChannelMask(image,channel_mask);
11075           break;
11076         }
11077         case 134:  /* Statistic */
11078         {
11079           StatisticType
11080             statistic;
11081
11082           statistic=UndefinedStatistic;
11083           if (attribute_flag[0] != 0)
11084             {
11085               flags=ParseGeometry(argument_list[0].string_reference,
11086                 &geometry_info);
11087               if ((flags & SigmaValue) == 0)
11088                 geometry_info.sigma=1.0;
11089             }
11090           if (attribute_flag[1] != 0)
11091             geometry_info.rho=argument_list[1].real_reference;
11092           if (attribute_flag[2] != 0)
11093             geometry_info.sigma=argument_list[2].real_reference;
11094           if (attribute_flag[3] != 0)
11095             channel=(ChannelType) argument_list[3].integer_reference;
11096           if (attribute_flag[4] != 0)
11097             statistic=(StatisticType) argument_list[4].integer_reference;
11098           channel_mask=SetImageChannelMask(image,channel);
11099           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11100             (size_t) geometry_info.sigma,exception);
11101           if (image != (Image *) NULL)
11102             (void) SetImageChannelMask(image,channel_mask);
11103           break;
11104         }
11105         case 135:  /* Perceptible */
11106         {
11107           double
11108             epsilon;
11109
11110           epsilon=MagickEpsilon;
11111           if (attribute_flag[0] != 0)
11112             epsilon=argument_list[0].real_reference;
11113           if (attribute_flag[1] != 0)
11114             channel=(ChannelType) argument_list[1].integer_reference;
11115           channel_mask=SetImageChannelMask(image,channel);
11116           (void) PerceptibleImage(image,epsilon,exception);
11117           (void) SetImageChannelMask(image,channel_mask);
11118           break;
11119         }
11120         case 136:  /* Poly */
11121         {
11122           AV
11123             *av;
11124
11125           double
11126             *terms;
11127
11128           size_t
11129             number_terms;
11130
11131           if (attribute_flag[0] == 0)
11132             break;
11133           if (attribute_flag[1] != 0)
11134             channel=(ChannelType) argument_list[1].integer_reference;
11135           av=(AV *) argument_list[0].array_reference;
11136           number_terms=(size_t) av_len(av);
11137           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11138           if (terms == (double *) NULL)
11139             {
11140               ThrowPerlException(exception,ResourceLimitFatalError,
11141                 "MemoryAllocationFailed",PackageName);
11142               goto PerlException;
11143             }
11144           for (j=0; j < av_len(av); j++)
11145             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11146           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11147           terms=(double *) RelinquishMagickMemory(terms);
11148           break;
11149         }
11150         case 137:  /* Grayscale */
11151         {
11152           PixelIntensityMethod
11153             method;
11154
11155           method=UndefinedPixelIntensityMethod;
11156           if (attribute_flag[0] != 0)
11157             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11158           (void) GrayscaleImage(image,method,exception);
11159           break;
11160         }
11161         case 138:  /* Canny */
11162         {
11163           if (attribute_flag[0] != 0)
11164             {
11165               flags=ParseGeometry(argument_list[0].string_reference,
11166                 &geometry_info);
11167               if ((flags & SigmaValue) == 0)
11168                 geometry_info.sigma=1.0;
11169               if ((flags & XiValue) == 0)
11170                 geometry_info.xi=0.10;
11171               if ((flags & PsiValue) == 0)
11172                 geometry_info.psi=0.30;
11173               if ((flags & PercentValue) != 0)
11174                 {
11175                   geometry_info.xi/=100.0;
11176                   geometry_info.psi/=100.0;
11177                 }
11178             }
11179           if (attribute_flag[1] != 0)
11180             geometry_info.rho=argument_list[1].real_reference;
11181           if (attribute_flag[2] != 0)
11182             geometry_info.sigma=argument_list[2].real_reference;
11183           if (attribute_flag[3] != 0)
11184             geometry_info.xi=argument_list[3].real_reference;
11185           if (attribute_flag[4] != 0)
11186             geometry_info.psi=argument_list[4].real_reference;
11187           if (attribute_flag[5] != 0)
11188             channel=(ChannelType) argument_list[5].integer_reference;
11189           channel_mask=SetImageChannelMask(image,channel);
11190           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11191             geometry_info.xi,geometry_info.psi,exception);
11192           if (image != (Image *) NULL)
11193             (void) SetImageChannelMask(image,channel_mask);
11194           break;
11195         }
11196         case 139:  /* HoughLine */
11197         {
11198           if (attribute_flag[0] != 0)
11199             {
11200               flags=ParseGeometry(argument_list[0].string_reference,
11201                 &geometry_info);
11202               if ((flags & SigmaValue) == 0)
11203                 geometry_info.sigma=geometry_info.rho;
11204               if ((flags & XiValue) == 0)
11205                 geometry_info.xi=40;
11206             }
11207           if (attribute_flag[1] != 0)
11208             geometry_info.rho=(double) argument_list[1].integer_reference;
11209           if (attribute_flag[2] != 0)
11210             geometry_info.sigma=(double) argument_list[2].integer_reference;
11211           if (attribute_flag[3] != 0)
11212             geometry_info.xi=(double) argument_list[3].integer_reference;
11213           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11214             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11215           break;
11216         }
11217         case 140:  /* MeanShift */
11218         {
11219           if (attribute_flag[0] != 0)
11220             {
11221               flags=ParseGeometry(argument_list[0].string_reference,
11222                 &geometry_info);
11223               if ((flags & SigmaValue) == 0)
11224                 geometry_info.sigma=geometry_info.rho;
11225               if ((flags & XiValue) == 0)
11226                 geometry_info.xi=0.10*QuantumRange;
11227               if ((flags & PercentValue) != 0)
11228                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11229             }
11230           if (attribute_flag[1] != 0)
11231             geometry_info.rho=(double) argument_list[1].integer_reference;
11232           if (attribute_flag[2] != 0)
11233             geometry_info.sigma=(double) argument_list[2].integer_reference;
11234           if (attribute_flag[3] != 0)
11235             geometry_info.xi=(double) argument_list[3].integer_reference;
11236           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11237             geometry_info.sigma,geometry_info.xi,exception);
11238           break;
11239         }
11240         case 141:  /* Kuwahara */
11241         {
11242           if (attribute_flag[0] != 0)
11243             {
11244               flags=ParseGeometry(argument_list[0].string_reference,
11245                 &geometry_info);
11246               if ((flags & SigmaValue) == 0)
11247                 geometry_info.sigma=geometry_info.rho-0.5;
11248             }
11249           if (attribute_flag[1] != 0)
11250             geometry_info.rho=argument_list[1].real_reference;
11251           if (attribute_flag[2] != 0)
11252             geometry_info.sigma=argument_list[2].real_reference;
11253           if (attribute_flag[3] != 0)
11254             channel=(ChannelType) argument_list[3].integer_reference;
11255           channel_mask=SetImageChannelMask(image,channel);
11256           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11257             exception);
11258           if (image != (Image *) NULL)
11259             (void) SetImageChannelMask(image,channel_mask);
11260           break;
11261         }
11262         case 142:  /* ConnectedComponent */
11263         {
11264           size_t
11265             connectivity;
11266
11267           connectivity=4;
11268           if (attribute_flag[0] != 0)
11269             connectivity=argument_list[0].integer_reference;
11270           image=ConnectedComponentsImage(image,connectivity,
11271             (CCObjectInfo **) NULL,exception);
11272           break;
11273         }
11274         case 143:  /* Copy */
11275         {
11276           Image
11277             *source_image;
11278
11279           OffsetInfo
11280             offset;
11281
11282           RectangleInfo
11283             offset_geometry;
11284
11285           source_image=image;
11286           if (attribute_flag[0] != 0)
11287             source_image=argument_list[0].image_reference;
11288           SetGeometry(source_image,&geometry);
11289           if (attribute_flag[1] != 0)
11290             flags=ParseGravityGeometry(source_image,
11291               argument_list[1].string_reference,&geometry,exception);
11292           if (attribute_flag[2] != 0)
11293             geometry.width=argument_list[2].integer_reference;
11294           if (attribute_flag[3] != 0)
11295             geometry.height=argument_list[3].integer_reference;
11296           if (attribute_flag[4] != 0)
11297             geometry.x=argument_list[4].integer_reference;
11298           if (attribute_flag[5] != 0)
11299             geometry.y=argument_list[5].integer_reference;
11300           if (attribute_flag[6] != 0)
11301             image->gravity=(GravityType) argument_list[6].integer_reference;
11302           SetGeometry(image,&offset_geometry);
11303           if (attribute_flag[7] != 0)
11304             flags=ParseGravityGeometry(image,argument_list[7].string_reference,
11305               &offset_geometry,exception);
11306           offset.x=offset_geometry.x;
11307           offset.y=offset_geometry.y;
11308           if (attribute_flag[8] != 0)
11309             offset.x=argument_list[8].integer_reference;
11310           if (attribute_flag[9] != 0)
11311             offset.y=argument_list[9].integer_reference;
11312           (void) CopyImagePixels(image,source_image,&geometry,&offset,
11313             exception);
11314           break;
11315         }
11316         case 144:  /* Color */
11317         {
11318           PixelInfo
11319             color;
11320
11321           (void) QueryColorCompliance("none",AllCompliance,&color,exception);
11322           if (attribute_flag[0] != 0)
11323             (void) QueryColorCompliance(argument_list[0].string_reference,
11324               AllCompliance,&color,exception);
11325           (void) SetImageColor(image,&color,exception);
11326           break;
11327         }
11328         case 145:  /* WaveletDenoise */
11329         {
11330           if (attribute_flag[0] == 0)
11331             argument_list[0].string_reference="5%";
11332           if (attribute_flag[2] != 0)
11333             channel=(ChannelType) argument_list[2].integer_reference;
11334           flags=ParseGeometry(argument_list[0].string_reference,&geometry_info);
11335           if ((flags & PercentValue) != 0)
11336             geometry_info.rho*=(double) (QuantumRange/100.0);
11337           channel_mask=SetImageChannelMask(image,channel);
11338           image=WaveletDenoiseImage(image,geometry_info.rho,exception);
11339           if (image != (Image *) NULL)
11340             (void) SetImageChannelMask(image,channel_mask);
11341           break;
11342         }
11343       }
11344       if (next != (Image *) NULL)
11345         (void) CatchImageException(next);
11346       if (region_image != (Image *) NULL)
11347         {
11348           /*
11349             Composite region.
11350           */
11351           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11352             region_info.x,region_info.y,exception);
11353           (void) status;
11354           (void) CatchImageException(region_image);
11355           image=DestroyImage(image);
11356           image=region_image;
11357         }
11358       if (image != (Image *) NULL)
11359         {
11360           number_images++;
11361           if (next && (next != image))
11362             {
11363               image->next=next->next;
11364               if (image->next != (Image *) NULL)
11365                 image->next->previous=image;
11366               DeleteImageFromRegistry(*pv,next);
11367             }
11368           sv_setiv(*pv,PTR2IV(image));
11369           next=image;
11370         }
11371       if (*pv)
11372         pv++;
11373     }
11374
11375   PerlException:
11376     if (reference_vector)
11377       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11378     InheritPerlException(exception,perl_exception);
11379     exception=DestroyExceptionInfo(exception);
11380     sv_setiv(perl_exception,(IV) number_images);
11381     SvPOK_on(perl_exception);
11382     ST(0)=sv_2mortal(perl_exception);
11383     XSRETURN(1);
11384   }
11385 \f
11386 #
11387 ###############################################################################
11388 #                                                                             #
11389 #                                                                             #
11390 #                                                                             #
11391 #   M o n t a g e                                                             #
11392 #                                                                             #
11393 #                                                                             #
11394 #                                                                             #
11395 ###############################################################################
11396 #
11397 #
11398 void
11399 Montage(ref,...)
11400   Image::Magick ref=NO_INIT
11401   ALIAS:
11402     MontageImage  = 1
11403     montage       = 2
11404     montageimage  = 3
11405   PPCODE:
11406   {
11407     AV
11408       *av;
11409
11410     char
11411       *attribute;
11412
11413     ExceptionInfo
11414       *exception;
11415
11416     HV
11417       *hv;
11418
11419     Image
11420       *image,
11421       *next;
11422
11423     PixelInfo
11424       transparent_color;
11425
11426     MontageInfo
11427       *montage_info;
11428
11429     register ssize_t
11430       i;
11431
11432     ssize_t
11433       sp;
11434
11435     struct PackageInfo
11436       *info;
11437
11438     SV
11439       *av_reference,
11440       *perl_exception,
11441       *reference,
11442       *rv,
11443       *sv;
11444
11445     PERL_UNUSED_VAR(ref);
11446     PERL_UNUSED_VAR(ix);
11447     exception=AcquireExceptionInfo();
11448     perl_exception=newSVpv("",0);
11449     sv=NULL;
11450     attribute=NULL;
11451     if (sv_isobject(ST(0)) == 0)
11452       {
11453         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11454           PackageName);
11455         goto PerlException;
11456       }
11457     reference=SvRV(ST(0));
11458     hv=SvSTASH(reference);
11459     av=newAV();
11460     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11461     SvREFCNT_dec(av);
11462     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11463     if (image == (Image *) NULL)
11464       {
11465         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11466           PackageName);
11467         goto PerlException;
11468       }
11469     /*
11470       Get options.
11471     */
11472     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11473     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11474     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11475       exception);
11476     for (i=2; i < items; i+=2)
11477     {
11478       attribute=(char *) SvPV(ST(i-1),na);
11479       switch (*attribute)
11480       {
11481         case 'B':
11482         case 'b':
11483         {
11484           if (LocaleCompare(attribute,"background") == 0)
11485             {
11486               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11487                 &montage_info->background_color,exception);
11488               for (next=image; next; next=next->next)
11489                 next->background_color=montage_info->background_color;
11490               break;
11491             }
11492           if (LocaleCompare(attribute,"border") == 0)
11493             {
11494               montage_info->border_width=SvIV(ST(i));
11495               break;
11496             }
11497           if (LocaleCompare(attribute,"bordercolor") == 0)
11498             {
11499               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11500                 &montage_info->border_color,exception);
11501               for (next=image; next; next=next->next)
11502                 next->border_color=montage_info->border_color;
11503               break;
11504             }
11505           if (LocaleCompare(attribute,"borderwidth") == 0)
11506             {
11507               montage_info->border_width=SvIV(ST(i));
11508               break;
11509             }
11510           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11511             attribute);
11512           break;
11513         }
11514         case 'C':
11515         case 'c':
11516         {
11517           if (LocaleCompare(attribute,"compose") == 0)
11518             {
11519               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11520                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11521               if (sp < 0)
11522                 {
11523                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11524                     SvPV(ST(i),na));
11525                   break;
11526                 }
11527               for (next=image; next; next=next->next)
11528                 next->compose=(CompositeOperator) sp;
11529               break;
11530             }
11531           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11532             attribute);
11533           break;
11534         }
11535         case 'F':
11536         case 'f':
11537         {
11538           if (LocaleCompare(attribute,"fill") == 0)
11539             {
11540               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11541                 &montage_info->fill,exception);
11542               break;
11543             }
11544           if (LocaleCompare(attribute,"font") == 0)
11545             {
11546               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11547               break;
11548             }
11549           if (LocaleCompare(attribute,"frame") == 0)
11550             {
11551               char
11552                 *p;
11553
11554               p=SvPV(ST(i),na);
11555               if (IsGeometry(p) == MagickFalse)
11556                 {
11557                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11558                     p);
11559                   break;
11560                 }
11561               (void) CloneString(&montage_info->frame,p);
11562               if (*p == '\0')
11563                 montage_info->frame=(char *) NULL;
11564               break;
11565             }
11566           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11567             attribute);
11568           break;
11569         }
11570         case 'G':
11571         case 'g':
11572         {
11573           if (LocaleCompare(attribute,"geometry") == 0)
11574             {
11575               char
11576                 *p;
11577
11578               p=SvPV(ST(i),na);
11579               if (IsGeometry(p) == MagickFalse)
11580                 {
11581                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11582                     p);
11583                   break;
11584                 }
11585              (void) CloneString(&montage_info->geometry,p);
11586              if (*p == '\0')
11587                montage_info->geometry=(char *) NULL;
11588              break;
11589            }
11590          if (LocaleCompare(attribute,"gravity") == 0)
11591            {
11592              ssize_t
11593                in;
11594
11595              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11596                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11597              if (in < 0)
11598                {
11599                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11600                    SvPV(ST(i),na));
11601                  return;
11602                }
11603              montage_info->gravity=(GravityType) in;
11604              for (next=image; next; next=next->next)
11605                next->gravity=(GravityType) in;
11606              break;
11607            }
11608           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11609             attribute);
11610           break;
11611         }
11612         case 'L':
11613         case 'l':
11614         {
11615           if (LocaleCompare(attribute,"label") == 0)
11616             {
11617               for (next=image; next; next=next->next)
11618                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11619                   info ? info->image_info : (ImageInfo *) NULL,next,
11620                   SvPV(ST(i),na),exception),exception);
11621               break;
11622             }
11623           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11624             attribute);
11625           break;
11626         }
11627         case 'M':
11628         case 'm':
11629         {
11630           if (LocaleCompare(attribute,"mattecolor") == 0)
11631             {
11632               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11633                 &montage_info->alpha_color,exception);
11634               for (next=image; next; next=next->next)
11635                 next->alpha_color=montage_info->alpha_color;
11636               break;
11637             }
11638           if (LocaleCompare(attribute,"mode") == 0)
11639             {
11640               ssize_t
11641                 in;
11642
11643               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11644                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11645               switch (in)
11646               {
11647                 default:
11648                 {
11649                   ThrowPerlException(exception,OptionError,
11650                     "UnrecognizedModeType",SvPV(ST(i),na));
11651                   break;
11652                 }
11653                 case FrameMode:
11654                 {
11655                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11656                   montage_info->shadow=MagickTrue;
11657                   break;
11658                 }
11659                 case UnframeMode:
11660                 {
11661                   montage_info->frame=(char *) NULL;
11662                   montage_info->shadow=MagickFalse;
11663                   montage_info->border_width=0;
11664                   break;
11665                 }
11666                 case ConcatenateMode:
11667                 {
11668                   montage_info->frame=(char *) NULL;
11669                   montage_info->shadow=MagickFalse;
11670                   (void) CloneString(&montage_info->geometry,"+0+0");
11671                   montage_info->border_width=0;
11672                 }
11673               }
11674               break;
11675             }
11676           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11677             attribute);
11678           break;
11679         }
11680         case 'P':
11681         case 'p':
11682         {
11683           if (LocaleCompare(attribute,"pointsize") == 0)
11684             {
11685               montage_info->pointsize=SvIV(ST(i));
11686               break;
11687             }
11688           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11689             attribute);
11690           break;
11691         }
11692         case 'S':
11693         case 's':
11694         {
11695           if (LocaleCompare(attribute,"shadow") == 0)
11696             {
11697               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11698                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11699               if (sp < 0)
11700                 {
11701                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11702                     SvPV(ST(i),na));
11703                   break;
11704                 }
11705              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11706              break;
11707             }
11708           if (LocaleCompare(attribute,"stroke") == 0)
11709             {
11710               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11711                 &montage_info->stroke,exception);
11712               break;
11713             }
11714           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11715             attribute);
11716           break;
11717         }
11718         case 'T':
11719         case 't':
11720         {
11721           if (LocaleCompare(attribute,"texture") == 0)
11722             {
11723               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11724               break;
11725             }
11726           if (LocaleCompare(attribute,"tile") == 0)
11727             {
11728               char *p=SvPV(ST(i),na);
11729               if (IsGeometry(p) == MagickFalse)
11730                 {
11731                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11732                     p);
11733                   break;
11734                 }
11735               (void) CloneString(&montage_info->tile,p);
11736               if (*p == '\0')
11737                 montage_info->tile=(char *) NULL;
11738               break;
11739             }
11740           if (LocaleCompare(attribute,"title") == 0)
11741             {
11742               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11743               break;
11744             }
11745           if (LocaleCompare(attribute,"transparent") == 0)
11746             {
11747               PixelInfo
11748                 transparent_color;
11749
11750               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11751                 &transparent_color,exception);
11752               for (next=image; next; next=next->next)
11753                 (void) TransparentPaintImage(next,&transparent_color,
11754                   TransparentAlpha,MagickFalse,exception);
11755               break;
11756             }
11757           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11758             attribute);
11759           break;
11760         }
11761         default:
11762         {
11763           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11764             attribute);
11765           break;
11766         }
11767       }
11768     }
11769     image=MontageImageList(info->image_info,montage_info,image,exception);
11770     montage_info=DestroyMontageInfo(montage_info);
11771     if (image == (Image *) NULL)
11772       goto PerlException;
11773     if (transparent_color.alpha != TransparentAlpha)
11774       for (next=image; next; next=next->next)
11775         (void) TransparentPaintImage(next,&transparent_color,
11776           TransparentAlpha,MagickFalse,exception);
11777     for (  ; image; image=image->next)
11778     {
11779       AddImageToRegistry(sv,image);
11780       rv=newRV(sv);
11781       av_push(av,sv_bless(rv,hv));
11782       SvREFCNT_dec(sv);
11783     }
11784     exception=DestroyExceptionInfo(exception);
11785     ST(0)=av_reference;
11786     SvREFCNT_dec(perl_exception);
11787     XSRETURN(1);
11788
11789   PerlException:
11790     InheritPerlException(exception,perl_exception);
11791     exception=DestroyExceptionInfo(exception);
11792     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11793     SvPOK_on(perl_exception);
11794     ST(0)=sv_2mortal(perl_exception);
11795     XSRETURN(1);
11796   }
11797 \f
11798 #
11799 ###############################################################################
11800 #                                                                             #
11801 #                                                                             #
11802 #                                                                             #
11803 #   M o r p h                                                                 #
11804 #                                                                             #
11805 #                                                                             #
11806 #                                                                             #
11807 ###############################################################################
11808 #
11809 #
11810 void
11811 Morph(ref,...)
11812   Image::Magick ref=NO_INIT
11813   ALIAS:
11814     MorphImage  = 1
11815     morph       = 2
11816     morphimage  = 3
11817   PPCODE:
11818   {
11819     AV
11820       *av;
11821
11822     char
11823       *attribute;
11824
11825     ExceptionInfo
11826       *exception;
11827
11828     HV
11829       *hv;
11830
11831     Image
11832       *image;
11833
11834     register ssize_t
11835       i;
11836
11837     ssize_t
11838       number_frames;
11839
11840     struct PackageInfo
11841       *info;
11842
11843     SV
11844       *av_reference,
11845       *perl_exception,
11846       *reference,
11847       *rv,
11848       *sv;
11849
11850     PERL_UNUSED_VAR(ref);
11851     PERL_UNUSED_VAR(ix);
11852     exception=AcquireExceptionInfo();
11853     perl_exception=newSVpv("",0);
11854     sv=NULL;
11855     av=NULL;
11856     attribute=NULL;
11857     if (sv_isobject(ST(0)) == 0)
11858       {
11859         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11860           PackageName);
11861         goto PerlException;
11862       }
11863     reference=SvRV(ST(0));
11864     hv=SvSTASH(reference);
11865     av=newAV();
11866     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11867     SvREFCNT_dec(av);
11868     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11869     if (image == (Image *) NULL)
11870       {
11871         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11872           PackageName);
11873         goto PerlException;
11874       }
11875     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11876     /*
11877       Get attribute.
11878     */
11879     number_frames=30;
11880     for (i=2; i < items; i+=2)
11881     {
11882       attribute=(char *) SvPV(ST(i-1),na);
11883       switch (*attribute)
11884       {
11885         case 'F':
11886         case 'f':
11887         {
11888           if (LocaleCompare(attribute,"frames") == 0)
11889             {
11890               number_frames=SvIV(ST(i));
11891               break;
11892             }
11893           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11894             attribute);
11895           break;
11896         }
11897         default:
11898         {
11899           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11900             attribute);
11901           break;
11902         }
11903       }
11904     }
11905     image=MorphImages(image,number_frames,exception);
11906     if (image == (Image *) NULL)
11907       goto PerlException;
11908     for ( ; image; image=image->next)
11909     {
11910       AddImageToRegistry(sv,image);
11911       rv=newRV(sv);
11912       av_push(av,sv_bless(rv,hv));
11913       SvREFCNT_dec(sv);
11914     }
11915     exception=DestroyExceptionInfo(exception);
11916     ST(0)=av_reference;
11917     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11918     XSRETURN(1);
11919
11920   PerlException:
11921     InheritPerlException(exception,perl_exception);
11922     exception=DestroyExceptionInfo(exception);
11923     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11924     SvPOK_on(perl_exception);
11925     ST(0)=sv_2mortal(perl_exception);
11926     XSRETURN(1);
11927   }
11928 \f
11929 #
11930 ###############################################################################
11931 #                                                                             #
11932 #                                                                             #
11933 #                                                                             #
11934 #   M o s a i c                                                               #
11935 #                                                                             #
11936 #                                                                             #
11937 #                                                                             #
11938 ###############################################################################
11939 #
11940 #
11941 void
11942 Mosaic(ref)
11943   Image::Magick ref=NO_INIT
11944   ALIAS:
11945     MosaicImage   = 1
11946     mosaic        = 2
11947     mosaicimage   = 3
11948   PPCODE:
11949   {
11950     AV
11951       *av;
11952
11953     ExceptionInfo
11954       *exception;
11955
11956     HV
11957       *hv;
11958
11959     Image
11960       *image;
11961
11962     struct PackageInfo
11963       *info;
11964
11965     SV
11966       *perl_exception,
11967       *reference,
11968       *rv,
11969       *sv;
11970
11971     PERL_UNUSED_VAR(ref);
11972     PERL_UNUSED_VAR(ix);
11973     exception=AcquireExceptionInfo();
11974     perl_exception=newSVpv("",0);
11975     sv=NULL;
11976     if (sv_isobject(ST(0)) == 0)
11977       {
11978         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11979           PackageName);
11980         goto PerlException;
11981       }
11982     reference=SvRV(ST(0));
11983     hv=SvSTASH(reference);
11984     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11985     if (image == (Image *) NULL)
11986       {
11987         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11988           PackageName);
11989         goto PerlException;
11990       }
11991     image=MergeImageLayers(image,MosaicLayer,exception);
11992     /*
11993       Create blessed Perl array for the returned image.
11994     */
11995     av=newAV();
11996     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11997     SvREFCNT_dec(av);
11998     AddImageToRegistry(sv,image);
11999     rv=newRV(sv);
12000     av_push(av,sv_bless(rv,hv));
12001     SvREFCNT_dec(sv);
12002     (void) CopyMagickString(info->image_info->filename,image->filename,
12003       MagickPathExtent);
12004     SetImageInfo(info->image_info,0,exception);
12005     exception=DestroyExceptionInfo(exception);
12006     SvREFCNT_dec(perl_exception);
12007     XSRETURN(1);
12008
12009   PerlException:
12010     InheritPerlException(exception,perl_exception);
12011     exception=DestroyExceptionInfo(exception);
12012     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12013     SvPOK_on(perl_exception);  /* return messages in string context */
12014     ST(0)=sv_2mortal(perl_exception);
12015     XSRETURN(1);
12016   }
12017 \f
12018 #
12019 ###############################################################################
12020 #                                                                             #
12021 #                                                                             #
12022 #                                                                             #
12023 #   P i n g                                                                   #
12024 #                                                                             #
12025 #                                                                             #
12026 #                                                                             #
12027 ###############################################################################
12028 #
12029 #
12030 void
12031 Ping(ref,...)
12032   Image::Magick ref=NO_INIT
12033   ALIAS:
12034     PingImage  = 1
12035     ping       = 2
12036     pingimage  = 3
12037   PPCODE:
12038   {
12039     AV
12040       *av;
12041
12042     char
12043       **keep,
12044       **list;
12045
12046     ExceptionInfo
12047       *exception;
12048
12049     Image
12050       *image,
12051       *next;
12052
12053     int
12054       n;
12055
12056     MagickBooleanType
12057       status;
12058
12059     register char
12060       **p;
12061
12062     register ssize_t
12063       i;
12064
12065     ssize_t
12066       ac;
12067
12068     STRLEN
12069       *length;
12070
12071     struct PackageInfo
12072       *info,
12073       *package_info;
12074
12075     SV
12076       *perl_exception,
12077       *reference;
12078
12079     size_t
12080       count;
12081
12082     PERL_UNUSED_VAR(ref);
12083     PERL_UNUSED_VAR(ix);
12084     exception=AcquireExceptionInfo();
12085     perl_exception=newSVpv("",0);
12086     package_info=(struct PackageInfo *) NULL;
12087     ac=(items < 2) ? 1 : items-1;
12088     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12089     keep=list;
12090     length=(STRLEN *) NULL;
12091     if (list == (char **) NULL)
12092       {
12093         ThrowPerlException(exception,ResourceLimitError,
12094           "MemoryAllocationFailed",PackageName);
12095         goto PerlException;
12096       }
12097     keep=list;
12098     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12099     if (length == (STRLEN *) NULL)
12100       {
12101         ThrowPerlException(exception,ResourceLimitError,
12102           "MemoryAllocationFailed",PackageName);
12103         goto PerlException;
12104       }
12105     if (sv_isobject(ST(0)) == 0)
12106       {
12107         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12108           PackageName);
12109         goto PerlException;
12110       }
12111     reference=SvRV(ST(0));
12112     if (SvTYPE(reference) != SVt_PVAV)
12113       {
12114         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12115           PackageName);
12116         goto PerlException;
12117       }
12118     av=(AV *) reference;
12119     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12120       exception);
12121     package_info=ClonePackageInfo(info,exception);
12122     n=1;
12123     if (items <= 1)
12124       *list=(char *) (*package_info->image_info->filename ?
12125         package_info->image_info->filename : "XC:black");
12126     else
12127       for (n=0, i=0; i < ac; i++)
12128       {
12129         list[n]=(char *) SvPV(ST(i+1),length[n]);
12130         if ((items >= 3) && strEQcase(list[n],"blob"))
12131           {
12132             void
12133               *blob;
12134
12135             i++;
12136             blob=(void *) (SvPV(ST(i+1),length[n]));
12137             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12138           }
12139         if ((items >= 3) && strEQcase(list[n],"filename"))
12140           continue;
12141         if ((items >= 3) && strEQcase(list[n],"file"))
12142           {
12143             FILE
12144               *file;
12145
12146             PerlIO
12147               *io_info;
12148
12149             i++;
12150             io_info=IoIFP(sv_2io(ST(i+1)));
12151             if (io_info == (PerlIO *) NULL)
12152               {
12153                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12154                   PackageName);
12155                 continue;
12156               }
12157             file=PerlIO_findFILE(io_info);
12158             if (file == (FILE *) NULL)
12159               {
12160                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12161                   PackageName);
12162                 continue;
12163               }
12164             SetImageInfoFile(package_info->image_info,file);
12165           }
12166         if ((items >= 3) && strEQcase(list[n],"magick"))
12167           continue;
12168         n++;
12169       }
12170     list[n]=(char *) NULL;
12171     keep=list;
12172     status=ExpandFilenames(&n,&list);
12173     if (status == MagickFalse)
12174       {
12175         ThrowPerlException(exception,ResourceLimitError,
12176           "MemoryAllocationFailed",PackageName);
12177         goto PerlException;
12178       }
12179     count=0;
12180     for (i=0; i < n; i++)
12181     {
12182       (void) CopyMagickString(package_info->image_info->filename,list[i],
12183         MagickPathExtent);
12184       image=PingImage(package_info->image_info,exception);
12185       if (image == (Image *) NULL)
12186         break;
12187       if ((package_info->image_info->file != (FILE *) NULL) ||
12188           (package_info->image_info->blob != (void *) NULL))
12189         DisassociateImageStream(image);
12190       count+=GetImageListLength(image);
12191       EXTEND(sp,4*count);
12192       for (next=image; next; next=next->next)
12193       {
12194         PUSHs(sv_2mortal(newSViv(next->columns)));
12195         PUSHs(sv_2mortal(newSViv(next->rows)));
12196         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12197         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12198       }
12199       image=DestroyImageList(image);
12200     }
12201     /*
12202       Free resources.
12203     */
12204     for (i=0; i < n; i++)
12205       if (list[i] != (char *) NULL)
12206         for (p=keep; list[i] != *p++; )
12207           if (*p == NULL)
12208             {
12209               list[i]=(char *) RelinquishMagickMemory(list[i]);
12210               break;
12211             }
12212
12213   PerlException:
12214     if (package_info != (struct PackageInfo *) NULL)
12215       DestroyPackageInfo(package_info);
12216     if (list && (list != keep))
12217       list=(char **) RelinquishMagickMemory(list);
12218     if (keep)
12219       keep=(char **) RelinquishMagickMemory(keep);
12220     if (length)
12221       length=(STRLEN *) RelinquishMagickMemory(length);
12222     InheritPerlException(exception,perl_exception);
12223     exception=DestroyExceptionInfo(exception);
12224     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12225   }
12226 \f
12227 #
12228 ###############################################################################
12229 #                                                                             #
12230 #                                                                             #
12231 #                                                                             #
12232 #   P r e v i e w                                                             #
12233 #                                                                             #
12234 #                                                                             #
12235 #                                                                             #
12236 ###############################################################################
12237 #
12238 #
12239 void
12240 Preview(ref,...)
12241   Image::Magick ref=NO_INIT
12242   ALIAS:
12243     PreviewImage = 1
12244     preview      = 2
12245     previewimage = 3
12246   PPCODE:
12247   {
12248     AV
12249       *av;
12250
12251     ExceptionInfo
12252       *exception;
12253
12254     HV
12255       *hv;
12256
12257     Image
12258       *image,
12259       *preview_image;
12260
12261     PreviewType
12262       preview_type;
12263
12264     struct PackageInfo
12265       *info;
12266
12267     SV
12268       *av_reference,
12269       *perl_exception,
12270       *reference,
12271       *rv,
12272       *sv;
12273
12274     PERL_UNUSED_VAR(ref);
12275     PERL_UNUSED_VAR(ix);
12276     exception=AcquireExceptionInfo();
12277     perl_exception=newSVpv("",0);
12278     sv=NULL;
12279     av=NULL;
12280     if (sv_isobject(ST(0)) == 0)
12281       {
12282         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12283           PackageName);
12284         goto PerlException;
12285       }
12286     reference=SvRV(ST(0));
12287     hv=SvSTASH(reference);
12288     av=newAV();
12289     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12290     SvREFCNT_dec(av);
12291     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12292     if (image == (Image *) NULL)
12293       {
12294         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12295           PackageName);
12296         goto PerlException;
12297       }
12298     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12299     preview_type=GammaPreview;
12300     if (items > 1)
12301       preview_type=(PreviewType)
12302         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12303     for ( ; image; image=image->next)
12304     {
12305       preview_image=PreviewImage(image,preview_type,exception);
12306       if (preview_image == (Image *) NULL)
12307         goto PerlException;
12308       AddImageToRegistry(sv,preview_image);
12309       rv=newRV(sv);
12310       av_push(av,sv_bless(rv,hv));
12311       SvREFCNT_dec(sv);
12312     }
12313     exception=DestroyExceptionInfo(exception);
12314     ST(0)=av_reference;
12315     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12316     XSRETURN(1);
12317
12318   PerlException:
12319     InheritPerlException(exception,perl_exception);
12320     exception=DestroyExceptionInfo(exception);
12321     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12322     SvPOK_on(perl_exception);
12323     ST(0)=sv_2mortal(perl_exception);
12324     XSRETURN(1);
12325   }
12326 \f
12327 #
12328 ###############################################################################
12329 #                                                                             #
12330 #                                                                             #
12331 #                                                                             #
12332 #   Q u e r y C o l o r                                                       #
12333 #                                                                             #
12334 #                                                                             #
12335 #                                                                             #
12336 ###############################################################################
12337 #
12338 #
12339 void
12340 QueryColor(ref,...)
12341   Image::Magick ref=NO_INIT
12342   ALIAS:
12343     querycolor = 1
12344   PPCODE:
12345   {
12346     char
12347       *name;
12348
12349     ExceptionInfo
12350       *exception;
12351
12352     PixelInfo
12353       color;
12354
12355     register ssize_t
12356       i;
12357
12358     SV
12359       *perl_exception;
12360
12361     PERL_UNUSED_VAR(ref);
12362     PERL_UNUSED_VAR(ix);
12363     exception=AcquireExceptionInfo();
12364     perl_exception=newSVpv("",0);
12365     if (items == 1)
12366       {
12367         const ColorInfo
12368           **colorlist;
12369
12370         size_t
12371           colors;
12372
12373         colorlist=GetColorInfoList("*",&colors,exception);
12374         EXTEND(sp,colors);
12375         for (i=0; i < (ssize_t) colors; i++)
12376         {
12377           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12378         }
12379         colorlist=(const ColorInfo **)
12380           RelinquishMagickMemory((ColorInfo **) colorlist);
12381         goto PerlException;
12382       }
12383     EXTEND(sp,5*items);
12384     for (i=1; i < items; i++)
12385     {
12386       name=(char *) SvPV(ST(i),na);
12387       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12388         {
12389           PUSHs(&sv_undef);
12390           continue;
12391         }
12392       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12393       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12394       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12395       if (color.colorspace == CMYKColorspace)
12396         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12397       if (color.alpha_trait != UndefinedPixelTrait)
12398         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12399     }
12400
12401   PerlException:
12402     InheritPerlException(exception,perl_exception);
12403     exception=DestroyExceptionInfo(exception);
12404     SvREFCNT_dec(perl_exception);
12405   }
12406 \f
12407 #
12408 ###############################################################################
12409 #                                                                             #
12410 #                                                                             #
12411 #                                                                             #
12412 #   Q u e r y C o l o r N a m e                                               #
12413 #                                                                             #
12414 #                                                                             #
12415 #                                                                             #
12416 ###############################################################################
12417 #
12418 #
12419 void
12420 QueryColorname(ref,...)
12421   Image::Magick ref=NO_INIT
12422   ALIAS:
12423     querycolorname = 1
12424   PPCODE:
12425   {
12426     AV
12427       *av;
12428
12429     char
12430       message[MagickPathExtent];
12431
12432     ExceptionInfo
12433       *exception;
12434
12435     Image
12436       *image;
12437
12438     PixelInfo
12439       target_color;
12440
12441     register ssize_t
12442       i;
12443
12444     struct PackageInfo
12445       *info;
12446
12447     SV
12448       *perl_exception,
12449       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12450
12451     PERL_UNUSED_VAR(ref);
12452     PERL_UNUSED_VAR(ix);
12453     exception=AcquireExceptionInfo();
12454     perl_exception=newSVpv("",0);
12455     reference=SvRV(ST(0));
12456     av=(AV *) reference;
12457     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12458       exception);
12459     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12460     if (image == (Image *) NULL)
12461       {
12462         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12463           PackageName);
12464         goto PerlException;
12465       }
12466     EXTEND(sp,items);
12467     for (i=1; i < items; i++)
12468     {
12469       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12470         exception);
12471       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12472         exception);
12473       PUSHs(sv_2mortal(newSVpv(message,0)));
12474     }
12475
12476   PerlException:
12477     InheritPerlException(exception,perl_exception);
12478     exception=DestroyExceptionInfo(exception);
12479     SvREFCNT_dec(perl_exception);
12480   }
12481 \f
12482 #
12483 ###############################################################################
12484 #                                                                             #
12485 #                                                                             #
12486 #                                                                             #
12487 #   Q u e r y F o n t                                                         #
12488 #                                                                             #
12489 #                                                                             #
12490 #                                                                             #
12491 ###############################################################################
12492 #
12493 #
12494 void
12495 QueryFont(ref,...)
12496   Image::Magick ref=NO_INIT
12497   ALIAS:
12498     queryfont = 1
12499   PPCODE:
12500   {
12501     char
12502       *name,
12503       message[MagickPathExtent];
12504
12505     ExceptionInfo
12506       *exception;
12507
12508     register ssize_t
12509       i;
12510
12511     SV
12512       *perl_exception;
12513
12514     volatile const TypeInfo
12515       *type_info;
12516
12517     PERL_UNUSED_VAR(ref);
12518     PERL_UNUSED_VAR(ix);
12519     exception=AcquireExceptionInfo();
12520     perl_exception=newSVpv("",0);
12521     if (items == 1)
12522       {
12523         const TypeInfo
12524           **typelist;
12525
12526         size_t
12527           types;
12528
12529         typelist=GetTypeInfoList("*",&types,exception);
12530         EXTEND(sp,types);
12531         for (i=0; i < (ssize_t) types; i++)
12532         {
12533           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12534         }
12535         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12536           typelist);
12537         goto PerlException;
12538       }
12539     EXTEND(sp,10*items);
12540     for (i=1; i < items; i++)
12541     {
12542       name=(char *) SvPV(ST(i),na);
12543       type_info=GetTypeInfo(name,exception);
12544       if (type_info == (TypeInfo *) NULL)
12545         {
12546           PUSHs(&sv_undef);
12547           continue;
12548         }
12549       if (type_info->name == (char *) NULL)
12550         PUSHs(&sv_undef);
12551       else
12552         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12553       if (type_info->description == (char *) NULL)
12554         PUSHs(&sv_undef);
12555       else
12556         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12557       if (type_info->family == (char *) NULL)
12558         PUSHs(&sv_undef);
12559       else
12560         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12561       if (type_info->style == UndefinedStyle)
12562         PUSHs(&sv_undef);
12563       else
12564         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12565           type_info->style),0)));
12566       if (type_info->stretch == UndefinedStretch)
12567         PUSHs(&sv_undef);
12568       else
12569         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12570           type_info->stretch),0)));
12571       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12572         type_info->weight);
12573       PUSHs(sv_2mortal(newSVpv(message,0)));
12574       if (type_info->encoding == (char *) NULL)
12575         PUSHs(&sv_undef);
12576       else
12577         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12578       if (type_info->foundry == (char *) NULL)
12579         PUSHs(&sv_undef);
12580       else
12581         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12582       if (type_info->format == (char *) NULL)
12583         PUSHs(&sv_undef);
12584       else
12585         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12586       if (type_info->metrics == (char *) NULL)
12587         PUSHs(&sv_undef);
12588       else
12589         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12590       if (type_info->glyphs == (char *) NULL)
12591         PUSHs(&sv_undef);
12592       else
12593         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12594     }
12595
12596   PerlException:
12597     InheritPerlException(exception,perl_exception);
12598     exception=DestroyExceptionInfo(exception);
12599     SvREFCNT_dec(perl_exception);
12600   }
12601 \f
12602 #
12603 ###############################################################################
12604 #                                                                             #
12605 #                                                                             #
12606 #                                                                             #
12607 #   Q u e r y F o n t M e t r i c s                                           #
12608 #                                                                             #
12609 #                                                                             #
12610 #                                                                             #
12611 ###############################################################################
12612 #
12613 #
12614 void
12615 QueryFontMetrics(ref,...)
12616   Image::Magick ref=NO_INIT
12617   ALIAS:
12618     queryfontmetrics = 1
12619   PPCODE:
12620   {
12621     AffineMatrix
12622       affine,
12623       current;
12624
12625     AV
12626       *av;
12627
12628     char
12629       *attribute;
12630
12631     double
12632       x,
12633       y;
12634
12635     DrawInfo
12636       *draw_info;
12637
12638     ExceptionInfo
12639       *exception;
12640
12641     GeometryInfo
12642       geometry_info;
12643
12644     Image
12645       *image;
12646
12647     MagickBooleanType
12648       status;
12649
12650     MagickStatusType
12651       flags;
12652
12653     register ssize_t
12654       i;
12655
12656     ssize_t
12657       type;
12658
12659     struct PackageInfo
12660       *info,
12661       *package_info;
12662
12663     SV
12664       *perl_exception,
12665       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12666
12667     TypeMetric
12668       metrics;
12669
12670     PERL_UNUSED_VAR(ref);
12671     PERL_UNUSED_VAR(ix);
12672     exception=AcquireExceptionInfo();
12673     package_info=(struct PackageInfo *) NULL;
12674     perl_exception=newSVpv("",0);
12675     reference=SvRV(ST(0));
12676     av=(AV *) reference;
12677     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12678       exception);
12679     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12680     if (image == (Image *) NULL)
12681       {
12682         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12683           PackageName);
12684         goto PerlException;
12685       }
12686     package_info=ClonePackageInfo(info,exception);
12687     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12688     CloneString(&draw_info->text,"");
12689     current=draw_info->affine;
12690     GetAffineMatrix(&affine);
12691     x=0.0;
12692     y=0.0;
12693     EXTEND(sp,7*items);
12694     for (i=2; i < items; i+=2)
12695     {
12696       attribute=(char *) SvPV(ST(i-1),na);
12697       switch (*attribute)
12698       {
12699         case 'A':
12700         case 'a':
12701         {
12702           if (LocaleCompare(attribute,"antialias") == 0)
12703             {
12704               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12705                 SvPV(ST(i),na));
12706               if (type < 0)
12707                 {
12708                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12709                     SvPV(ST(i),na));
12710                   break;
12711                 }
12712               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12713               break;
12714             }
12715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12716             attribute);
12717           break;
12718         }
12719         case 'd':
12720         case 'D':
12721         {
12722           if (LocaleCompare(attribute,"density") == 0)
12723             {
12724               CloneString(&draw_info->density,SvPV(ST(i),na));
12725               break;
12726             }
12727           if (LocaleCompare(attribute,"direction") == 0)
12728             {
12729               draw_info->direction=(DirectionType) ParseCommandOption(
12730                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12731               break;
12732             }
12733           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12734             attribute);
12735           break;
12736         }
12737         case 'e':
12738         case 'E':
12739         {
12740           if (LocaleCompare(attribute,"encoding") == 0)
12741             {
12742               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12743               break;
12744             }
12745           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12746             attribute);
12747           break;
12748         }
12749         case 'f':
12750         case 'F':
12751         {
12752           if (LocaleCompare(attribute,"family") == 0)
12753             {
12754               CloneString(&draw_info->family,SvPV(ST(i),na));
12755               break;
12756             }
12757           if (LocaleCompare(attribute,"fill") == 0)
12758             {
12759               if (info)
12760                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12761                   &draw_info->fill,exception);
12762               break;
12763             }
12764           if (LocaleCompare(attribute,"font") == 0)
12765             {
12766               CloneString(&draw_info->font,SvPV(ST(i),na));
12767               break;
12768             }
12769           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12770             attribute);
12771           break;
12772         }
12773         case 'g':
12774         case 'G':
12775         {
12776           if (LocaleCompare(attribute,"geometry") == 0)
12777             {
12778               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12779               break;
12780             }
12781           if (LocaleCompare(attribute,"gravity") == 0)
12782             {
12783               draw_info->gravity=(GravityType) ParseCommandOption(
12784                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12785               break;
12786             }
12787           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12788             attribute);
12789           break;
12790         }
12791         case 'i':
12792         case 'I':
12793         {
12794           if (LocaleCompare(attribute,"interline-spacing") == 0)
12795             {
12796               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12797               draw_info->interline_spacing=geometry_info.rho;
12798               break;
12799             }
12800           if (LocaleCompare(attribute,"interword-spacing") == 0)
12801             {
12802               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12803               draw_info->interword_spacing=geometry_info.rho;
12804               break;
12805             }
12806           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12807             attribute);
12808           break;
12809         }
12810         case 'k':
12811         case 'K':
12812         {
12813           if (LocaleCompare(attribute,"kerning") == 0)
12814             {
12815               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12816               draw_info->kerning=geometry_info.rho;
12817               break;
12818             }
12819           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12820             attribute);
12821           break;
12822         }
12823         case 'p':
12824         case 'P':
12825         {
12826           if (LocaleCompare(attribute,"pointsize") == 0)
12827             {
12828               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12829               draw_info->pointsize=geometry_info.rho;
12830               break;
12831             }
12832           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12833             attribute);
12834           break;
12835         }
12836         case 'r':
12837         case 'R':
12838         {
12839           if (LocaleCompare(attribute,"rotate") == 0)
12840             {
12841               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12842               affine.rx=geometry_info.rho;
12843               affine.ry=geometry_info.sigma;
12844               if ((flags & SigmaValue) == 0)
12845                 affine.ry=affine.rx;
12846               break;
12847             }
12848           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12849             attribute);
12850           break;
12851         }
12852         case 's':
12853         case 'S':
12854         {
12855           if (LocaleCompare(attribute,"scale") == 0)
12856             {
12857               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12858               affine.sx=geometry_info.rho;
12859               affine.sy=geometry_info.sigma;
12860               if ((flags & SigmaValue) == 0)
12861                 affine.sy=affine.sx;
12862               break;
12863             }
12864           if (LocaleCompare(attribute,"skew") == 0)
12865             {
12866               double
12867                 x_angle,
12868                 y_angle;
12869
12870               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12871               x_angle=geometry_info.rho;
12872               y_angle=geometry_info.sigma;
12873               if ((flags & SigmaValue) == 0)
12874                 y_angle=x_angle;
12875               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12876               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12877               break;
12878             }
12879           if (LocaleCompare(attribute,"stroke") == 0)
12880             {
12881               if (info)
12882                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12883                   &draw_info->stroke,exception);
12884               break;
12885             }
12886           if (LocaleCompare(attribute,"style") == 0)
12887             {
12888               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12889                 SvPV(ST(i),na));
12890               if (type < 0)
12891                 {
12892                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12893                     SvPV(ST(i),na));
12894                   break;
12895                 }
12896               draw_info->style=(StyleType) type;
12897               break;
12898             }
12899           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12900             attribute);
12901           break;
12902         }
12903         case 't':
12904         case 'T':
12905         {
12906           if (LocaleCompare(attribute,"text") == 0)
12907             {
12908               CloneString(&draw_info->text,SvPV(ST(i),na));
12909               break;
12910             }
12911           if (LocaleCompare(attribute,"translate") == 0)
12912             {
12913               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12914               affine.tx=geometry_info.rho;
12915               affine.ty=geometry_info.sigma;
12916               if ((flags & SigmaValue) == 0)
12917                 affine.ty=affine.tx;
12918               break;
12919             }
12920           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12921             attribute);
12922           break;
12923         }
12924         case 'w':
12925         case 'W':
12926         {
12927           if (LocaleCompare(attribute,"weight") == 0)
12928             {
12929               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12930               draw_info->weight=(size_t) geometry_info.rho;
12931               break;
12932             }
12933           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12934             attribute);
12935           break;
12936         }
12937         case 'x':
12938         case 'X':
12939         {
12940           if (LocaleCompare(attribute,"x") == 0)
12941             {
12942               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12943               x=geometry_info.rho;
12944               break;
12945             }
12946           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12947             attribute);
12948           break;
12949         }
12950         case 'y':
12951         case 'Y':
12952         {
12953           if (LocaleCompare(attribute,"y") == 0)
12954             {
12955               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12956               y=geometry_info.rho;
12957               break;
12958             }
12959           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12960             attribute);
12961           break;
12962         }
12963         default:
12964         {
12965           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12966             attribute);
12967           break;
12968         }
12969       }
12970     }
12971     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12972     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12973     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12974     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12975     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12976     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12977     if (draw_info->geometry == (char *) NULL)
12978       {
12979         draw_info->geometry=AcquireString((char *) NULL);
12980         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12981           "%.15g,%.15g",x,y);
12982       }
12983     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12984     (void) CatchImageException(image);
12985     if (status == MagickFalse)
12986       PUSHs(&sv_undef);
12987     else
12988       {
12989         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12990         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12991         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12992         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12993         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12994         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12995         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12996         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12997         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12998         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12999         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13000         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13001         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13002       }
13003     draw_info=DestroyDrawInfo(draw_info);
13004
13005   PerlException:
13006     if (package_info != (struct PackageInfo *) NULL)
13007       DestroyPackageInfo(package_info);
13008     InheritPerlException(exception,perl_exception);
13009     exception=DestroyExceptionInfo(exception);
13010     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13011   }
13012 \f
13013 #
13014 ###############################################################################
13015 #                                                                             #
13016 #                                                                             #
13017 #                                                                             #
13018 #   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                         #
13019 #                                                                             #
13020 #                                                                             #
13021 #                                                                             #
13022 ###############################################################################
13023 #
13024 #
13025 void
13026 QueryMultilineFontMetrics(ref,...)
13027   Image::Magick ref=NO_INIT
13028   ALIAS:
13029     querymultilinefontmetrics = 1
13030   PPCODE:
13031   {
13032     AffineMatrix
13033       affine,
13034       current;
13035
13036     AV
13037       *av;
13038
13039     char
13040       *attribute;
13041
13042     double
13043       x,
13044       y;
13045
13046     DrawInfo
13047       *draw_info;
13048
13049     ExceptionInfo
13050       *exception;
13051
13052     GeometryInfo
13053       geometry_info;
13054
13055     Image
13056       *image;
13057
13058     MagickBooleanType
13059       status;
13060
13061     MagickStatusType
13062       flags;
13063
13064     register ssize_t
13065       i;
13066
13067     ssize_t
13068       type;
13069
13070     struct PackageInfo
13071       *info,
13072       *package_info;
13073
13074     SV
13075       *perl_exception,
13076       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13077
13078     TypeMetric
13079       metrics;
13080
13081     PERL_UNUSED_VAR(ref);
13082     PERL_UNUSED_VAR(ix);
13083     exception=AcquireExceptionInfo();
13084     package_info=(struct PackageInfo *) NULL;
13085     perl_exception=newSVpv("",0);
13086     reference=SvRV(ST(0));
13087     av=(AV *) reference;
13088     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13089       exception);
13090     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13091     if (image == (Image *) NULL)
13092       {
13093         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13094           PackageName);
13095         goto PerlException;
13096       }
13097     package_info=ClonePackageInfo(info,exception);
13098     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
13099     CloneString(&draw_info->text,"");
13100     current=draw_info->affine;
13101     GetAffineMatrix(&affine);
13102     x=0.0;
13103     y=0.0;
13104     EXTEND(sp,7*items);
13105     for (i=2; i < items; i+=2)
13106     {
13107       attribute=(char *) SvPV(ST(i-1),na);
13108       switch (*attribute)
13109       {
13110         case 'A':
13111         case 'a':
13112         {
13113           if (LocaleCompare(attribute,"antialias") == 0)
13114             {
13115               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13116                 SvPV(ST(i),na));
13117               if (type < 0)
13118                 {
13119                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13120                     SvPV(ST(i),na));
13121                   break;
13122                 }
13123               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13124               break;
13125             }
13126           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13127             attribute);
13128           break;
13129         }
13130         case 'd':
13131         case 'D':
13132         {
13133           if (LocaleCompare(attribute,"density") == 0)
13134             {
13135               CloneString(&draw_info->density,SvPV(ST(i),na));
13136               break;
13137             }
13138           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13139             attribute);
13140           break;
13141         }
13142         case 'e':
13143         case 'E':
13144         {
13145           if (LocaleCompare(attribute,"encoding") == 0)
13146             {
13147               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13148               break;
13149             }
13150           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13151             attribute);
13152           break;
13153         }
13154         case 'f':
13155         case 'F':
13156         {
13157           if (LocaleCompare(attribute,"family") == 0)
13158             {
13159               CloneString(&draw_info->family,SvPV(ST(i),na));
13160               break;
13161             }
13162           if (LocaleCompare(attribute,"fill") == 0)
13163             {
13164               if (info)
13165                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13166                   &draw_info->fill,exception);
13167               break;
13168             }
13169           if (LocaleCompare(attribute,"font") == 0)
13170             {
13171               CloneString(&draw_info->font,SvPV(ST(i),na));
13172               break;
13173             }
13174           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13175             attribute);
13176           break;
13177         }
13178         case 'g':
13179         case 'G':
13180         {
13181           if (LocaleCompare(attribute,"geometry") == 0)
13182             {
13183               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13184               break;
13185             }
13186           if (LocaleCompare(attribute,"gravity") == 0)
13187             {
13188               draw_info->gravity=(GravityType) ParseCommandOption(
13189                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13190               break;
13191             }
13192           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13193             attribute);
13194           break;
13195         }
13196         case 'p':
13197         case 'P':
13198         {
13199           if (LocaleCompare(attribute,"pointsize") == 0)
13200             {
13201               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13202               draw_info->pointsize=geometry_info.rho;
13203               break;
13204             }
13205           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13206             attribute);
13207           break;
13208         }
13209         case 'r':
13210         case 'R':
13211         {
13212           if (LocaleCompare(attribute,"rotate") == 0)
13213             {
13214               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13215               affine.rx=geometry_info.rho;
13216               affine.ry=geometry_info.sigma;
13217               if ((flags & SigmaValue) == 0)
13218                 affine.ry=affine.rx;
13219               break;
13220             }
13221           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13222             attribute);
13223           break;
13224         }
13225         case 's':
13226         case 'S':
13227         {
13228           if (LocaleCompare(attribute,"scale") == 0)
13229             {
13230               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13231               affine.sx=geometry_info.rho;
13232               affine.sy=geometry_info.sigma;
13233               if ((flags & SigmaValue) == 0)
13234                 affine.sy=affine.sx;
13235               break;
13236             }
13237           if (LocaleCompare(attribute,"skew") == 0)
13238             {
13239               double
13240                 x_angle,
13241                 y_angle;
13242
13243               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13244               x_angle=geometry_info.rho;
13245               y_angle=geometry_info.sigma;
13246               if ((flags & SigmaValue) == 0)
13247                 y_angle=x_angle;
13248               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13249               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13250               break;
13251             }
13252           if (LocaleCompare(attribute,"stroke") == 0)
13253             {
13254               if (info)
13255                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13256                   &draw_info->stroke,exception);
13257               break;
13258             }
13259           if (LocaleCompare(attribute,"style") == 0)
13260             {
13261               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13262                 SvPV(ST(i),na));
13263               if (type < 0)
13264                 {
13265                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13266                     SvPV(ST(i),na));
13267                   break;
13268                 }
13269               draw_info->style=(StyleType) type;
13270               break;
13271             }
13272           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13273             attribute);
13274           break;
13275         }
13276         case 't':
13277         case 'T':
13278         {
13279           if (LocaleCompare(attribute,"text") == 0)
13280             {
13281               CloneString(&draw_info->text,SvPV(ST(i),na));
13282               break;
13283             }
13284           if (LocaleCompare(attribute,"translate") == 0)
13285             {
13286               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13287               affine.tx=geometry_info.rho;
13288               affine.ty=geometry_info.sigma;
13289               if ((flags & SigmaValue) == 0)
13290                 affine.ty=affine.tx;
13291               break;
13292             }
13293           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13294             attribute);
13295           break;
13296         }
13297         case 'w':
13298         case 'W':
13299         {
13300           if (LocaleCompare(attribute,"weight") == 0)
13301             {
13302               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13303               draw_info->weight=(size_t) geometry_info.rho;
13304               break;
13305             }
13306           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13307             attribute);
13308           break;
13309         }
13310         case 'x':
13311         case 'X':
13312         {
13313           if (LocaleCompare(attribute,"x") == 0)
13314             {
13315               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13316               x=geometry_info.rho;
13317               break;
13318             }
13319           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13320             attribute);
13321           break;
13322         }
13323         case 'y':
13324         case 'Y':
13325         {
13326           if (LocaleCompare(attribute,"y") == 0)
13327             {
13328               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13329               y=geometry_info.rho;
13330               break;
13331             }
13332           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13333             attribute);
13334           break;
13335         }
13336         default:
13337         {
13338           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13339             attribute);
13340           break;
13341         }
13342       }
13343     }
13344     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13345     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13346     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13347     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13348     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13349     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13350     if (draw_info->geometry == (char *) NULL)
13351       {
13352         draw_info->geometry=AcquireString((char *) NULL);
13353         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13354           "%.15g,%.15g",x,y);
13355       }
13356     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13357     (void) CatchException(exception);
13358     if (status == MagickFalse)
13359       PUSHs(&sv_undef);
13360     else
13361       {
13362         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13363         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13364         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13365         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13366         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13367         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13368         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13369         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13370         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13371         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13372         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13373         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13374         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13375       }
13376     draw_info=DestroyDrawInfo(draw_info);
13377
13378   PerlException:
13379     if (package_info != (struct PackageInfo *) NULL)
13380       DestroyPackageInfo(package_info);
13381     InheritPerlException(exception,perl_exception);
13382     exception=DestroyExceptionInfo(exception);
13383     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13384   }
13385 \f
13386 #
13387 ###############################################################################
13388 #                                                                             #
13389 #                                                                             #
13390 #                                                                             #
13391 #   Q u e r y F o r m a t                                                     #
13392 #                                                                             #
13393 #                                                                             #
13394 #                                                                             #
13395 ###############################################################################
13396 #
13397 #
13398 void
13399 QueryFormat(ref,...)
13400   Image::Magick ref=NO_INIT
13401   ALIAS:
13402     queryformat = 1
13403   PPCODE:
13404   {
13405     char
13406       *name;
13407
13408     ExceptionInfo
13409       *exception;
13410
13411     register ssize_t
13412       i;
13413
13414     SV
13415       *perl_exception;
13416
13417     volatile const MagickInfo
13418       *magick_info;
13419
13420     PERL_UNUSED_VAR(ref);
13421     PERL_UNUSED_VAR(ix);
13422     exception=AcquireExceptionInfo();
13423     perl_exception=newSVpv("",0);
13424     if (items == 1)
13425       {
13426         char
13427           format[MagickPathExtent];
13428
13429         const MagickInfo
13430           **format_list;
13431
13432         size_t
13433           types;
13434
13435         format_list=GetMagickInfoList("*",&types,exception);
13436         EXTEND(sp,types);
13437         for (i=0; i < (ssize_t) types; i++)
13438         {
13439           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13440           LocaleLower(format);
13441           PUSHs(sv_2mortal(newSVpv(format,0)));
13442         }
13443         format_list=(const MagickInfo **)
13444           RelinquishMagickMemory((MagickInfo *) format_list);
13445         goto PerlException;
13446       }
13447     EXTEND(sp,8*items);
13448     for (i=1; i < items; i++)
13449     {
13450       name=(char *) SvPV(ST(i),na);
13451       magick_info=GetMagickInfo(name,exception);
13452       if (magick_info == (const MagickInfo *) NULL)
13453         {
13454           PUSHs(&sv_undef);
13455           continue;
13456         }
13457       if (magick_info->description == (char *) NULL)
13458         PUSHs(&sv_undef);
13459       else
13460         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13461       if (magick_info->module == (char *) NULL)
13462         PUSHs(&sv_undef);
13463       else
13464         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13465     }
13466
13467   PerlException:
13468     InheritPerlException(exception,perl_exception);
13469     exception=DestroyExceptionInfo(exception);
13470     SvREFCNT_dec(perl_exception);
13471   }
13472 \f
13473 #
13474 ###############################################################################
13475 #                                                                             #
13476 #                                                                             #
13477 #                                                                             #
13478 #   Q u e r y O p t i o n                                                     #
13479 #                                                                             #
13480 #                                                                             #
13481 #                                                                             #
13482 ###############################################################################
13483 #
13484 #
13485 void
13486 QueryOption(ref,...)
13487   Image::Magick ref=NO_INIT
13488   ALIAS:
13489     queryoption = 1
13490   PPCODE:
13491   {
13492     char
13493       **options;
13494
13495     ExceptionInfo
13496       *exception;
13497
13498     register ssize_t
13499       i;
13500
13501     ssize_t
13502       j,
13503       option;
13504
13505     SV
13506       *perl_exception;
13507
13508     PERL_UNUSED_VAR(ref);
13509     PERL_UNUSED_VAR(ix);
13510     exception=AcquireExceptionInfo();
13511     perl_exception=newSVpv("",0);
13512     EXTEND(sp,8*items);
13513     for (i=1; i < items; i++)
13514     {
13515       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13516         SvPV(ST(i),na));
13517       options=GetCommandOptions((CommandOption) option);
13518       if (options == (char **) NULL)
13519         PUSHs(&sv_undef);
13520       else
13521         {
13522           for (j=0; options[j] != (char *) NULL; j++)
13523             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13524           options=DestroyStringList(options);
13525         }
13526     }
13527
13528     InheritPerlException(exception,perl_exception);
13529     exception=DestroyExceptionInfo(exception);
13530     SvREFCNT_dec(perl_exception);
13531   }
13532 \f
13533 #
13534 ###############################################################################
13535 #                                                                             #
13536 #                                                                             #
13537 #                                                                             #
13538 #   R e a d                                                                   #
13539 #                                                                             #
13540 #                                                                             #
13541 #                                                                             #
13542 ###############################################################################
13543 #
13544 #
13545 void
13546 Read(ref,...)
13547   Image::Magick ref=NO_INIT
13548   ALIAS:
13549     ReadImage  = 1
13550     read       = 2
13551     readimage  = 3
13552   PPCODE:
13553   {
13554     AV
13555       *av;
13556
13557     char
13558       **keep,
13559       **list;
13560
13561     ExceptionInfo
13562       *exception;
13563
13564     HV
13565       *hv;
13566
13567     Image
13568       *image;
13569
13570     int
13571       n;
13572
13573     MagickBooleanType
13574       status;
13575
13576     register char
13577       **p;
13578
13579     register ssize_t
13580       i;
13581
13582     ssize_t
13583       ac,
13584       number_images;
13585
13586     STRLEN
13587       *length;
13588
13589     struct PackageInfo
13590       *info,
13591       *package_info;
13592
13593     SV
13594       *perl_exception,  /* Perl variable for storing messages */
13595       *reference,
13596       *rv,
13597       *sv;
13598
13599     PERL_UNUSED_VAR(ref);
13600     PERL_UNUSED_VAR(ix);
13601     exception=AcquireExceptionInfo();
13602     perl_exception=newSVpv("",0);
13603     sv=NULL;
13604     package_info=(struct PackageInfo *) NULL;
13605     number_images=0;
13606     ac=(items < 2) ? 1 : items-1;
13607     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13608     keep=list;
13609     length=(STRLEN *) NULL;
13610     if (list == (char **) NULL)
13611       {
13612         ThrowPerlException(exception,ResourceLimitError,
13613           "MemoryAllocationFailed",PackageName);
13614         goto PerlException;
13615       }
13616     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13617     if (length == (STRLEN *) NULL)
13618       {
13619         ThrowPerlException(exception,ResourceLimitError,
13620           "MemoryAllocationFailed",PackageName);
13621         goto PerlException;
13622       }
13623     if (sv_isobject(ST(0)) == 0)
13624       {
13625         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13626           PackageName);
13627         goto PerlException;
13628       }
13629     reference=SvRV(ST(0));
13630     hv=SvSTASH(reference);
13631     if (SvTYPE(reference) != SVt_PVAV)
13632       {
13633         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13634           PackageName);
13635         goto PerlException;
13636       }
13637     av=(AV *) reference;
13638     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13639       exception);
13640     package_info=ClonePackageInfo(info,exception);
13641     n=1;
13642     if (items <= 1)
13643       *list=(char *) (*package_info->image_info->filename ?
13644         package_info->image_info->filename : "XC:black");
13645     else
13646       for (n=0, i=0; i < ac; i++)
13647       {
13648         list[n]=(char *) SvPV(ST(i+1),length[n]);
13649         if ((items >= 3) && strEQcase(list[n],"blob"))
13650           {
13651             void
13652               *blob;
13653
13654             i++;
13655             blob=(void *) (SvPV(ST(i+1),length[n]));
13656             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13657           }
13658         if ((items >= 3) && strEQcase(list[n],"filename"))
13659           continue;
13660         if ((items >= 3) && strEQcase(list[n],"file"))
13661           {
13662             FILE
13663               *file;
13664
13665             PerlIO
13666               *io_info;
13667
13668             i++;
13669             io_info=IoIFP(sv_2io(ST(i+1)));
13670             if (io_info == (PerlIO *) NULL)
13671               {
13672                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13673                   PackageName);
13674                 continue;
13675               }
13676             file=PerlIO_findFILE(io_info);
13677             if (file == (FILE *) NULL)
13678               {
13679                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13680                   PackageName);
13681                 continue;
13682               }
13683             SetImageInfoFile(package_info->image_info,file);
13684           }
13685         if ((items >= 3) && strEQcase(list[n],"magick"))
13686           continue;
13687         n++;
13688       }
13689     list[n]=(char *) NULL;
13690     keep=list;
13691     status=ExpandFilenames(&n,&list);
13692     if (status == MagickFalse)
13693       {
13694         ThrowPerlException(exception,ResourceLimitError,
13695           "MemoryAllocationFailed",PackageName);
13696         goto PerlException;
13697       }
13698     number_images=0;
13699     for (i=0; i < n; i++)
13700     {
13701       if ((package_info->image_info->file == (FILE *) NULL) &&
13702           (package_info->image_info->blob == (void *) NULL))
13703         image=ReadImages(package_info->image_info,list[i],exception);
13704       else
13705         {
13706           image=ReadImages(package_info->image_info,
13707             package_info->image_info->filename,exception);
13708           if (image != (Image *) NULL)
13709             DisassociateImageStream(image);
13710         }
13711       if (image == (Image *) NULL)
13712         break;
13713       for ( ; image; image=image->next)
13714       {
13715         AddImageToRegistry(sv,image);
13716         rv=newRV(sv);
13717         av_push(av,sv_bless(rv,hv));
13718         SvREFCNT_dec(sv);
13719         number_images++;
13720       }
13721     }
13722     /*
13723       Free resources.
13724     */
13725     for (i=0; i < n; i++)
13726       if (list[i] != (char *) NULL)
13727         for (p=keep; list[i] != *p++; )
13728           if (*p == (char *) NULL)
13729             {
13730               list[i]=(char *) RelinquishMagickMemory(list[i]);
13731               break;
13732             }
13733
13734   PerlException:
13735     if (package_info != (struct PackageInfo *) NULL)
13736       DestroyPackageInfo(package_info);
13737     if (list && (list != keep))
13738       list=(char **) RelinquishMagickMemory(list);
13739     if (keep)
13740       keep=(char **) RelinquishMagickMemory(keep);
13741     if (length)
13742       length=(STRLEN *) RelinquishMagickMemory(length);
13743     InheritPerlException(exception,perl_exception);
13744     exception=DestroyExceptionInfo(exception);
13745     sv_setiv(perl_exception,(IV) number_images);
13746     SvPOK_on(perl_exception);
13747     ST(0)=sv_2mortal(perl_exception);
13748     XSRETURN(1);
13749   }
13750 \f
13751 #
13752 ###############################################################################
13753 #                                                                             #
13754 #                                                                             #
13755 #                                                                             #
13756 #   R e m o t e                                                               #
13757 #                                                                             #
13758 #                                                                             #
13759 #                                                                             #
13760 ###############################################################################
13761 #
13762 #
13763 void
13764 Remote(ref,...)
13765   Image::Magick ref=NO_INIT
13766   ALIAS:
13767     RemoteCommand  = 1
13768     remote         = 2
13769     remoteCommand  = 3
13770   PPCODE:
13771   {
13772     AV
13773       *av;
13774
13775     ExceptionInfo
13776       *exception;
13777
13778     register ssize_t
13779       i;
13780
13781     SV
13782       *perl_exception,
13783       *reference;
13784
13785     struct PackageInfo
13786       *info;
13787
13788     PERL_UNUSED_VAR(ref);
13789     PERL_UNUSED_VAR(ix);
13790     exception=AcquireExceptionInfo();
13791     perl_exception=newSVpv("",0);
13792     reference=SvRV(ST(0));
13793     av=(AV *) reference;
13794     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13795       exception);
13796     for (i=1; i < items; i++)
13797       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13798         SvPV(ST(i),na),exception);
13799     InheritPerlException(exception,perl_exception);
13800     exception=DestroyExceptionInfo(exception);
13801     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13802   }
13803 \f
13804 #
13805 ###############################################################################
13806 #                                                                             #
13807 #                                                                             #
13808 #                                                                             #
13809 #   S e t                                                                     #
13810 #                                                                             #
13811 #                                                                             #
13812 #                                                                             #
13813 ###############################################################################
13814 #
13815 #
13816 void
13817 Set(ref,...)
13818   Image::Magick ref=NO_INIT
13819   ALIAS:
13820     SetAttributes  = 1
13821     SetAttribute   = 2
13822     set            = 3
13823     setattributes  = 4
13824     setattribute   = 5
13825   PPCODE:
13826   {
13827     ExceptionInfo
13828       *exception;
13829
13830     Image
13831       *image;
13832
13833     register ssize_t
13834       i;
13835
13836     struct PackageInfo
13837       *info;
13838
13839     SV
13840       *perl_exception,
13841       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13842
13843     PERL_UNUSED_VAR(ref);
13844     PERL_UNUSED_VAR(ix);
13845     exception=AcquireExceptionInfo();
13846     perl_exception=newSVpv("",0);
13847     if (sv_isobject(ST(0)) == 0)
13848       {
13849         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13850           PackageName);
13851         goto PerlException;
13852       }
13853     reference=SvRV(ST(0));
13854     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13855     if (items == 2)
13856       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13857     else
13858       for (i=2; i < items; i+=2)
13859         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13860
13861   PerlException:
13862     InheritPerlException(exception,perl_exception);
13863     exception=DestroyExceptionInfo(exception);
13864     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13865     SvPOK_on(perl_exception);
13866     ST(0)=sv_2mortal(perl_exception);
13867     XSRETURN(1);
13868   }
13869 \f
13870 #
13871 ###############################################################################
13872 #                                                                             #
13873 #                                                                             #
13874 #                                                                             #
13875 #   S e t P i x e l                                                           #
13876 #                                                                             #
13877 #                                                                             #
13878 #                                                                             #
13879 ###############################################################################
13880 #
13881 #
13882 void
13883 SetPixel(ref,...)
13884   Image::Magick ref=NO_INIT
13885   ALIAS:
13886     setpixel = 1
13887     setPixel = 2
13888   PPCODE:
13889   {
13890     AV
13891       *av;
13892
13893     char
13894       *attribute;
13895
13896     ChannelType
13897       channel,
13898       channel_mask;
13899
13900     ExceptionInfo
13901       *exception;
13902
13903     Image
13904       *image;
13905
13906     MagickBooleanType
13907       normalize;
13908
13909     RectangleInfo
13910       region;
13911
13912     register ssize_t
13913       i;
13914
13915     register Quantum
13916       *q;
13917
13918     ssize_t
13919       option;
13920
13921     struct PackageInfo
13922       *info;
13923
13924     SV
13925       *perl_exception,
13926       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13927
13928     PERL_UNUSED_VAR(ref);
13929     PERL_UNUSED_VAR(ix);
13930     exception=AcquireExceptionInfo();
13931     perl_exception=newSVpv("",0);
13932     reference=SvRV(ST(0));
13933     av=(AV *) reference;
13934     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13935       exception);
13936     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13937     if (image == (Image *) NULL)
13938       {
13939         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13940           PackageName);
13941         goto PerlException;
13942       }
13943     av=(AV *) NULL;
13944     normalize=MagickTrue;
13945     region.x=0;
13946     region.y=0;
13947     region.width=image->columns;
13948     region.height=1;
13949     if (items == 1)
13950       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13951     channel=DefaultChannels;
13952     for (i=2; i < items; i+=2)
13953     {
13954       attribute=(char *) SvPV(ST(i-1),na);
13955       switch (*attribute)
13956       {
13957         case 'C':
13958         case 'c':
13959         {
13960           if (LocaleCompare(attribute,"channel") == 0)
13961             {
13962               ssize_t
13963                 option;
13964
13965               option=ParseChannelOption(SvPV(ST(i),na));
13966               if (option < 0)
13967                 {
13968                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13969                     SvPV(ST(i),na));
13970                   return;
13971                 }
13972               channel=(ChannelType) option;
13973               break;
13974             }
13975           if (LocaleCompare(attribute,"color") == 0)
13976             {
13977               if (SvTYPE(ST(i)) != SVt_RV)
13978                 {
13979                   char
13980                     message[MagickPathExtent];
13981
13982                   (void) FormatLocaleString(message,MagickPathExtent,
13983                     "invalid %.60s value",attribute);
13984                   ThrowPerlException(exception,OptionError,message,
13985                     SvPV(ST(i),na));
13986                 }
13987               av=(AV *) SvRV(ST(i));
13988               break;
13989             }
13990           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13991             attribute);
13992           break;
13993         }
13994         case 'g':
13995         case 'G':
13996         {
13997           if (LocaleCompare(attribute,"geometry") == 0)
13998             {
13999               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
14000               break;
14001             }
14002           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14003             attribute);
14004           break;
14005         }
14006         case 'N':
14007         case 'n':
14008         {
14009           if (LocaleCompare(attribute,"normalize") == 0)
14010             {
14011               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14012                 SvPV(ST(i),na));
14013               if (option < 0)
14014                 {
14015                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14016                     SvPV(ST(i),na));
14017                   break;
14018                 }
14019              normalize=option != 0 ? MagickTrue : MagickFalse;
14020              break;
14021             }
14022           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14023             attribute);
14024           break;
14025         }
14026         case 'x':
14027         case 'X':
14028         {
14029           if (LocaleCompare(attribute,"x") == 0)
14030             {
14031               region.x=SvIV(ST(i));
14032               break;
14033             }
14034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14035             attribute);
14036           break;
14037         }
14038         case 'y':
14039         case 'Y':
14040         {
14041           if (LocaleCompare(attribute,"y") == 0)
14042             {
14043               region.y=SvIV(ST(i));
14044               break;
14045             }
14046           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14047             attribute);
14048           break;
14049         }
14050         default:
14051         {
14052           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14053             attribute);
14054           break;
14055         }
14056       }
14057     }
14058     (void) SetImageStorageClass(image,DirectClass,exception);
14059     channel_mask=SetImageChannelMask(image,channel);
14060     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
14061     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
14062         (SvTYPE(av) != SVt_PVAV))
14063       PUSHs(&sv_undef);
14064     else
14065       {
14066         double
14067           scale;
14068
14069         register ssize_t
14070           i;
14071
14072         i=0;
14073         scale=1.0;
14074         if (normalize != MagickFalse)
14075           scale=QuantumRange;
14076         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
14077             (i <= av_len(av)))
14078           {
14079             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
14080               av_fetch(av,i,0)))),q);
14081             i++;
14082           }
14083         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
14084             (i <= av_len(av)))
14085           {
14086             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
14087               av_fetch(av,i,0)))),q);
14088             i++;
14089           }
14090         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
14091             (i <= av_len(av)))
14092           {
14093             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
14094               av_fetch(av,i,0)))),q);
14095             i++;
14096           }
14097         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
14098             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
14099           {
14100             SetPixelBlack(image,ClampToQuantum(scale*
14101               SvNV(*(av_fetch(av,i,0)))),q);
14102             i++;
14103           }
14104         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
14105             (i <= av_len(av)))
14106           {
14107             SetPixelAlpha(image,ClampToQuantum(scale*
14108               SvNV(*(av_fetch(av,i,0)))),q);
14109             i++;
14110           }
14111         (void) SyncAuthenticPixels(image,exception);
14112       }
14113     (void) SetImageChannelMask(image,channel_mask);
14114
14115   PerlException:
14116     InheritPerlException(exception,perl_exception);
14117     exception=DestroyExceptionInfo(exception);
14118     SvREFCNT_dec(perl_exception);
14119   }
14120 \f
14121 #
14122 ###############################################################################
14123 #                                                                             #
14124 #                                                                             #
14125 #                                                                             #
14126 #   S m u s h                                                                 #
14127 #                                                                             #
14128 #                                                                             #
14129 #                                                                             #
14130 ###############################################################################
14131 #
14132 #
14133 void
14134 Smush(ref,...)
14135   Image::Magick ref=NO_INIT
14136   ALIAS:
14137     SmushImage  = 1
14138     smush       = 2
14139     smushimage  = 3
14140   PPCODE:
14141   {
14142     AV
14143       *av;
14144
14145     char
14146       *attribute;
14147
14148     ExceptionInfo
14149       *exception;
14150
14151     HV
14152       *hv;
14153
14154     Image
14155       *image;
14156
14157     register ssize_t
14158       i;
14159
14160     ssize_t
14161       offset,
14162       stack;
14163
14164     struct PackageInfo
14165       *info;
14166
14167     SV
14168       *av_reference,
14169       *perl_exception,
14170       *reference,
14171       *rv,
14172       *sv;
14173
14174     PERL_UNUSED_VAR(ref);
14175     PERL_UNUSED_VAR(ix);
14176     exception=AcquireExceptionInfo();
14177     perl_exception=newSVpv("",0);
14178     sv=NULL;
14179     attribute=NULL;
14180     av=NULL;
14181     if (sv_isobject(ST(0)) == 0)
14182       {
14183         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14184           PackageName);
14185         goto PerlException;
14186       }
14187     reference=SvRV(ST(0));
14188     hv=SvSTASH(reference);
14189     av=newAV();
14190     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14191     SvREFCNT_dec(av);
14192     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14193     if (image == (Image *) NULL)
14194       {
14195         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14196           PackageName);
14197         goto PerlException;
14198       }
14199     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14200     /*
14201       Get options.
14202     */
14203     offset=0;
14204     stack=MagickTrue;
14205     for (i=2; i < items; i+=2)
14206     {
14207       attribute=(char *) SvPV(ST(i-1),na);
14208       switch (*attribute)
14209       {
14210         case 'O':
14211         case 'o':
14212         {
14213           if (LocaleCompare(attribute,"offset") == 0)
14214             {
14215               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14216               break;
14217             }
14218           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14219             attribute);
14220           break;
14221         }
14222         case 'S':
14223         case 's':
14224         {
14225           if (LocaleCompare(attribute,"stack") == 0)
14226             {
14227               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14228                 SvPV(ST(i),na));
14229               if (stack < 0)
14230                 {
14231                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14232                     SvPV(ST(i),na));
14233                   return;
14234                 }
14235               break;
14236             }
14237           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14238             attribute);
14239           break;
14240         }
14241         default:
14242         {
14243           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14244             attribute);
14245           break;
14246         }
14247       }
14248     }
14249     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14250       exception);
14251     if (image == (Image *) NULL)
14252       goto PerlException;
14253     for ( ; image; image=image->next)
14254     {
14255       AddImageToRegistry(sv,image);
14256       rv=newRV(sv);
14257       av_push(av,sv_bless(rv,hv));
14258       SvREFCNT_dec(sv);
14259     }
14260     exception=DestroyExceptionInfo(exception);
14261     ST(0)=av_reference;
14262     SvREFCNT_dec(perl_exception);
14263     XSRETURN(1);
14264
14265   PerlException:
14266     InheritPerlException(exception,perl_exception);
14267     exception=DestroyExceptionInfo(exception);
14268     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14269     SvPOK_on(perl_exception);
14270     ST(0)=sv_2mortal(perl_exception);
14271     XSRETURN(1);
14272   }
14273 \f
14274 #
14275 ###############################################################################
14276 #                                                                             #
14277 #                                                                             #
14278 #                                                                             #
14279 #   S t a t i s t i c s                                                       #
14280 #                                                                             #
14281 #                                                                             #
14282 #                                                                             #
14283 ###############################################################################
14284 #
14285 #
14286 void
14287 Statistics(ref,...)
14288   Image::Magick ref=NO_INIT
14289   ALIAS:
14290     StatisticsImage = 1
14291     statistics      = 2
14292     statisticsimage = 3
14293   PPCODE:
14294   {
14295 #define ChannelStatistics(channel) \
14296 { \
14297   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14298     (double) channel_statistics[channel].depth); \
14299   PUSHs(sv_2mortal(newSVpv(message,0))); \
14300   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14301     channel_statistics[channel].minima/scale); \
14302   PUSHs(sv_2mortal(newSVpv(message,0))); \
14303   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14304     channel_statistics[channel].maxima/scale); \
14305   PUSHs(sv_2mortal(newSVpv(message,0))); \
14306   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14307     channel_statistics[channel].mean/scale); \
14308   PUSHs(sv_2mortal(newSVpv(message,0))); \
14309   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14310     channel_statistics[channel].standard_deviation/scale); \
14311   PUSHs(sv_2mortal(newSVpv(message,0))); \
14312   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14313     channel_statistics[channel].kurtosis); \
14314   PUSHs(sv_2mortal(newSVpv(message,0))); \
14315   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14316     channel_statistics[channel].skewness); \
14317   PUSHs(sv_2mortal(newSVpv(message,0))); \
14318   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14319     channel_statistics[channel].entropy); \
14320   PUSHs(sv_2mortal(newSVpv(message,0))); \
14321 }
14322
14323     AV
14324       *av;
14325
14326     char
14327       message[MagickPathExtent];
14328
14329     ChannelStatistics
14330       *channel_statistics;
14331
14332     double
14333       scale;
14334
14335     ExceptionInfo
14336       *exception;
14337
14338     Image
14339       *image;
14340
14341     ssize_t
14342       count;
14343
14344     struct PackageInfo
14345       *info;
14346
14347     SV
14348       *perl_exception,
14349       *reference;
14350
14351     PERL_UNUSED_VAR(ref);
14352     PERL_UNUSED_VAR(ix);
14353     exception=AcquireExceptionInfo();
14354     perl_exception=newSVpv("",0);
14355     av=NULL;
14356     if (sv_isobject(ST(0)) == 0)
14357       {
14358         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14359           PackageName);
14360         goto PerlException;
14361       }
14362     reference=SvRV(ST(0));
14363     av=newAV();
14364     SvREFCNT_dec(av);
14365     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14366     if (image == (Image *) NULL)
14367       {
14368         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14369           PackageName);
14370         goto PerlException;
14371       }
14372     count=0;
14373     for ( ; image; image=image->next)
14374     {
14375       channel_statistics=GetImageStatistics(image,exception);
14376       if (channel_statistics == (ChannelStatistics *) NULL)
14377         continue;
14378       count++;
14379       EXTEND(sp,35*count);
14380       scale=(double) QuantumRange;
14381       ChannelStatistics(RedChannel);
14382       ChannelStatistics(GreenChannel);
14383       ChannelStatistics(BlueChannel);
14384       if (image->colorspace == CMYKColorspace)
14385         ChannelStatistics(BlackChannel);
14386       if (image->alpha_trait != UndefinedPixelTrait)
14387         ChannelStatistics(AlphaChannel);
14388       channel_statistics=(ChannelStatistics *)
14389         RelinquishMagickMemory(channel_statistics);
14390     }
14391
14392   PerlException:
14393     InheritPerlException(exception,perl_exception);
14394     exception=DestroyExceptionInfo(exception);
14395     SvREFCNT_dec(perl_exception);
14396   }
14397 \f
14398 #
14399 ###############################################################################
14400 #                                                                             #
14401 #                                                                             #
14402 #                                                                             #
14403 #   S y n c A u t h e n t i c P i x e l s                                     #
14404 #                                                                             #
14405 #                                                                             #
14406 #                                                                             #
14407 ###############################################################################
14408 #
14409 #
14410 void
14411 SyncAuthenticPixels(ref,...)
14412   Image::Magick ref = NO_INIT
14413   ALIAS:
14414     Syncauthenticpixels = 1
14415     SyncImagePixels = 2
14416     syncimagepixels = 3
14417   CODE:
14418   {
14419     ExceptionInfo
14420       *exception;
14421
14422     Image
14423       *image;
14424
14425     MagickBooleanType
14426       status;
14427
14428     struct PackageInfo
14429       *info;
14430
14431     SV
14432       *perl_exception,
14433       *reference;
14434
14435     PERL_UNUSED_VAR(ref);
14436     PERL_UNUSED_VAR(ix);
14437     exception=AcquireExceptionInfo();
14438     perl_exception=newSVpv("",0);
14439     if (sv_isobject(ST(0)) == 0)
14440       {
14441         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14442           PackageName);
14443         goto PerlException;
14444       }
14445
14446     reference=SvRV(ST(0));
14447     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14448     if (image == (Image *) NULL)
14449       {
14450         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14451           PackageName);
14452         goto PerlException;
14453       }
14454
14455     status=SyncAuthenticPixels(image,exception);
14456     if (status != MagickFalse)
14457       return;
14458
14459   PerlException:
14460     InheritPerlException(exception,perl_exception);
14461     exception=DestroyExceptionInfo(exception);
14462     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14463   }
14464 \f
14465 #
14466 ###############################################################################
14467 #                                                                             #
14468 #                                                                             #
14469 #                                                                             #
14470 #   T r a n s f o r m                                                         #
14471 #                                                                             #
14472 #                                                                             #
14473 #                                                                             #
14474 ###############################################################################
14475 #
14476 #
14477 void
14478 Transform(ref,...)
14479   Image::Magick ref=NO_INIT
14480   ALIAS:
14481     TransformImage = 1
14482     transform      = 2
14483     transformimage = 3
14484   PPCODE:
14485   {
14486     AV
14487       *av;
14488
14489     char
14490       *attribute,
14491       *crop_geometry,
14492       *geometry;
14493
14494     ExceptionInfo
14495       *exception;
14496
14497     HV
14498       *hv;
14499
14500     Image
14501       *clone,
14502       *image;
14503
14504     register ssize_t
14505       i;
14506
14507     struct PackageInfo
14508       *info;
14509
14510     SV
14511       *av_reference,
14512       *perl_exception,
14513       *reference,
14514       *rv,
14515       *sv;
14516
14517     PERL_UNUSED_VAR(ref);
14518     PERL_UNUSED_VAR(ix);
14519     exception=AcquireExceptionInfo();
14520     perl_exception=newSVpv("",0);
14521     sv=NULL;
14522     av=NULL;
14523     attribute=NULL;
14524     if (sv_isobject(ST(0)) == 0)
14525       {
14526         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14527           PackageName);
14528         goto PerlException;
14529       }
14530     reference=SvRV(ST(0));
14531     hv=SvSTASH(reference);
14532     av=newAV();
14533     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14534     SvREFCNT_dec(av);
14535     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14536     if (image == (Image *) NULL)
14537       {
14538         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14539           PackageName);
14540         goto PerlException;
14541       }
14542     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14543     /*
14544       Get attribute.
14545     */
14546     crop_geometry=(char *) NULL;
14547     geometry=(char *) NULL;
14548     for (i=2; i < items; i+=2)
14549     {
14550       attribute=(char *) SvPV(ST(i-1),na);
14551       switch (*attribute)
14552       {
14553         case 'c':
14554         case 'C':
14555         {
14556           if (LocaleCompare(attribute,"crop") == 0)
14557             {
14558               crop_geometry=SvPV(ST(i),na);
14559               break;
14560             }
14561           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14562             attribute);
14563           break;
14564         }
14565         case 'g':
14566         case 'G':
14567         {
14568           if (LocaleCompare(attribute,"geometry") == 0)
14569             {
14570               geometry=SvPV(ST(i),na);
14571               break;
14572             }
14573           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14574             attribute);
14575           break;
14576         }
14577         default:
14578         {
14579           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14580             attribute);
14581           break;
14582         }
14583       }
14584     }
14585     for ( ; image; image=image->next)
14586     {
14587       clone=CloneImage(image,0,0,MagickTrue,exception);
14588       if (clone == (Image *) NULL)
14589         goto PerlException;
14590       TransformImage(&clone,crop_geometry,geometry,exception);
14591       for ( ; clone; clone=clone->next)
14592       {
14593         AddImageToRegistry(sv,clone);
14594         rv=newRV(sv);
14595         av_push(av,sv_bless(rv,hv));
14596         SvREFCNT_dec(sv);
14597       }
14598     }
14599     exception=DestroyExceptionInfo(exception);
14600     ST(0)=av_reference;
14601     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14602     XSRETURN(1);
14603
14604   PerlException:
14605     InheritPerlException(exception,perl_exception);
14606     exception=DestroyExceptionInfo(exception);
14607     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14608     SvPOK_on(perl_exception);
14609     ST(0)=sv_2mortal(perl_exception);
14610     XSRETURN(1);
14611   }
14612 \f
14613 #
14614 ###############################################################################
14615 #                                                                             #
14616 #                                                                             #
14617 #                                                                             #
14618 #   W r i t e                                                                 #
14619 #                                                                             #
14620 #                                                                             #
14621 #                                                                             #
14622 ###############################################################################
14623 #
14624 #
14625 void
14626 Write(ref,...)
14627   Image::Magick ref=NO_INIT
14628   ALIAS:
14629     WriteImage    = 1
14630     write         = 2
14631     writeimage    = 3
14632   PPCODE:
14633   {
14634     char
14635       filename[MagickPathExtent];
14636
14637     ExceptionInfo
14638       *exception;
14639
14640     Image
14641       *image,
14642       *next;
14643
14644     register ssize_t
14645       i;
14646
14647     ssize_t
14648       number_images,
14649       scene;
14650
14651     struct PackageInfo
14652       *info,
14653       *package_info;
14654
14655     SV
14656       *perl_exception,
14657       *reference;
14658
14659     PERL_UNUSED_VAR(ref);
14660     PERL_UNUSED_VAR(ix);
14661     exception=AcquireExceptionInfo();
14662     perl_exception=newSVpv("",0);
14663     number_images=0;
14664     package_info=(struct PackageInfo *) NULL;
14665     if (sv_isobject(ST(0)) == 0)
14666       {
14667         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14668           PackageName);
14669         goto PerlException;
14670       }
14671     reference=SvRV(ST(0));
14672     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14673     if (image == (Image *) NULL)
14674       {
14675         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14676           PackageName);
14677         goto PerlException;
14678       }
14679     package_info=ClonePackageInfo(info,exception);
14680     if (items == 2)
14681       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14682     else
14683       if (items > 2)
14684         for (i=2; i < items; i+=2)
14685           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14686             exception);
14687     (void) CopyMagickString(filename,package_info->image_info->filename,
14688       MagickPathExtent);
14689     scene=0;
14690     for (next=image; next; next=next->next)
14691     {
14692       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14693       next->scene=scene++;
14694     }
14695     *package_info->image_info->magick='\0';
14696     SetImageInfo(package_info->image_info,(unsigned int)
14697       GetImageListLength(image),exception);
14698     for (next=image; next; next=next->next)
14699     {
14700       (void) WriteImage(package_info->image_info,next,exception);
14701       number_images++;
14702       if (package_info->image_info->adjoin)
14703         break;
14704     }
14705
14706   PerlException:
14707     if (package_info != (struct PackageInfo *) NULL)
14708       DestroyPackageInfo(package_info);
14709     InheritPerlException(exception,perl_exception);
14710     exception=DestroyExceptionInfo(exception);
14711     sv_setiv(perl_exception,(IV) number_images);
14712     SvPOK_on(perl_exception);
14713     ST(0)=sv_2mortal(perl_exception);
14714     XSRETURN(1);
14715   }