]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
(no commit message)
[imagemagick] / PerlMagick / Magick.xs
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                         PPPP   EEEEE  RRRR   L                              %
6 %                         P   P  E      R   R  L                              %
7 %                         PPPP   EEE    RRRR   L                              %
8 %                         P      E      R  R   L                              %
9 %                         P      EEEEE  R   R  LLLLL                          %
10 %                                                                             %
11 %                  M   M   AAA    GGGG  IIIII   CCCC  K   K                   %
12 %                  MM MM  A   A  G        I    C      K  K                    %
13 %                  M M M  AAAAA  G GGG    I    C      KKK                     %
14 %                  M   M  A   A  G   G    I    C      K  K                    %
15 %                  M   M  A   A   GGGG  IIIII   CCCC  K   K                   %
16 %                                                                             %
17 %                                                                             %
18 %                Object-oriented Perl interface to ImageMagick                %
19 %                                                                             %
20 %                            Software Design                                  %
21 %                              Kyle Shorter                                   %
22 %                                 Cristy                                      %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization      %
27 %  dedicated to making software imaging solutions freely available.           %
28 %                                                                             %
29 %  You may not use this file except in compliance with the License.  You may  %
30 %  obtain a copy of the License at                                            %
31 %                                                                             %
32 %    http://www.imagemagick.org/script/license.php                            %
33 %                                                                             %
34 %  Unless required by applicable law or agreed to in writing, software        %
35 %  distributed under the License is distributed on an "AS IS" BASIS,          %
36 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
37 %  See the License for the specific language governing permissions and        %
38 %  limitations under the License.                                             %
39 %                                                                             %
40 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
41 %
42 %  PerlMagick is an objected-oriented Perl interface to ImageMagick.  Use
43 %  the module to read, manipulate, or write an image or image sequence from
44 %  within a Perl script.  This makes PerlMagick suitable for Web CGI scripts.
45 %
46 */
47 \f
48 /*
49   Include declarations.
50 */
51 #if defined(__cplusplus) || defined(c_plusplus)
52 extern "C" {
53 #endif
54
55 #define PERL_NO_GET_CONTEXT
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <math.h>
60 #include <MagickCore/MagickCore.h>
61 #undef tainted
62
63 #if defined(__cplusplus) || defined(c_plusplus)
64 }
65 #endif
66 \f
67 /*
68   Define declarations.
69 */
70 #ifndef aTHX_
71 #define aTHX_
72 #define pTHX_
73 #define dTHX
74 #endif
75 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
76 #define EndOf(array)  (&array[NumberOf(array)])
77 #define MagickPI  3.14159265358979323846264338327950288419716939937510
78 #define MaxArguments  33
79 #ifndef na
80 #define na  PL_na
81 #endif
82 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
83 #define PackageName   "Image::Magick"
84 #if PERL_VERSION <= 6
85 #define PerlIO  FILE
86 #define PerlIO_importFILE(f, fl)  (f)
87 #define PerlIO_findFILE(f)  NULL
88 #endif
89 #ifndef sv_undef
90 #define sv_undef  PL_sv_undef
91 #endif
92
93 #define AddImageToRegistry(sv,image) \
94 { \
95   if (magick_registry != (SplayTreeInfo *) NULL) \
96     { \
97       (void) AddValueToSplayTree(magick_registry,image,image); \
98       (sv)=newSViv(PTR2IV(image)); \
99     } \
100 }
101
102 #define DeleteImageFromRegistry(reference,image) \
103 { \
104   if (magick_registry != (SplayTreeInfo *) NULL) \
105     { \
106       if (GetImageReferenceCount(image) == 1) \
107        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
108       image=DestroyImage(image); \
109       sv_setiv(reference,0); \
110     } \
111 }
112
113 #define InheritPerlException(exception,perl_exception) \
114 { \
115   char \
116     message[MagickPathExtent]; \
117  \
118   if ((exception)->severity != UndefinedException) \
119     { \
120       (void) FormatLocaleString(message,MagickPathExtent,"Exception %d: %s%s%s%s",\
121         (exception)->severity, (exception)->reason ? \
122         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
123         "Unknown", (exception)->description ? " (" : "", \
124         (exception)->description ? GetLocaleExceptionMessage( \
125         (exception)->severity,(exception)->description) : "", \
126         (exception)->description ? ")" : ""); \
127       if ((perl_exception) != (SV *) NULL) \
128         { \
129           if (SvCUR(perl_exception)) \
130             sv_catpv(perl_exception,"\n"); \
131           sv_catpv(perl_exception,message); \
132         } \
133     } \
134 }
135
136 #define ThrowPerlException(exception,severity,tag,reason) \
137   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
138     tag,"`%s'",reason); \
139 \f
140 /*
141   Typedef and structure declarations.
142 */
143 typedef enum
144 {
145   ArrayReference = (~0),
146   RealReference = (~0)-1,
147   FileReference = (~0)-2,
148   ImageReference = (~0)-3,
149   IntegerReference = (~0)-4,
150   StringReference = (~0)-5
151 } MagickReference;
152
153 typedef struct _Arguments
154 {
155   const char
156     *method;
157
158   ssize_t
159     type;
160 } Arguments;
161
162 struct ArgumentList
163 {
164   ssize_t
165     integer_reference;
166
167   double
168     real_reference;
169
170   const char
171     *string_reference;
172
173   Image
174     *image_reference;
175
176   SV
177     *array_reference;
178
179   FILE
180     *file_reference;
181
182   size_t
183     length;
184 };
185
186 struct PackageInfo
187 {
188   ImageInfo
189     *image_info;
190 };
191
192 typedef void
193   *Image__Magick;  /* data type for the Image::Magick package */
194 \f
195 /*
196   Static declarations.
197 */
198 static struct
199   Methods
200   {
201     const char
202       *name;
203
204     Arguments
205       arguments[MaxArguments];
206   } Methods[] =
207   {
208     { "Comment", { {"comment", StringReference} } },
209     { "Label", { {"label", StringReference} } },
210     { "AddNoise", { {"noise", MagickNoiseOptions}, {"attenuate", RealReference},
211       {"channel", MagickChannelOptions} } },
212     { "Colorize", { {"fill", StringReference}, {"blend", StringReference} } },
213     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
214       {"height", IntegerReference}, {"fill", StringReference},
215       {"bordercolor", StringReference}, {"color", StringReference},
216       {"compose", MagickComposeOptions} } },
217     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
218       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
219     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
220       {"height", IntegerReference}, {"x", IntegerReference},
221       {"y", IntegerReference}, {"gravity", MagickGravityOptions} } },
222     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference}, {"fuzz", StringReference},
225       {"gravity", MagickGravityOptions} } },
226     { "Despeckle", },
227     { "Edge", { {"radius", RealReference} } },
228     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
229       {"sigma", RealReference} } },
230     { "Enhance", },
231     { "Flip", },
232     { "Flop", },
233     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
234       {"height", IntegerReference}, {"inner", IntegerReference},
235       {"outer", IntegerReference}, {"fill", StringReference},
236       {"color", StringReference}, {"compose", MagickComposeOptions} } },
237     { "Implode", { {"amount", RealReference},
238       {"interpolate", MagickInterpolateOptions} } },
239     { "Magnify", },
240     { "MedianFilter", { {"geometry", StringReference},
241       {"width", IntegerReference}, {"height", IntegerReference},
242       {"channel", MagickChannelOptions} } },
243     { "Minify", },
244     { "OilPaint", { {"radius", RealReference}, {"sigma", RealReference} } },
245     { "ReduceNoise", { {"geometry", StringReference},
246       {"width", IntegerReference},{"height", IntegerReference},
247       {"channel", MagickChannelOptions} } },
248     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
249       {"y", IntegerReference} } },
250     { "Rotate", { {"degrees", RealReference},
251       {"background", StringReference} } },
252     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
253       {"height", IntegerReference} } },
254     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
255       {"height", IntegerReference} } },
256     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
257       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
258     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
259       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
260     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
261       {"y", RealReference}, { "fill", StringReference},
262       {"color", StringReference} } },
263     { "Spread", { {"radius", RealReference},
264       {"interpolate", MagickInterpolateOptions} } },
265     { "Swirl", { {"degrees", RealReference},
266       {"interpolate", MagickInterpolateOptions} } },
267     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
268       {"height", IntegerReference}, {"filter", MagickFilterOptions},
269       {"support", StringReference } } },
270     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
271       {"height", IntegerReference}, {"filter", MagickFilterOptions},
272       {"support", RealReference } } },
273     { "Annotate", { {"text", StringReference}, {"font", StringReference},
274       {"pointsize", RealReference}, {"density", StringReference},
275       {"undercolor", StringReference}, {"stroke", StringReference},
276       {"fill", StringReference}, {"geometry", StringReference},
277       {"sans", StringReference}, {"x", RealReference},
278       {"y", RealReference}, {"gravity", MagickGravityOptions},
279       {"translate", StringReference}, {"scale", StringReference},
280       {"rotate", RealReference}, {"skewX", RealReference},
281       {"skewY", RealReference}, {"strokewidth", RealReference},
282       {"antialias", MagickBooleanOptions}, {"family", StringReference},
283       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
284       {"weight", IntegerReference}, {"align", MagickAlignOptions},
285       {"encoding", StringReference}, {"affine", ArrayReference},
286       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
287       {"tile", ImageReference}, {"kerning", RealReference},
288       {"interline-spacing", RealReference},
289       {"interword-spacing", RealReference},
290       {"direction", MagickDirectionOptions} } },
291     { "ColorFloodfill", { {"geometry", StringReference},
292       {"x", IntegerReference}, {"y", IntegerReference},
293       {"fill", StringReference}, {"bordercolor", StringReference},
294       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
295     { "Composite", { {"image", ImageReference},
296       {"compose", MagickComposeOptions}, {"geometry", StringReference},
297       {"x", IntegerReference}, {"y", IntegerReference},
298       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
299       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
300       {"color", StringReference}, {"mask", ImageReference},
301       {"channel", MagickChannelOptions},
302       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
303       {"blend", StringReference}, {"crop-to-self", MagickBooleanOptions} } },
304     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
305     { "CycleColormap", { {"display", IntegerReference} } },
306     { "Draw", { {"primitive", MagickPrimitiveOptions},
307       {"points", StringReference}, {"method", MagickMethodOptions},
308       {"stroke", StringReference}, {"fill", StringReference},
309       {"strokewidth", RealReference}, {"font", StringReference},
310       {"bordercolor", StringReference}, {"x", RealReference},
311       {"y", RealReference}, {"translate", StringReference},
312       {"scale", StringReference}, {"rotate", RealReference},
313       {"skewX", RealReference}, {"skewY", RealReference},
314       {"tile", ImageReference}, {"pointsize", RealReference},
315       {"antialias", MagickBooleanOptions}, {"density", StringReference},
316       {"linewidth", RealReference}, {"affine", ArrayReference},
317       {"stroke-dashoffset", RealReference},
318       {"stroke-dasharray", ArrayReference},
319       {"interpolate", MagickInterpolateOptions},
320       {"origin", StringReference}, {"text", StringReference},
321       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
322       {"vector-graphics", StringReference}, {"kerning", RealReference},
323       {"interline-spacing", RealReference},
324       {"interword-spacing", RealReference},
325       {"direction", MagickDirectionOptions} } },
326     { "Equalize", { {"channel", MagickChannelOptions} } },
327     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
328       {"red", RealReference}, {"green", RealReference},
329       {"blue", RealReference} } },
330     { "Map", { {"image", ImageReference},
331       {"dither-method", MagickDitherOptions} } },
332     { "MatteFloodfill", { {"geometry", StringReference},
333       {"x", IntegerReference}, {"y", IntegerReference},
334       {"opacity", StringReference}, {"bordercolor", StringReference},
335       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
336     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
337       {"saturation", RealReference}, {"whiteness", RealReference},
338       {"brightness", RealReference}, {"lightness", RealReference},
339       {"blackness", RealReference} } },
340     { "Negate", { {"gray", MagickBooleanOptions},
341       {"channel", MagickChannelOptions} } },
342     { "Normalize", { {"channel", MagickChannelOptions} } },
343     { "NumberColors", },
344     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
345       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
346       {"invert", MagickBooleanOptions} } },
347     { "Quantize", { {"colors", IntegerReference},
348       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
349       {"dither", MagickDitherOptions}, {"measure", MagickBooleanOptions},
350       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
351       {"dither-method", MagickDitherOptions} } },
352     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
353       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
354     { "Segment", { {"geometry", StringReference},
355       {"cluster-threshold", RealReference},
356       {"smoothing-threshold", RealReference},
357       {"colorspace", MagickColorspaceOptions},
358       {"verbose", MagickBooleanOptions} } },
359     { "Signature", },
360     { "Solarize", { {"geometry", StringReference},
361       {"threshold", StringReference} } },
362     { "Sync", },
363     { "Texture", { {"texture", ImageReference} } },
364     { "Evaluate", { {"value", RealReference},
365       {"operator", MagickEvaluateOptions},
366       {"channel", MagickChannelOptions} } },
367     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
368       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
369     { "Threshold", { {"threshold", StringReference},
370       {"channel", MagickChannelOptions} } },
371     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
372       {"sigma", RealReference} } },
373     { "Trim", { {"fuzz", StringReference} } },
374     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
375       {"wavelength", RealReference},
376       {"interpolate", MagickInterpolateOptions} } },
377     { "Separate", { {"channel", MagickChannelOptions} } },
378     { "Condense", },
379     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
380       {"y", IntegerReference} } },
381     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
382     { "Deconstruct", },
383     { "GaussianBlur", { {"geometry", StringReference},
384       {"radius", RealReference}, {"sigma", RealReference},
385       {"channel", MagickChannelOptions} } },
386     { "Convolve", { {"coefficients", ArrayReference},
387       {"channel", MagickChannelOptions}, {"bias", StringReference},
388       {"kernel", StringReference} } },
389     { "Profile", { {"name", StringReference}, {"profile", StringReference},
390       { "rendering-intent", MagickIntentOptions},
391       { "black-point-compensation", MagickBooleanOptions} } },
392     { "UnsharpMask", { {"geometry", StringReference},
393       {"radius", RealReference}, {"sigma", RealReference},
394       {"gain", RealReference}, {"threshold", RealReference},
395       {"channel", MagickChannelOptions} } },
396     { "MotionBlur", { {"geometry", StringReference},
397       {"radius", RealReference}, {"sigma", RealReference},
398       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
399     { "OrderedDither", { {"threshold", StringReference},
400       {"channel", MagickChannelOptions} } },
401     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
402       {"height", IntegerReference} } },
403     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
404       {"white-point", RealReference}, {"gamma", RealReference},
405       {"channel", MagickChannelOptions}, {"level", StringReference} } },
406     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
407     { "AffineTransform", { {"affine", ArrayReference},
408       {"translate", StringReference}, {"scale", StringReference},
409       {"rotate", RealReference}, {"skewX", RealReference},
410       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
411       {"background", StringReference} } },
412     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
413     { "AdaptiveThreshold", { {"geometry", StringReference},
414       {"width", IntegerReference}, {"height", IntegerReference} } },
415     { "Resample", { {"density", StringReference}, {"x", RealReference},
416       {"y", RealReference}, {"filter", MagickFilterOptions},
417       {"support", RealReference } } },
418     { "Describe", { {"file", FileReference} } },
419     { "BlackThreshold", { {"threshold", StringReference},
420       {"channel", MagickChannelOptions} } },
421     { "WhiteThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "RotationalBlur", { {"geometry", StringReference},
424       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
425     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
426       {"height", IntegerReference} } },
427     { "Strip", },
428     { "Tint", { {"fill", StringReference}, {"blend", StringReference} } },
429     { "Channel", { {"channel", MagickChannelOptions} } },
430     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
431       {"height", IntegerReference}, {"x", IntegerReference},
432       {"y", IntegerReference}, {"fuzz", StringReference},
433       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
434     { "Posterize", { {"levels", IntegerReference},
435       {"dither", MagickBooleanOptions} } },
436     { "Shadow", { {"geometry", StringReference}, {"alpha", RealReference},
437       {"sigma", RealReference}, {"x", IntegerReference},
438       {"y", IntegerReference} } },
439     { "Identify", { {"file", FileReference}, {"features", StringReference},
440       {"unique", MagickBooleanOptions} } },
441     { "SepiaTone", { {"threshold", RealReference} } },
442     { "SigmoidalContrast", { {"geometry", StringReference},
443       {"contrast", RealReference}, {"mid-point", RealReference},
444       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
445     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
446       {"height", IntegerReference}, {"x", IntegerReference},
447       {"y", IntegerReference}, {"fuzz", StringReference},
448       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
449     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
450       {"sigma", RealReference}, {"x", IntegerReference},
451       {"y", IntegerReference}, {"background", StringReference} } },
452     { "ContrastStretch", { {"levels", StringReference},
453       {"black-point", RealReference},{"white-point", RealReference},
454       {"channel", MagickChannelOptions} } },
455     { "Sans0", },
456     { "Sans1", },
457     { "AdaptiveSharpen", { {"geometry", StringReference},
458       {"radius", RealReference}, {"sigma", RealReference},
459       {"bias", RealReference}, {"channel", MagickChannelOptions} } },
460     { "Transpose", },
461     { "Transverse", },
462     { "AutoOrient", },
463     { "AdaptiveBlur", { {"geometry", StringReference},
464       {"radius", RealReference}, {"sigma", RealReference},
465       {"channel", MagickChannelOptions} } },
466     { "Sketch", { {"geometry", StringReference},
467       {"radius", RealReference}, {"sigma", RealReference},
468       {"angle", RealReference} } },
469     { "UniqueColors", },
470     { "AdaptiveResize", { {"geometry", StringReference},
471       {"width", IntegerReference}, {"height", IntegerReference},
472       {"filter", MagickFilterOptions}, {"support", StringReference },
473       {"blur", RealReference } } },
474     { "ClipMask", { {"mask", ImageReference} } },
475     { "LinearStretch", { {"levels", StringReference},
476       {"black-point", RealReference},{"white-point", RealReference} } },
477     { "ColorMatrix", { {"matrix", ArrayReference} } },
478     { "Mask", { {"mask", ImageReference} } },
479     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
480       {"font", StringReference}, {"stroke", StringReference},
481       {"fill", StringReference}, {"strokewidth", RealReference},
482       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
483       {"background", StringReference},
484       {"interpolate", MagickInterpolateOptions} } },
485     { "FloodfillPaint", { {"geometry", StringReference},
486       {"x", IntegerReference}, {"y", IntegerReference},
487       {"fill", StringReference}, {"bordercolor", StringReference},
488       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
489       {"invert", MagickBooleanOptions} } },
490     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
491       {"virtual-pixel", MagickVirtualPixelOptions},
492       {"best-fit", MagickBooleanOptions} } },
493     { "Clut", { {"image", ImageReference},
494       {"interpolate", MagickInterpolateOptions},
495       {"channel", MagickChannelOptions} } },
496     { "LiquidRescale", { {"geometry", StringReference},
497       {"width", IntegerReference}, {"height", IntegerReference},
498       {"delta-x", RealReference}, {"rigidity", RealReference } } },
499     { "Encipher", { {"passphrase", StringReference} } },
500     { "Decipher", { {"passphrase", StringReference} } },
501     { "Deskew", { {"geometry", StringReference},
502       {"threshold", StringReference} } },
503     { "Remap", { {"image", ImageReference},
504       {"dither-method", MagickDitherOptions} } },
505     { "SparseColor", { {"points", ArrayReference},
506       {"method", MagickSparseColorOptions},
507       {"virtual-pixel", MagickVirtualPixelOptions},
508       {"channel", MagickChannelOptions} } },
509     { "Function", { {"parameters", ArrayReference},
510       {"function", MagickFunctionOptions},
511       {"virtual-pixel", MagickVirtualPixelOptions} } },
512     { "SelectiveBlur", { {"geometry", StringReference},
513       {"radius", RealReference}, {"sigma", RealReference},
514       {"threshold", RealReference}, {"channel", MagickChannelOptions} } },
515     { "HaldClut", { {"image", ImageReference},
516       {"channel", MagickChannelOptions} } },
517     { "BlueShift", { {"factor", StringReference} } },
518     { "ForwardFourierTransform", { {"magnitude", MagickBooleanOptions} } },
519     { "InverseFourierTransform", { {"magnitude", MagickBooleanOptions} } },
520     { "ColorDecisionList", {
521       {"color-correction-collection", StringReference} } },
522     { "AutoGamma", { {"channel", MagickChannelOptions} } },
523     { "AutoLevel", { {"channel", MagickChannelOptions} } },
524     { "LevelColors", { {"invert", MagickBooleanOptions},
525       {"black-point", StringReference}, {"white-point", StringReference},
526       {"channel", MagickChannelOptions}, {"invert", MagickBooleanOptions} } },
527     { "Clamp", { {"channel", MagickChannelOptions} } },
528     { "BrightnessContrast", { {"levels", StringReference},
529       {"brightness", RealReference},{"contrast", RealReference},
530       {"channel", MagickChannelOptions} } },
531     { "Morphology", { {"kernel", StringReference},
532       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
533       {"iterations", IntegerReference} } },
534     { "Sans", { {"matrix", ArrayReference} } },
535     { "Color", { {"color", StringReference} } },
536     { "Mode", { {"geometry", StringReference},
537       {"width", IntegerReference},{"height", IntegerReference},
538       {"channel", MagickChannelOptions} } },
539     { "Statistic", { {"geometry", StringReference},
540       {"width", IntegerReference},{"height", IntegerReference},
541       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } },
542     { "Perceptible", { {"epsilon", RealReference},
543       {"channel", MagickChannelOptions} } },
544     { "Poly", { {"terms", ArrayReference},
545       {"channel", MagickChannelOptions} } },
546     { "Grayscale", { {"method", MagickNoiseOptions} } },
547     { "CannyEdge", { {"geometry", StringReference},
548       {"radius", RealReference}, {"sigma", RealReference},
549       {"lower-percent", RealReference}, {"upper-percent", RealReference} } },
550     { "HoughLine", { {"geometry", StringReference},
551       {"width", IntegerReference}, {"height", IntegerReference},
552       {"threshold", IntegerReference} } },
553     { "MeanShift", { {"geometry", StringReference},
554       {"width", IntegerReference}, {"height", IntegerReference},
555       {"distance", RealReference} } },
556     { "Kuwahara", { {"geometry", StringReference}, {"radius", RealReference},
557       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
558     { "ConnectedComponents", { {"connectivity", IntegerReference} } },
559   };
560
561 static SplayTreeInfo
562   *magick_registry = (SplayTreeInfo *) NULL;
563 \f
564 /*
565   Forward declarations.
566 */
567 static Image
568   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
569
570 static ssize_t
571   strEQcase(const char *,const char *);
572 \f
573 /*
574 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
575 %                                                                             %
576 %                                                                             %
577 %                                                                             %
578 %   C l o n e P a c k a g e I n f o                                           %
579 %                                                                             %
580 %                                                                             %
581 %                                                                             %
582 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583 %
584 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
585 %  a new one.
586 %
587 %  The format of the ClonePackageInfo routine is:
588 %
589 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
590 %        exception)
591 %
592 %  A description of each parameter follows:
593 %
594 %    o info: a structure of type info.
595 %
596 %    o exception: Return any errors or warnings in this structure.
597 %
598 */
599 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
600   ExceptionInfo *exception)
601 {
602   struct PackageInfo
603     *clone_info;
604
605   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
606   if (clone_info == (struct PackageInfo *) NULL)
607     {
608       ThrowPerlException(exception,ResourceLimitError,
609         "UnableToClonePackageInfo",PackageName);
610       return((struct PackageInfo *) NULL);
611     }
612   if (info == (struct PackageInfo *) NULL)
613     {
614       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
615       return(clone_info);
616     }
617   *clone_info=(*info);
618   clone_info->image_info=CloneImageInfo(info->image_info);
619   return(clone_info);
620 }
621 \f
622 /*
623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
624 %                                                                             %
625 %                                                                             %
626 %                                                                             %
627 %   c o n s t a n t                                                           %
628 %                                                                             %
629 %                                                                             %
630 %                                                                             %
631 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
632 %
633 %  constant() returns a double value for the specified name.
634 %
635 %  The format of the constant routine is:
636 %
637 %      double constant(char *name,ssize_t sans)
638 %
639 %  A description of each parameter follows:
640 %
641 %    o value: Method constant returns a double value for the specified name.
642 %
643 %    o name: The name of the constant.
644 %
645 %    o sans: This integer value is not used.
646 %
647 */
648 static double constant(char *name,ssize_t sans)
649 {
650   (void) sans;
651   errno=0;
652   switch (*name)
653   {
654     case 'B':
655     {
656       if (strEQ(name,"BlobError"))
657         return(BlobError);
658       if (strEQ(name,"BlobWarning"))
659         return(BlobWarning);
660       break;
661     }
662     case 'C':
663     {
664       if (strEQ(name,"CacheError"))
665         return(CacheError);
666       if (strEQ(name,"CacheWarning"))
667         return(CacheWarning);
668       if (strEQ(name,"CoderError"))
669         return(CoderError);
670       if (strEQ(name,"CoderWarning"))
671         return(CoderWarning);
672       if (strEQ(name,"ConfigureError"))
673         return(ConfigureError);
674       if (strEQ(name,"ConfigureWarning"))
675         return(ConfigureWarning);
676       if (strEQ(name,"CorruptImageError"))
677         return(CorruptImageError);
678       if (strEQ(name,"CorruptImageWarning"))
679         return(CorruptImageWarning);
680       break;
681     }
682     case 'D':
683     {
684       if (strEQ(name,"DelegateError"))
685         return(DelegateError);
686       if (strEQ(name,"DelegateWarning"))
687         return(DelegateWarning);
688       if (strEQ(name,"DrawError"))
689         return(DrawError);
690       if (strEQ(name,"DrawWarning"))
691         return(DrawWarning);
692       break;
693     }
694     case 'E':
695     {
696       if (strEQ(name,"ErrorException"))
697         return(ErrorException);
698       if (strEQ(name,"ExceptionError"))
699         return(CoderError);
700       if (strEQ(name,"ExceptionWarning"))
701         return(CoderWarning);
702       break;
703     }
704     case 'F':
705     {
706       if (strEQ(name,"FatalErrorException"))
707         return(FatalErrorException);
708       if (strEQ(name,"FileOpenError"))
709         return(FileOpenError);
710       if (strEQ(name,"FileOpenWarning"))
711         return(FileOpenWarning);
712       break;
713     }
714     case 'I':
715     {
716       if (strEQ(name,"ImageError"))
717         return(ImageError);
718       if (strEQ(name,"ImageWarning"))
719         return(ImageWarning);
720       break;
721     }
722     case 'M':
723     {
724       if (strEQ(name,"MaxRGB"))
725         return(QuantumRange);
726       if (strEQ(name,"MissingDelegateError"))
727         return(MissingDelegateError);
728       if (strEQ(name,"MissingDelegateWarning"))
729         return(MissingDelegateWarning);
730       if (strEQ(name,"ModuleError"))
731         return(ModuleError);
732       if (strEQ(name,"ModuleWarning"))
733         return(ModuleWarning);
734       break;
735     }
736     case 'O':
737     {
738       if (strEQ(name,"Opaque"))
739         return(OpaqueAlpha);
740       if (strEQ(name,"OptionError"))
741         return(OptionError);
742       if (strEQ(name,"OptionWarning"))
743         return(OptionWarning);
744       break;
745     }
746     case 'Q':
747     {
748       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
749         return(MAGICKCORE_QUANTUM_DEPTH);
750       if (strEQ(name,"QuantumDepth"))
751         return(MAGICKCORE_QUANTUM_DEPTH);
752       if (strEQ(name,"QuantumRange"))
753         return(QuantumRange);
754       break;
755     }
756     case 'R':
757     {
758       if (strEQ(name,"ResourceLimitError"))
759         return(ResourceLimitError);
760       if (strEQ(name,"ResourceLimitWarning"))
761         return(ResourceLimitWarning);
762       if (strEQ(name,"RegistryError"))
763         return(RegistryError);
764       if (strEQ(name,"RegistryWarning"))
765         return(RegistryWarning);
766       break;
767     }
768     case 'S':
769     {
770       if (strEQ(name,"StreamError"))
771         return(StreamError);
772       if (strEQ(name,"StreamWarning"))
773         return(StreamWarning);
774       if (strEQ(name,"Success"))
775         return(0);
776       break;
777     }
778     case 'T':
779     {
780       if (strEQ(name,"Transparent"))
781         return(TransparentAlpha);
782       if (strEQ(name,"TypeError"))
783         return(TypeError);
784       if (strEQ(name,"TypeWarning"))
785         return(TypeWarning);
786       break;
787     }
788     case 'W':
789     {
790       if (strEQ(name,"WarningException"))
791         return(WarningException);
792       break;
793     }
794     case 'X':
795     {
796       if (strEQ(name,"XServerError"))
797         return(XServerError);
798       if (strEQ(name,"XServerWarning"))
799         return(XServerWarning);
800       break;
801     }
802   }
803   errno=EINVAL;
804   return(0);
805 }
806 \f
807 /*
808 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
809 %                                                                             %
810 %                                                                             %
811 %                                                                             %
812 %   D e s t r o y P a c k a g e I n f o                                       %
813 %                                                                             %
814 %                                                                             %
815 %                                                                             %
816 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817 %
818 %  Method DestroyPackageInfo frees a previously created info structure.
819 %
820 %  The format of the DestroyPackageInfo routine is:
821 %
822 %      DestroyPackageInfo(struct PackageInfo *info)
823 %
824 %  A description of each parameter follows:
825 %
826 %    o info: a structure of type info.
827 %
828 */
829 static void DestroyPackageInfo(struct PackageInfo *info)
830 {
831   info->image_info=DestroyImageInfo(info->image_info);
832   info=(struct PackageInfo *) RelinquishMagickMemory(info);
833 }
834 \f
835 /*
836 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
837 %                                                                             %
838 %                                                                             %
839 %                                                                             %
840 %   G e t L i s t                                                             %
841 %                                                                             %
842 %                                                                             %
843 %                                                                             %
844 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
845 %
846 %  Method GetList is recursively called by SetupList to traverse the
847 %  Image__Magick reference.  If building an reference_vector (see SetupList),
848 %  *current is the current position in *reference_vector and *last is the final
849 %  entry in *reference_vector.
850 %
851 %  The format of the GetList routine is:
852 %
853 %      GetList(info)
854 %
855 %  A description of each parameter follows:
856 %
857 %    o info: a structure of type info.
858 %
859 */
860 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
861   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
862 {
863   Image
864     *image;
865
866   if (reference == (SV *) NULL)
867     return(NULL);
868   switch (SvTYPE(reference))
869   {
870     case SVt_PVAV:
871     {
872       AV
873         *av;
874
875       Image
876         *head,
877         *previous;
878
879       register ssize_t
880         i;
881
882       ssize_t
883         n;
884
885       /*
886         Array of images.
887       */
888       previous=(Image *) NULL;
889       head=(Image *) NULL;
890       av=(AV *) reference;
891       n=av_len(av);
892       for (i=0; i <= n; i++)
893       {
894         SV
895           **rv;
896
897         rv=av_fetch(av,i,0);
898         if (rv && *rv && sv_isobject(*rv))
899           {
900             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
901               exception);
902             if (image == (Image *) NULL)
903               continue;
904             if (image == previous)
905               {
906                 image=CloneImage(image,0,0,MagickTrue,exception);
907                 if (image == (Image *) NULL)
908                   return(NULL);
909               }
910             image->previous=previous;
911             *(previous ? &previous->next : &head)=image;
912             for (previous=image; previous->next; previous=previous->next) ;
913           }
914       }
915       return(head);
916     }
917     case SVt_PVMG:
918     {
919       /*
920         Blessed scalar, one image.
921       */
922       image=INT2PTR(Image *,SvIV(reference));
923       if (image == (Image *) NULL)
924         return(NULL);
925       image->previous=(Image *) NULL;
926       image->next=(Image *) NULL;
927       if (reference_vector)
928         {
929           if (*current == *last)
930             {
931               *last+=256;
932               if (*reference_vector == (SV **) NULL)
933                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
934                   sizeof(*reference_vector));
935               else
936                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
937                   *last,sizeof(*reference_vector));
938             }
939           if (*reference_vector == (SV **) NULL)
940             {
941               ThrowPerlException(exception,ResourceLimitError,
942                 "MemoryAllocationFailed",PackageName);
943               return((Image *) NULL);
944             }
945           (*reference_vector)[*current]=reference;
946           (*reference_vector)[++(*current)]=NULL;
947         }
948       return(image);
949     }
950     default:
951       break;
952   }
953   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
954     (double) SvTYPE(reference));
955   return((Image *) NULL);
956 }
957 \f
958 /*
959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
960 %                                                                             %
961 %                                                                             %
962 %                                                                             %
963 %   G e t P a c k a g e I n f o                                               %
964 %                                                                             %
965 %                                                                             %
966 %                                                                             %
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
968 %
969 %  Method GetPackageInfo looks up or creates an info structure for the given
970 %  Image__Magick reference.  If it does create a new one, the information in
971 %  package_info is used to initialize it.
972 %
973 %  The format of the GetPackageInfo routine is:
974 %
975 %      struct PackageInfo *GetPackageInfo(void *reference,
976 %        struct PackageInfo *package_info,ExceptionInfo *exception)
977 %
978 %  A description of each parameter follows:
979 %
980 %    o info: a structure of type info.
981 %
982 %    o exception: Return any errors or warnings in this structure.
983 %
984 */
985 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
986   struct PackageInfo *package_info,ExceptionInfo *exception)
987 {
988   char
989     message[MagickPathExtent];
990
991   struct PackageInfo
992     *clone_info;
993
994   SV
995     *sv;
996
997   (void) FormatLocaleString(message,MagickPathExtent,"%s::package%s%p",
998     PackageName,XS_VERSION,reference);
999   sv=perl_get_sv(message,(TRUE | 0x02));
1000   if (sv == (SV *) NULL)
1001     {
1002       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
1003         message);
1004       return(package_info);
1005     }
1006   if (SvREFCNT(sv) == 0)
1007     (void) SvREFCNT_inc(sv);
1008   if (SvIOKp(sv) && (clone_info=INT2PTR(struct PackageInfo *,SvIV(sv))))
1009     return(clone_info);
1010   clone_info=ClonePackageInfo(package_info,exception);
1011   sv_setiv(sv,PTR2IV(clone_info));
1012   return(clone_info);
1013 }
1014 \f
1015 /*
1016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1017 %                                                                             %
1018 %                                                                             %
1019 %                                                                             %
1020 %   S e t A t t r i b u t e                                                   %
1021 %                                                                             %
1022 %                                                                             %
1023 %                                                                             %
1024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1025 %
1026 %  SetAttribute() sets the attribute to the value in sval.  This can change
1027 %  either or both of image or info.
1028 %
1029 %  The format of the SetAttribute routine is:
1030 %
1031 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1032 %        SV *sval,ExceptionInfo *exception)
1033 %
1034 %  A description of each parameter follows:
1035 %
1036 %    o list: a list of strings.
1037 %
1038 %    o string: a character string.
1039 %
1040 */
1041
1042 static double SiPrefixToDoubleInterval(const char *string,const double interval)
1043 {
1044   char
1045     *q;
1046
1047   double
1048     value;
1049
1050   value=InterpretSiPrefixValue(string,&q);
1051   if (*q == '%')
1052     value*=interval/100.0;
1053   return(value);
1054 }
1055
1056 static inline double StringToDouble(const char *string,char **sentinal)
1057 {
1058   return(InterpretLocaleValue(string,sentinal));
1059 }
1060
1061 static double StringToDoubleInterval(const char *string,const double interval)
1062 {
1063   char
1064     *q;
1065
1066   double
1067     value;
1068
1069   value=InterpretLocaleValue(string,&q);
1070   if (*q == '%')
1071     value*=interval/100.0;
1072   return(value);
1073 }
1074
1075 static inline ssize_t StringToLong(const char *value)
1076 {
1077   return(strtol(value,(char **) NULL,10));
1078 }
1079
1080 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1081   const char *attribute,SV *sval,ExceptionInfo *exception)
1082 {
1083   GeometryInfo
1084     geometry_info;
1085
1086   long
1087     x,
1088     y;
1089
1090   PixelInfo
1091     pixel;
1092
1093   MagickStatusType
1094     flags;
1095
1096   PixelInfo
1097     *color,
1098     target_color;
1099
1100   ssize_t
1101     sp;
1102
1103   switch (*attribute)
1104   {
1105     case 'A':
1106     case 'a':
1107     {
1108       if (LocaleCompare(attribute,"adjoin") == 0)
1109         {
1110           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1111             SvPV(sval,na)) : SvIV(sval);
1112           if (sp < 0)
1113             {
1114               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1115                 SvPV(sval,na));
1116               break;
1117             }
1118           if (info)
1119             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1120           break;
1121         }
1122       if (LocaleCompare(attribute,"alpha") == 0)
1123         {
1124           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaChannelOptions,
1125             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1126           if (sp < 0)
1127             {
1128               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1129                 SvPV(sval,na));
1130               break;
1131             }
1132           for ( ; image; image=image->next)
1133             (void) SetImageAlphaChannel(image,(AlphaChannelOption) sp,
1134               exception);
1135           break;
1136         }
1137       if (LocaleCompare(attribute,"antialias") == 0)
1138         {
1139           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1140             SvPV(sval,na)) : SvIV(sval);
1141           if (sp < 0)
1142             {
1143               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1144                 SvPV(sval,na));
1145               break;
1146             }
1147           if (info)
1148             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1149           break;
1150         }
1151       if (LocaleCompare(attribute,"area-limit") == 0)
1152         {
1153           MagickSizeType
1154             limit;
1155
1156           limit=MagickResourceInfinity;
1157           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1158             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1159               100.0);
1160           (void) SetMagickResourceLimit(AreaResource,limit);
1161           break;
1162         }
1163       if (LocaleCompare(attribute,"attenuate") == 0)
1164         {
1165           if (info)
1166             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1167           break;
1168         }
1169       if (LocaleCompare(attribute,"authenticate") == 0)
1170         {
1171           if (info)
1172             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1173           break;
1174         }
1175       if (info)
1176         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1177       for ( ; image; image=image->next)
1178         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1179       break;
1180     }
1181     case 'B':
1182     case 'b':
1183     {
1184       if (LocaleCompare(attribute,"background") == 0)
1185         {
1186           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1187             exception);
1188           if (info)
1189             info->image_info->background_color=target_color;
1190           for ( ; image; image=image->next)
1191             image->background_color=target_color;
1192           break;
1193         }
1194       if (LocaleCompare(attribute,"blue-primary") == 0)
1195         {
1196           for ( ; image; image=image->next)
1197           {
1198             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1199             image->chromaticity.blue_primary.x=geometry_info.rho;
1200             image->chromaticity.blue_primary.y=geometry_info.sigma;
1201             if ((flags & SigmaValue) == 0)
1202               image->chromaticity.blue_primary.y=
1203                 image->chromaticity.blue_primary.x;
1204           }
1205           break;
1206         }
1207       if (LocaleCompare(attribute,"bordercolor") == 0)
1208         {
1209           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1210             exception);
1211           if (info)
1212             info->image_info->border_color=target_color;
1213           for ( ; image; image=image->next)
1214             image->border_color=target_color;
1215           break;
1216         }
1217       if (info)
1218         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1219       for ( ; image; image=image->next)
1220         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1221       break;
1222     }
1223     case 'C':
1224     case 'c':
1225     {
1226       if (LocaleCompare(attribute,"cache-threshold") == 0)
1227         {
1228           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1229             SiPrefixToDoubleInterval(SvPV(sval,na),100.0));
1230           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1231             (2.0*SiPrefixToDoubleInterval(SvPV(sval,na),100.0)));
1232           break;
1233         }
1234       if (LocaleCompare(attribute,"clip-mask") == 0)
1235         {
1236           Image
1237             *clip_mask;
1238
1239           clip_mask=(Image *) NULL;
1240           if (SvPOK(sval))
1241             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1242           for ( ; image; image=image->next)
1243             SetImageMask(image,clip_mask,exception);
1244           break;
1245         }
1246       if (LocaleNCompare(attribute,"colormap",8) == 0)
1247         {
1248           for ( ; image; image=image->next)
1249           {
1250             int
1251               items;
1252
1253             long
1254               i;
1255
1256             if (image->storage_class == DirectClass)
1257               continue;
1258             i=0;
1259             items=sscanf(attribute,"%*[^[][%ld",&i);
1260             (void) items;
1261             if (i > (ssize_t) image->colors)
1262               i%=image->colors;
1263             if ((strchr(SvPV(sval,na),',') == 0) ||
1264                 (strchr(SvPV(sval,na),')') != 0))
1265               QueryColorCompliance(SvPV(sval,na),AllCompliance,
1266                 image->colormap+i,exception);
1267             else
1268               {
1269                 color=image->colormap+i;
1270                 pixel.red=color->red;
1271                 pixel.green=color->green;
1272                 pixel.blue=color->blue;
1273                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1274                 pixel.red=geometry_info.rho;
1275                 pixel.green=geometry_info.sigma;
1276                 pixel.blue=geometry_info.xi;
1277                 color->red=ClampToQuantum(pixel.red);
1278                 color->green=ClampToQuantum(pixel.green);
1279                 color->blue=ClampToQuantum(pixel.blue);
1280               }
1281           }
1282           break;
1283         }
1284       if (LocaleCompare(attribute,"colorspace") == 0)
1285         {
1286           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1287             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1288           if (sp < 0)
1289             {
1290               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1291                 SvPV(sval,na));
1292               break;
1293             }
1294           for ( ; image; image=image->next)
1295             (void) TransformImageColorspace(image,(ColorspaceType) sp,
1296               exception);
1297           break;
1298         }
1299       if (LocaleCompare(attribute,"comment") == 0)
1300         {
1301           for ( ; image; image=image->next)
1302             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1303               info ? info->image_info : (ImageInfo *) NULL,image,
1304               SvPV(sval,na),exception),exception);
1305           break;
1306         }
1307       if (LocaleCompare(attribute,"compression") == 0)
1308         {
1309           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1310             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1311           if (sp < 0)
1312             {
1313               ThrowPerlException(exception,OptionError,
1314                 "UnrecognizedImageCompression",SvPV(sval,na));
1315               break;
1316             }
1317           if (info)
1318             info->image_info->compression=(CompressionType) sp;
1319           for ( ; image; image=image->next)
1320             image->compression=(CompressionType) sp;
1321           break;
1322         }
1323       if (info)
1324         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1325       for ( ; image; image=image->next)
1326         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1327       break;
1328     }
1329     case 'D':
1330     case 'd':
1331     {
1332       if (LocaleCompare(attribute,"debug") == 0)
1333         {
1334           SetLogEventMask(SvPV(sval,na));
1335           break;
1336         }
1337       if (LocaleCompare(attribute,"delay") == 0)
1338         {
1339           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1340           for ( ; image; image=image->next)
1341           {
1342             image->delay=(size_t) floor(geometry_info.rho+0.5);
1343             if ((flags & SigmaValue) != 0)
1344               image->ticks_per_second=(ssize_t)
1345                 floor(geometry_info.sigma+0.5);
1346           }
1347           break;
1348         }
1349       if (LocaleCompare(attribute,"disk-limit") == 0)
1350         {
1351           MagickSizeType
1352             limit;
1353
1354           limit=MagickResourceInfinity;
1355           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1356             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1357               100.0);
1358           (void) SetMagickResourceLimit(DiskResource,limit);
1359           break;
1360         }
1361       if (LocaleCompare(attribute,"density") == 0)
1362         {
1363           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1364             {
1365               ThrowPerlException(exception,OptionError,"MissingGeometry",
1366                 SvPV(sval,na));
1367               break;
1368             }
1369           if (info)
1370             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1371           for ( ; image; image=image->next)
1372           {
1373             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1374             image->resolution.x=geometry_info.rho;
1375             image->resolution.y=geometry_info.sigma;
1376             if ((flags & SigmaValue) == 0)
1377               image->resolution.y=image->resolution.x;
1378           }
1379           break;
1380         }
1381       if (LocaleCompare(attribute,"depth") == 0)
1382         {
1383           if (info)
1384             info->image_info->depth=SvIV(sval);
1385           for ( ; image; image=image->next)
1386             (void) SetImageDepth(image,SvIV(sval),exception);
1387           break;
1388         }
1389       if (LocaleCompare(attribute,"dispose") == 0)
1390         {
1391           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1392             SvPV(sval,na)) : SvIV(sval);
1393           if (sp < 0)
1394             {
1395               ThrowPerlException(exception,OptionError,
1396                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1397               break;
1398             }
1399           for ( ; image; image=image->next)
1400             image->dispose=(DisposeType) sp;
1401           break;
1402         }
1403       if (LocaleCompare(attribute,"dither") == 0)
1404         {
1405           if (info)
1406             {
1407               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1408                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1409               if (sp < 0)
1410                 {
1411                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1412                     SvPV(sval,na));
1413                   break;
1414                 }
1415               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1416             }
1417           break;
1418         }
1419       if (LocaleCompare(attribute,"display") == 0)
1420         {
1421           display:
1422           if (info)
1423             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1424           break;
1425         }
1426       if (info)
1427         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1428       for ( ; image; image=image->next)
1429         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1430       break;
1431     }
1432     case 'E':
1433     case 'e':
1434     {
1435       if (LocaleCompare(attribute,"endian") == 0)
1436         {
1437           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1438             SvPV(sval,na)) : SvIV(sval);
1439           if (sp < 0)
1440             {
1441               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1442                 SvPV(sval,na));
1443               break;
1444             }
1445           if (info)
1446             info->image_info->endian=(EndianType) sp;
1447           for ( ; image; image=image->next)
1448             image->endian=(EndianType) sp;
1449           break;
1450         }
1451       if (LocaleCompare(attribute,"extract") == 0)
1452         {
1453           /*
1454             Set image extract geometry.
1455           */
1456           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1457           break;
1458         }
1459       if (info)
1460         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1461       for ( ; image; image=image->next)
1462         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1463       break;
1464     }
1465     case 'F':
1466     case 'f':
1467     {
1468       if (LocaleCompare(attribute,"filename") == 0)
1469         {
1470           if (info)
1471             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1472               MagickPathExtent);
1473           for ( ; image; image=image->next)
1474             (void) CopyMagickString(image->filename,SvPV(sval,na),
1475               MagickPathExtent);
1476           break;
1477         }
1478       if (LocaleCompare(attribute,"file") == 0)
1479         {
1480           FILE
1481             *file;
1482
1483           PerlIO
1484             *io_info;
1485
1486           if (info == (struct PackageInfo *) NULL)
1487             break;
1488           io_info=IoIFP(sv_2io(sval));
1489           if (io_info == (PerlIO *) NULL)
1490             {
1491               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1492                 PackageName);
1493               break;
1494             }
1495           file=PerlIO_findFILE(io_info);
1496           if (file == (FILE *) NULL)
1497             {
1498               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1499                 PackageName);
1500               break;
1501             }
1502           SetImageInfoFile(info->image_info,file);
1503           break;
1504         }
1505       if (LocaleCompare(attribute,"fill") == 0)
1506         {
1507           if (info)
1508             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1509           break;
1510         }
1511       if (LocaleCompare(attribute,"font") == 0)
1512         {
1513           if (info)
1514             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1515           break;
1516         }
1517       if (LocaleCompare(attribute,"foreground") == 0)
1518         break;
1519       if (LocaleCompare(attribute,"fuzz") == 0)
1520         {
1521           if (info)
1522             info->image_info->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1523               QuantumRange+1.0);
1524           for ( ; image; image=image->next)
1525             image->fuzz=StringToDoubleInterval(SvPV(sval,na),(double)
1526               QuantumRange+1.0);
1527           break;
1528         }
1529       if (info)
1530         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1531       for ( ; image; image=image->next)
1532         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1533       break;
1534     }
1535     case 'G':
1536     case 'g':
1537     {
1538       if (LocaleCompare(attribute,"gamma") == 0)
1539         {
1540           for ( ; image; image=image->next)
1541             image->gamma=SvNV(sval);
1542           break;
1543         }
1544       if (LocaleCompare(attribute,"gravity") == 0)
1545         {
1546           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1547             SvPV(sval,na)) : SvIV(sval);
1548           if (sp < 0)
1549             {
1550               ThrowPerlException(exception,OptionError,
1551                 "UnrecognizedGravityType",SvPV(sval,na));
1552               break;
1553             }
1554           if (info)
1555             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1556           for ( ; image; image=image->next)
1557             image->gravity=(GravityType) sp;
1558           break;
1559         }
1560       if (LocaleCompare(attribute,"green-primary") == 0)
1561         {
1562           for ( ; image; image=image->next)
1563           {
1564             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1565             image->chromaticity.green_primary.x=geometry_info.rho;
1566             image->chromaticity.green_primary.y=geometry_info.sigma;
1567             if ((flags & SigmaValue) == 0)
1568               image->chromaticity.green_primary.y=
1569                 image->chromaticity.green_primary.x;
1570           }
1571           break;
1572         }
1573       if (info)
1574         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1575       for ( ; image; image=image->next)
1576         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1577       break;
1578     }
1579     case 'I':
1580     case 'i':
1581     {
1582       if (LocaleNCompare(attribute,"index",5) == 0)
1583         {
1584           int
1585             items;
1586
1587           long
1588             index;
1589
1590           register Quantum
1591             *q;
1592
1593           CacheView
1594             *image_view;
1595
1596           for ( ; image; image=image->next)
1597           {
1598             if (image->storage_class != PseudoClass)
1599               continue;
1600             x=0;
1601             y=0;
1602             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1603             (void) items;
1604             image_view=AcquireAuthenticCacheView(image,exception);
1605             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1606             if (q != (Quantum *) NULL)
1607               {
1608                 items=sscanf(SvPV(sval,na),"%ld",&index);
1609                 if ((index >= 0) && (index < (ssize_t) image->colors))
1610                   SetPixelIndex(image,index,q);
1611                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1612               }
1613             image_view=DestroyCacheView(image_view);
1614           }
1615           break;
1616         }
1617       if (LocaleCompare(attribute,"iterations") == 0)
1618         {
1619   iterations:
1620           for ( ; image; image=image->next)
1621             image->iterations=SvIV(sval);
1622           break;
1623         }
1624       if (LocaleCompare(attribute,"interlace") == 0)
1625         {
1626           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1627             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1628           if (sp < 0)
1629             {
1630               ThrowPerlException(exception,OptionError,
1631                 "UnrecognizedInterlaceType",SvPV(sval,na));
1632               break;
1633             }
1634           if (info)
1635             info->image_info->interlace=(InterlaceType) sp;
1636           for ( ; image; image=image->next)
1637             image->interlace=(InterlaceType) sp;
1638           break;
1639         }
1640       if (info)
1641         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1642       for ( ; image; image=image->next)
1643         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1644       break;
1645     }
1646     case 'L':
1647     case 'l':
1648     {
1649       if (LocaleCompare(attribute,"label") == 0)
1650         {
1651           for ( ; image; image=image->next)
1652             (void) SetImageProperty(image,"label",InterpretImageProperties(
1653               info ? info->image_info : (ImageInfo *) NULL,image,
1654               SvPV(sval,na),exception),exception);
1655           break;
1656         }
1657       if (LocaleCompare(attribute,"loop") == 0)
1658         goto iterations;
1659       if (info)
1660         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1661       for ( ; image; image=image->next)
1662         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1663       break;
1664     }
1665     case 'M':
1666     case 'm':
1667     {
1668       if (LocaleCompare(attribute,"magick") == 0)
1669         {
1670           if (info)
1671             (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
1672               "%s:",SvPV(sval,na));
1673           for ( ; image; image=image->next)
1674             (void) CopyMagickString(image->magick,SvPV(sval,na),MagickPathExtent);
1675           break;
1676         }
1677       if (LocaleCompare(attribute,"map-limit") == 0)
1678         {
1679           MagickSizeType
1680             limit;
1681
1682           limit=MagickResourceInfinity;
1683           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1684             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1685               100.0);
1686           (void) SetMagickResourceLimit(MapResource,limit);
1687           break;
1688         }
1689       if (LocaleCompare(attribute,"mask") == 0)
1690         {
1691           Image
1692             *mask;
1693
1694           mask=(Image *) NULL;
1695           if (SvPOK(sval))
1696             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1697           for ( ; image; image=image->next)
1698             SetImageMask(image,mask,exception);
1699           break;
1700         }
1701       if (LocaleCompare(attribute,"mattecolor") == 0)
1702         {
1703           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
1704             exception);
1705           if (info)
1706             info->image_info->matte_color=target_color;
1707           for ( ; image; image=image->next)
1708             image->matte_color=target_color;
1709           break;
1710         }
1711       if (LocaleCompare(attribute,"matte") == 0)
1712         {
1713           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1714             SvPV(sval,na)) : SvIV(sval);
1715           if (sp < 0)
1716             {
1717               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1718                 SvPV(sval,na));
1719               break;
1720             }
1721           for ( ; image; image=image->next)
1722             image->alpha_trait=sp != 0 ? BlendPixelTrait : UndefinedPixelTrait;
1723           break;
1724         }
1725       if (LocaleCompare(attribute,"memory-limit") == 0)
1726         {
1727           MagickSizeType
1728             limit;
1729
1730           limit=MagickResourceInfinity;
1731           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1732             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
1733               100.0);
1734           (void) SetMagickResourceLimit(MemoryResource,limit);
1735           break;
1736         }
1737       if (LocaleCompare(attribute,"monochrome") == 0)
1738         {
1739           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1740             SvPV(sval,na)) : SvIV(sval);
1741           if (sp < 0)
1742             {
1743               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1744                 SvPV(sval,na));
1745               break;
1746             }
1747           if (info)
1748             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1749           for ( ; image; image=image->next)
1750             (void) SetImageType(image,BilevelType,exception);
1751           break;
1752         }
1753       if (info)
1754         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1755       for ( ; image; image=image->next)
1756         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1757       break;
1758     }
1759     case 'O':
1760     case 'o':
1761     {
1762       if (LocaleCompare(attribute,"option") == 0)
1763         {
1764           if (info)
1765             DefineImageOption(info->image_info,SvPV(sval,na));
1766           break;
1767         }
1768       if (LocaleCompare(attribute,"orientation") == 0)
1769         {
1770           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1771             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1772           if (sp < 0)
1773             {
1774               ThrowPerlException(exception,OptionError,
1775                 "UnrecognizedOrientationType",SvPV(sval,na));
1776               break;
1777             }
1778           if (info)
1779             info->image_info->orientation=(OrientationType) sp;
1780           for ( ; image; image=image->next)
1781             image->orientation=(OrientationType) sp;
1782           break;
1783         }
1784       if (info)
1785         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1786       for ( ; image; image=image->next)
1787         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1788       break;
1789     }
1790     case 'P':
1791     case 'p':
1792     {
1793       if (LocaleCompare(attribute,"page") == 0)
1794         {
1795           char
1796             *geometry;
1797
1798           geometry=GetPageGeometry(SvPV(sval,na));
1799           if (info)
1800             (void) CloneString(&info->image_info->page,geometry);
1801           for ( ; image; image=image->next)
1802             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1803           geometry=(char *) RelinquishMagickMemory(geometry);
1804           break;
1805         }
1806       if (LocaleNCompare(attribute,"pixel",5) == 0)
1807         {
1808           int
1809             items;
1810
1811           PixelInfo
1812             pixel;
1813
1814           register Quantum
1815             *q;
1816
1817           CacheView
1818             *image_view;
1819
1820           for ( ; image; image=image->next)
1821           {
1822             if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1823               break;
1824             x=0;
1825             y=0;
1826             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1827             (void) items;
1828             image_view=AcquireVirtualCacheView(image,exception);
1829             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1830             if (q != (Quantum *) NULL)
1831               {
1832                 if ((strchr(SvPV(sval,na),',') == 0) ||
1833                     (strchr(SvPV(sval,na),')') != 0))
1834                   QueryColorCompliance(SvPV(sval,na),AllCompliance,
1835                     &pixel,exception);
1836                 else
1837                   {
1838                     GetPixelInfo(image,&pixel);
1839                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1840                     pixel.red=geometry_info.rho;
1841                     if ((flags & SigmaValue) != 0)
1842                       pixel.green=geometry_info.sigma;
1843                     if ((flags & XiValue) != 0)
1844                       pixel.blue=geometry_info.xi;
1845                     if ((flags & PsiValue) != 0)
1846                       pixel.alpha=geometry_info.psi;
1847                     if ((flags & ChiValue) != 0)
1848                       pixel.black=geometry_info.chi;
1849                   }
1850                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1851                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1852                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1853                 if (image->colorspace == CMYKColorspace)
1854                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1855                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1856                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1857               }
1858             image_view=DestroyCacheView(image_view);
1859           }
1860           break;
1861         }
1862       if (LocaleCompare(attribute,"pointsize") == 0)
1863         {
1864           if (info)
1865             {
1866               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1867               info->image_info->pointsize=geometry_info.rho;
1868             }
1869           break;
1870         }
1871       if (LocaleCompare(attribute,"preview") == 0)
1872         {
1873           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1874             SvPV(sval,na)) : SvIV(sval);
1875           if (sp < 0)
1876             {
1877               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1878                 SvPV(sval,na));
1879               break;
1880             }
1881           if (info)
1882             info->image_info->preview_type=(PreviewType) sp;
1883           break;
1884         }
1885       if (info)
1886         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1887       for ( ; image; image=image->next)
1888         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1889       break;
1890     }
1891     case 'Q':
1892     case 'q':
1893     {
1894       if (LocaleCompare(attribute,"quality") == 0)
1895         {
1896           if (info)
1897             info->image_info->quality=SvIV(sval);
1898           for ( ; image; image=image->next)
1899             image->quality=SvIV(sval);
1900           break;
1901         }
1902       if (info)
1903         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1904       for ( ; image; image=image->next)
1905         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1906       break;
1907     }
1908     case 'R':
1909     case 'r':
1910     {
1911       if (LocaleCompare(attribute,"red-primary") == 0)
1912         {
1913           for ( ; image; image=image->next)
1914           {
1915             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1916             image->chromaticity.red_primary.x=geometry_info.rho;
1917             image->chromaticity.red_primary.y=geometry_info.sigma;
1918             if ((flags & SigmaValue) == 0)
1919               image->chromaticity.red_primary.y=
1920                 image->chromaticity.red_primary.x;
1921           }
1922           break;
1923         }
1924       if (LocaleCompare(attribute,"render") == 0)
1925         {
1926           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1927             SvPV(sval,na)) : SvIV(sval);
1928           if (sp < 0)
1929             {
1930               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1931                 SvPV(sval,na));
1932               break;
1933             }
1934          for ( ; image; image=image->next)
1935            image->rendering_intent=(RenderingIntent) sp;
1936          break;
1937        }
1938       if (LocaleCompare(attribute,"repage") == 0)
1939         {
1940           RectangleInfo
1941             geometry;
1942
1943           for ( ; image; image=image->next)
1944           {
1945             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1946             if ((flags & WidthValue) != 0)
1947               {
1948                 if ((flags & HeightValue) == 0)
1949                   geometry.height=geometry.width;
1950                 image->page.width=geometry.width;
1951                 image->page.height=geometry.height;
1952               }
1953             if ((flags & AspectValue) != 0)
1954               {
1955                 if ((flags & XValue) != 0)
1956                   image->page.x+=geometry.x;
1957                 if ((flags & YValue) != 0)
1958                   image->page.y+=geometry.y;
1959               }
1960             else
1961               {
1962                 if ((flags & XValue) != 0)
1963                   {
1964                     image->page.x=geometry.x;
1965                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1966                       image->page.width=image->columns+geometry.x;
1967                   }
1968                 if ((flags & YValue) != 0)
1969                   {
1970                     image->page.y=geometry.y;
1971                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1972                       image->page.height=image->rows+geometry.y;
1973                   }
1974               }
1975           }
1976           break;
1977         }
1978       if (info)
1979         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1980       for ( ; image; image=image->next)
1981         SetImageProperty(image,attribute,SvPV(sval,na),exception);
1982       break;
1983     }
1984     case 'S':
1985     case 's':
1986     {
1987       if (LocaleCompare(attribute,"sampling-factor") == 0)
1988         {
1989           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1990             {
1991               ThrowPerlException(exception,OptionError,"MissingGeometry",
1992                 SvPV(sval,na));
1993               break;
1994             }
1995           if (info)
1996             (void) CloneString(&info->image_info->sampling_factor,
1997               SvPV(sval,na));
1998           break;
1999         }
2000       if (LocaleCompare(attribute,"scene") == 0)
2001         {
2002           for ( ; image; image=image->next)
2003             image->scene=SvIV(sval);
2004           break;
2005         }
2006       if (LocaleCompare(attribute,"server") == 0)
2007         goto display;
2008       if (LocaleCompare(attribute,"size") == 0)
2009         {
2010           if (info)
2011             {
2012               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
2013                 {
2014                   ThrowPerlException(exception,OptionError,"MissingGeometry",
2015                     SvPV(sval,na));
2016                   break;
2017                 }
2018               (void) CloneString(&info->image_info->size,SvPV(sval,na));
2019             }
2020           break;
2021         }
2022       if (LocaleCompare(attribute,"stroke") == 0)
2023         {
2024           if (info)
2025             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2026           break;
2027         }
2028       if (info)
2029         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2030       for ( ; image; image=image->next)
2031         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2032       break;
2033     }
2034     case 'T':
2035     case 't':
2036     {
2037       if (LocaleCompare(attribute,"texture") == 0)
2038         {
2039           if (info)
2040             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2041           break;
2042         }
2043       if (LocaleCompare(attribute,"thread-limit") == 0)
2044         {
2045           MagickSizeType
2046             limit;
2047
2048           limit=MagickResourceInfinity;
2049           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2050             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2051               100.0);
2052           (void) SetMagickResourceLimit(ThreadResource,limit);
2053           break;
2054         }
2055       if (LocaleCompare(attribute,"tile-offset") == 0)
2056         {
2057           char
2058             *geometry;
2059
2060           geometry=GetPageGeometry(SvPV(sval,na));
2061           if (info)
2062             (void) CloneString(&info->image_info->page,geometry);
2063           for ( ; image; image=image->next)
2064             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2065               exception);
2066           geometry=(char *) RelinquishMagickMemory(geometry);
2067           break;
2068         }
2069       if (LocaleCompare(attribute,"time-limit") == 0)
2070         {
2071           MagickSizeType
2072             limit;
2073
2074           limit=MagickResourceInfinity;
2075           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2076             limit=(MagickSizeType) SiPrefixToDoubleInterval(SvPV(sval,na),
2077               100.0);
2078           (void) SetMagickResourceLimit(TimeResource,limit);
2079           break;
2080         }
2081       if (LocaleCompare(attribute,"transparent-color") == 0)
2082         {
2083           (void) QueryColorCompliance(SvPV(sval,na),AllCompliance,&target_color,
2084             exception);
2085           if (info)
2086             info->image_info->transparent_color=target_color;
2087           for ( ; image; image=image->next)
2088             image->transparent_color=target_color;
2089           break;
2090         }
2091       if (LocaleCompare(attribute,"type") == 0)
2092         {
2093           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2094             SvPV(sval,na)) : SvIV(sval);
2095           if (sp < 0)
2096             {
2097               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2098                 SvPV(sval,na));
2099               break;
2100             }
2101           if (info)
2102             info->image_info->type=(ImageType) sp;
2103           for ( ; image; image=image->next)
2104             SetImageType(image,(ImageType) sp,exception);
2105           break;
2106         }
2107       if (info)
2108         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2109       for ( ; image; image=image->next)
2110         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2111       break;
2112     }
2113     case 'U':
2114     case 'u':
2115     {
2116       if (LocaleCompare(attribute,"units") == 0)
2117         {
2118           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2119             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2120           if (sp < 0)
2121             {
2122               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2123                 SvPV(sval,na));
2124               break;
2125             }
2126           if (info)
2127             info->image_info->units=(ResolutionType) sp;
2128           for ( ; image; image=image->next)
2129           {
2130             ResolutionType
2131               units;
2132
2133             units=(ResolutionType) sp;
2134             if (image->units != units)
2135               switch (image->units)
2136               {
2137                 case UndefinedResolution:
2138                 case PixelsPerInchResolution:
2139                 {
2140                   if (units == PixelsPerCentimeterResolution)
2141                     {
2142                       image->resolution.x*=2.54;
2143                       image->resolution.y*=2.54;
2144                     }
2145                   break;
2146                 }
2147                 case PixelsPerCentimeterResolution:
2148                 {
2149                   if (units == PixelsPerInchResolution)
2150                     {
2151                       image->resolution.x/=2.54;
2152                       image->resolution.y/=2.54;
2153                     }
2154                   break;
2155                 }
2156               }
2157             image->units=units;
2158           }
2159           break;
2160         }
2161       if (info)
2162         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2163       for ( ; image; image=image->next)
2164         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2165       break;
2166     }
2167     case 'V':
2168     case 'v':
2169     {
2170       if (LocaleCompare(attribute,"verbose") == 0)
2171         {
2172           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2173             SvPV(sval,na)) : SvIV(sval);
2174           if (sp < 0)
2175             {
2176               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2177                 SvPV(sval,na));
2178               break;
2179             }
2180           if (info)
2181             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2182           break;
2183         }
2184       if (LocaleCompare(attribute,"view") == 0)
2185         {
2186           if (info)
2187             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2188           break;
2189         }
2190       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2191         {
2192           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2193             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2194           if (sp < 0)
2195             {
2196               ThrowPerlException(exception,OptionError,
2197                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2198               break;
2199             }
2200           for ( ; image; image=image->next)
2201             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp,exception);
2202           break;
2203         }
2204       if (info)
2205         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2206       for ( ; image; image=image->next)
2207         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2208       break;
2209     }
2210     case 'W':
2211     case 'w':
2212     {
2213       if (LocaleCompare(attribute,"white-point") == 0)
2214         {
2215           for ( ; image; image=image->next)
2216           {
2217             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2218             image->chromaticity.white_point.x=geometry_info.rho;
2219             image->chromaticity.white_point.y=geometry_info.sigma;
2220             if ((flags & SigmaValue) == 0)
2221               image->chromaticity.white_point.y=
2222                 image->chromaticity.white_point.x;
2223           }
2224           break;
2225         }
2226       if (info)
2227         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2228       for ( ; image; image=image->next)
2229         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2230       break;
2231     }
2232     default:
2233     {
2234       if (info)
2235         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2236       for ( ; image; image=image->next)
2237         SetImageProperty(image,attribute,SvPV(sval,na),exception);
2238       break;
2239     }
2240   }
2241 }
2242 \f
2243 /*
2244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2245 %                                                                             %
2246 %                                                                             %
2247 %                                                                             %
2248 %   S e t u p L i s t                                                         %
2249 %                                                                             %
2250 %                                                                             %
2251 %                                                                             %
2252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2253 %
2254 %  Method SetupList returns the list of all the images linked by their
2255 %  image->next and image->previous link lists for use with ImageMagick.  If
2256 %  info is non-NULL, an info structure is returned in *info.  If
2257 %  reference_vector is non-NULL,an array of SV* are returned in
2258 %  *reference_vector.  Reference_vector is used when the images are going to be
2259 %  replaced with new Image*'s.
2260 %
2261 %  The format of the SetupList routine is:
2262 %
2263 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2264 %        SV ***reference_vector,ExceptionInfo *exception)
2265 %
2266 %  A description of each parameter follows:
2267 %
2268 %    o list: a list of strings.
2269 %
2270 %    o string: a character string.
2271 %
2272 %    o exception: Return any errors or warnings in this structure.
2273 %
2274 */
2275 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2276   SV ***reference_vector,ExceptionInfo *exception)
2277 {
2278   Image
2279     *image;
2280
2281   ssize_t
2282     current,
2283     last;
2284
2285   if (reference_vector)
2286     *reference_vector=NULL;
2287   if (info)
2288     *info=NULL;
2289   current=0;
2290   last=0;
2291   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2292   if (info && (SvTYPE(reference) == SVt_PVAV))
2293     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2294       exception);
2295   return(image);
2296 }
2297 \f
2298 /*
2299 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2300 %                                                                             %
2301 %                                                                             %
2302 %                                                                             %
2303 %   s t r E Q c a s e                                                         %
2304 %                                                                             %
2305 %                                                                             %
2306 %                                                                             %
2307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2308 %
2309 %  strEQcase() compares two strings and returns 0 if they are the
2310 %  same or if the second string runs out first.  The comparison is case
2311 %  insensitive.
2312 %
2313 %  The format of the strEQcase routine is:
2314 %
2315 %      ssize_t strEQcase(const char *p,const char *q)
2316 %
2317 %  A description of each parameter follows:
2318 %
2319 %    o p: a character string.
2320 %
2321 %    o q: a character string.
2322 %
2323 %
2324 */
2325 static ssize_t strEQcase(const char *p,const char *q)
2326 {
2327   char
2328     c;
2329
2330   register ssize_t
2331     i;
2332
2333   for (i=0 ; (c=(*q)) != 0; i++)
2334   {
2335     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2336         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2337       return(0);
2338     p++;
2339     q++;
2340   }
2341   return(((*q == 0) && (*p == 0)) ? i : 0);
2342 }
2343 \f
2344 /*
2345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2346 %                                                                             %
2347 %                                                                             %
2348 %                                                                             %
2349 %   I m a g e : : M a g i c k                                                 %
2350 %                                                                             %
2351 %                                                                             %
2352 %                                                                             %
2353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2354 %
2355 %
2356 */
2357 MODULE = Image::Magick PACKAGE = Image::Magick
2358
2359 PROTOTYPES: ENABLE
2360
2361 BOOT:
2362   MagickCoreGenesis("PerlMagick",MagickFalse);
2363   SetWarningHandler(NULL);
2364   SetErrorHandler(NULL);
2365   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2366     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2367
2368 void
2369 UNLOAD()
2370   PPCODE:
2371   {
2372     if (magick_registry != (SplayTreeInfo *) NULL)
2373       magick_registry=DestroySplayTree(magick_registry);
2374     MagickCoreTerminus();
2375   }
2376
2377 double
2378 constant(name,argument)
2379   char *name
2380   ssize_t argument
2381 \f
2382 #
2383 ###############################################################################
2384 #                                                                             #
2385 #                                                                             #
2386 #                                                                             #
2387 #   A n i m a t e                                                             #
2388 #                                                                             #
2389 #                                                                             #
2390 #                                                                             #
2391 ###############################################################################
2392 #
2393 #
2394 void
2395 Animate(ref,...)
2396   Image::Magick ref=NO_INIT
2397   ALIAS:
2398     AnimateImage  = 1
2399     animate       = 2
2400     animateimage  = 3
2401   PPCODE:
2402   {
2403     ExceptionInfo
2404       *exception;
2405
2406     Image
2407       *image;
2408
2409     register ssize_t
2410       i;
2411
2412     struct PackageInfo
2413       *info,
2414       *package_info;
2415
2416     SV
2417       *perl_exception,
2418       *reference;
2419
2420     PERL_UNUSED_VAR(ref);
2421     PERL_UNUSED_VAR(ix);
2422     exception=AcquireExceptionInfo();
2423     perl_exception=newSVpv("",0);
2424     package_info=(struct PackageInfo *) NULL;
2425     if (sv_isobject(ST(0)) == 0)
2426       {
2427         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2428           PackageName);
2429         goto PerlException;
2430       }
2431     reference=SvRV(ST(0));
2432     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2433     if (image == (Image *) NULL)
2434       {
2435         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2436           PackageName);
2437         goto PerlException;
2438       }
2439     package_info=ClonePackageInfo(info,exception);
2440     if (items == 2)
2441       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2442     else
2443       if (items > 2)
2444         for (i=2; i < items; i+=2)
2445           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2446             exception);
2447     (void) AnimateImages(package_info->image_info,image,exception);
2448     (void) CatchImageException(image);
2449
2450   PerlException:
2451     if (package_info != (struct PackageInfo *) NULL)
2452       DestroyPackageInfo(package_info);
2453     InheritPerlException(exception,perl_exception);
2454     exception=DestroyExceptionInfo(exception);
2455     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2456     SvPOK_on(perl_exception);
2457     ST(0)=sv_2mortal(perl_exception);
2458     XSRETURN(1);
2459   }
2460 \f
2461 #
2462 ###############################################################################
2463 #                                                                             #
2464 #                                                                             #
2465 #                                                                             #
2466 #   A p p e n d                                                               #
2467 #                                                                             #
2468 #                                                                             #
2469 #                                                                             #
2470 ###############################################################################
2471 #
2472 #
2473 void
2474 Append(ref,...)
2475   Image::Magick ref=NO_INIT
2476   ALIAS:
2477     AppendImage  = 1
2478     append       = 2
2479     appendimage  = 3
2480   PPCODE:
2481   {
2482     AV
2483       *av;
2484
2485     char
2486       *attribute;
2487
2488     ExceptionInfo
2489       *exception;
2490
2491     HV
2492       *hv;
2493
2494     Image
2495       *image;
2496
2497     register ssize_t
2498       i;
2499
2500     ssize_t
2501       stack;
2502
2503     struct PackageInfo
2504       *info;
2505
2506     SV
2507       *av_reference,
2508       *perl_exception,
2509       *reference,
2510       *rv,
2511       *sv;
2512
2513     PERL_UNUSED_VAR(ref);
2514     PERL_UNUSED_VAR(ix);
2515     exception=AcquireExceptionInfo();
2516     perl_exception=newSVpv("",0);
2517     sv=NULL;
2518     attribute=NULL;
2519     av=NULL;
2520     if (sv_isobject(ST(0)) == 0)
2521       {
2522         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2523           PackageName);
2524         goto PerlException;
2525       }
2526     reference=SvRV(ST(0));
2527     hv=SvSTASH(reference);
2528     av=newAV();
2529     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2530     SvREFCNT_dec(av);
2531     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2532     if (image == (Image *) NULL)
2533       {
2534         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2535           PackageName);
2536         goto PerlException;
2537       }
2538     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2539     /*
2540       Get options.
2541     */
2542     stack=MagickTrue;
2543     for (i=2; i < items; i+=2)
2544     {
2545       attribute=(char *) SvPV(ST(i-1),na);
2546       switch (*attribute)
2547       {
2548         case 'S':
2549         case 's':
2550         {
2551           if (LocaleCompare(attribute,"stack") == 0)
2552             {
2553               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2554                 SvPV(ST(i),na));
2555               if (stack < 0)
2556                 {
2557                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2558                     SvPV(ST(i),na));
2559                   return;
2560                 }
2561               break;
2562             }
2563           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2564             attribute);
2565           break;
2566         }
2567         default:
2568         {
2569           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2570             attribute);
2571           break;
2572         }
2573       }
2574     }
2575     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2576     if (image == (Image *) NULL)
2577       goto PerlException;
2578     for ( ; image; image=image->next)
2579     {
2580       AddImageToRegistry(sv,image);
2581       rv=newRV(sv);
2582       av_push(av,sv_bless(rv,hv));
2583       SvREFCNT_dec(sv);
2584     }
2585     exception=DestroyExceptionInfo(exception);
2586     ST(0)=av_reference;
2587     SvREFCNT_dec(perl_exception);
2588     XSRETURN(1);
2589
2590   PerlException:
2591     InheritPerlException(exception,perl_exception);
2592     exception=DestroyExceptionInfo(exception);
2593     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2594     SvPOK_on(perl_exception);
2595     ST(0)=sv_2mortal(perl_exception);
2596     XSRETURN(1);
2597   }
2598 \f
2599 #
2600 ###############################################################################
2601 #                                                                             #
2602 #                                                                             #
2603 #                                                                             #
2604 #   A v e r a g e                                                             #
2605 #                                                                             #
2606 #                                                                             #
2607 #                                                                             #
2608 ###############################################################################
2609 #
2610 #
2611 void
2612 Average(ref)
2613   Image::Magick ref=NO_INIT
2614   ALIAS:
2615     AverageImage   = 1
2616     average        = 2
2617     averageimage   = 3
2618   PPCODE:
2619   {
2620     AV
2621       *av;
2622
2623     char
2624       *p;
2625
2626     ExceptionInfo
2627       *exception;
2628
2629     HV
2630       *hv;
2631
2632     Image
2633       *image;
2634
2635     struct PackageInfo
2636       *info;
2637
2638     SV
2639       *perl_exception,
2640       *reference,
2641       *rv,
2642       *sv;
2643
2644     PERL_UNUSED_VAR(ref);
2645     PERL_UNUSED_VAR(ix);
2646     exception=AcquireExceptionInfo();
2647     perl_exception=newSVpv("",0);
2648     sv=NULL;
2649     if (sv_isobject(ST(0)) == 0)
2650       {
2651         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2652           PackageName);
2653         goto PerlException;
2654       }
2655     reference=SvRV(ST(0));
2656     hv=SvSTASH(reference);
2657     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2658     if (image == (Image *) NULL)
2659       {
2660         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2661           PackageName);
2662         goto PerlException;
2663       }
2664     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2665     if (image == (Image *) NULL)
2666       goto PerlException;
2667     /*
2668       Create blessed Perl array for the returned image.
2669     */
2670     av=newAV();
2671     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2672     SvREFCNT_dec(av);
2673     AddImageToRegistry(sv,image);
2674     rv=newRV(sv);
2675     av_push(av,sv_bless(rv,hv));
2676     SvREFCNT_dec(sv);
2677     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2678     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
2679       "average-%.*s",(int) (MagickPathExtent-9),
2680       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2681     (void) CopyMagickString(image->filename,info->image_info->filename,
2682       MagickPathExtent);
2683     SetImageInfo(info->image_info,0,exception);
2684     exception=DestroyExceptionInfo(exception);
2685     SvREFCNT_dec(perl_exception);
2686     XSRETURN(1);
2687
2688   PerlException:
2689     InheritPerlException(exception,perl_exception);
2690     exception=DestroyExceptionInfo(exception);
2691     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2692     SvPOK_on(perl_exception);
2693     ST(0)=sv_2mortal(perl_exception);
2694     XSRETURN(1);
2695   }
2696 \f
2697 #
2698 ###############################################################################
2699 #                                                                             #
2700 #                                                                             #
2701 #                                                                             #
2702 #   B l o b T o I m a g e                                                     #
2703 #                                                                             #
2704 #                                                                             #
2705 #                                                                             #
2706 ###############################################################################
2707 #
2708 #
2709 void
2710 BlobToImage(ref,...)
2711   Image::Magick ref=NO_INIT
2712   ALIAS:
2713     BlobToImage  = 1
2714     blobtoimage  = 2
2715     blobto       = 3
2716   PPCODE:
2717   {
2718     AV
2719       *av;
2720
2721     char
2722       **keep,
2723       **list;
2724
2725     ExceptionInfo
2726       *exception;
2727
2728     HV
2729       *hv;
2730
2731     Image
2732       *image;
2733
2734     register char
2735       **p;
2736
2737     register ssize_t
2738       i;
2739
2740     ssize_t
2741       ac,
2742       n,
2743       number_images;
2744
2745     STRLEN
2746       *length;
2747
2748     struct PackageInfo
2749       *info;
2750
2751     SV
2752       *perl_exception,
2753       *reference,
2754       *rv,
2755       *sv;
2756
2757     PERL_UNUSED_VAR(ref);
2758     PERL_UNUSED_VAR(ix);
2759     exception=AcquireExceptionInfo();
2760     perl_exception=newSVpv("",0);
2761     sv=NULL;
2762     number_images=0;
2763     ac=(items < 2) ? 1 : items-1;
2764     length=(STRLEN *) NULL;
2765     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2766     if (list == (char **) NULL)
2767       {
2768         ThrowPerlException(exception,ResourceLimitError,
2769           "MemoryAllocationFailed",PackageName);
2770         goto PerlException;
2771       }
2772     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2773     if (length == (STRLEN *) NULL)
2774       {
2775         ThrowPerlException(exception,ResourceLimitError,
2776           "MemoryAllocationFailed",PackageName);
2777         goto PerlException;
2778       }
2779     if (sv_isobject(ST(0)) == 0)
2780       {
2781         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2782           PackageName);
2783         goto PerlException;
2784       }
2785     reference=SvRV(ST(0));
2786     hv=SvSTASH(reference);
2787     if (SvTYPE(reference) != SVt_PVAV)
2788       {
2789         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2790           PackageName);
2791         goto PerlException;
2792       }
2793     av=(AV *) reference;
2794     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2795       exception);
2796     n=1;
2797     if (items <= 1)
2798       {
2799         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2800         goto PerlException;
2801       }
2802     for (n=0, i=0; i < ac; i++)
2803     {
2804       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2805       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2806         {
2807           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2808           continue;
2809         }
2810       n++;
2811     }
2812     list[n]=(char *) NULL;
2813     keep=list;
2814     for (i=number_images=0; i < n; i++)
2815     {
2816       image=BlobToImage(info->image_info,list[i],length[i],exception);
2817       if (image == (Image *) NULL)
2818         break;
2819       for ( ; image; image=image->next)
2820       {
2821         AddImageToRegistry(sv,image);
2822         rv=newRV(sv);
2823         av_push(av,sv_bless(rv,hv));
2824         SvREFCNT_dec(sv);
2825         number_images++;
2826       }
2827     }
2828     /*
2829       Free resources.
2830     */
2831     for (i=0; i < n; i++)
2832       if (list[i] != (char *) NULL)
2833         for (p=keep; list[i] != *p++; )
2834           if (*p == (char *) NULL)
2835             {
2836               list[i]=(char *) RelinquishMagickMemory(list[i]);
2837               break;
2838             }
2839
2840   PerlException:
2841     if (list)
2842       list=(char **) RelinquishMagickMemory(list);
2843     if (length)
2844       length=(STRLEN *) RelinquishMagickMemory(length);
2845     InheritPerlException(exception,perl_exception);
2846     exception=DestroyExceptionInfo(exception);
2847     sv_setiv(perl_exception,(IV) number_images);
2848     SvPOK_on(perl_exception);
2849     ST(0)=sv_2mortal(perl_exception);
2850     XSRETURN(1);
2851   }
2852 \f
2853 #
2854 ###############################################################################
2855 #                                                                             #
2856 #                                                                             #
2857 #                                                                             #
2858 #   C h a n n e l F x                                                         #
2859 #                                                                             #
2860 #                                                                             #
2861 #                                                                             #
2862 ###############################################################################
2863 #
2864 #
2865 void
2866 ChannelFx(ref,...)
2867   Image::Magick ref=NO_INIT
2868   ALIAS:
2869     ChannelFxImage  = 1
2870     channelfx       = 2
2871     channelfximage  = 3
2872   PPCODE:
2873   {
2874     AV
2875       *av;
2876
2877     char
2878       *attribute,
2879       expression[MagickPathExtent];
2880
2881     ChannelType
2882       channel,
2883       channel_mask;
2884
2885     ExceptionInfo
2886       *exception;
2887
2888     HV
2889       *hv;
2890
2891     Image
2892       *image;
2893
2894     register ssize_t
2895       i;
2896
2897     struct PackageInfo
2898       *info;
2899
2900     SV
2901       *av_reference,
2902       *perl_exception,
2903       *reference,
2904       *rv,
2905       *sv;
2906
2907     PERL_UNUSED_VAR(ref);
2908     PERL_UNUSED_VAR(ix);
2909     exception=AcquireExceptionInfo();
2910     perl_exception=newSVpv("",0);
2911     sv=NULL;
2912     attribute=NULL;
2913     av=NULL;
2914     if (sv_isobject(ST(0)) == 0)
2915       {
2916         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2917           PackageName);
2918         goto PerlException;
2919       }
2920     reference=SvRV(ST(0));
2921     hv=SvSTASH(reference);
2922     av=newAV();
2923     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2924     SvREFCNT_dec(av);
2925     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2926     if (image == (Image *) NULL)
2927       {
2928         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2929           PackageName);
2930         goto PerlException;
2931       }
2932     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2933     /*
2934       Get options.
2935     */
2936     channel=DefaultChannels;
2937     (void) CopyMagickString(expression,"u",MagickPathExtent);
2938     if (items == 2)
2939       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
2940     else
2941       for (i=2; i < items; i+=2)
2942       {
2943         attribute=(char *) SvPV(ST(i-1),na);
2944         switch (*attribute)
2945         {
2946           case 'C':
2947           case 'c':
2948           {
2949             if (LocaleCompare(attribute,"channel") == 0)
2950               {
2951                 ssize_t
2952                   option;
2953
2954                 option=ParseChannelOption(SvPV(ST(i),na));
2955                 if (option < 0)
2956                   {
2957                     ThrowPerlException(exception,OptionError,
2958                       "UnrecognizedType",SvPV(ST(i),na));
2959                     return;
2960                   }
2961                 channel=(ChannelType) option;
2962                 break;
2963               }
2964             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2965               attribute);
2966             break;
2967           }
2968           case 'E':
2969           case 'e':
2970           {
2971             if (LocaleCompare(attribute,"expression") == 0)
2972               {
2973                 (void) CopyMagickString(expression,SvPV(ST(i),na),
2974                   MagickPathExtent);
2975                 break;
2976               }
2977             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2978               attribute);
2979             break;
2980           }
2981           default:
2982           {
2983             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2984               attribute);
2985             break;
2986           }
2987         }
2988       }
2989     channel_mask=SetImageChannelMask(image,channel);
2990     image=ChannelFxImage(image,expression,exception);
2991     if (image != (Image *) NULL)
2992       (void) SetImageChannelMask(image,channel_mask);
2993     if (image == (Image *) NULL)
2994       goto PerlException;
2995     for ( ; image; image=image->next)
2996     {
2997       AddImageToRegistry(sv,image);
2998       rv=newRV(sv);
2999       av_push(av,sv_bless(rv,hv));
3000       SvREFCNT_dec(sv);
3001     }
3002     exception=DestroyExceptionInfo(exception);
3003     ST(0)=av_reference;
3004     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3005     XSRETURN(1);
3006
3007   PerlException:
3008     InheritPerlException(exception,perl_exception);
3009     exception=DestroyExceptionInfo(exception);
3010     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3011     SvPOK_on(perl_exception);
3012     ST(0)=sv_2mortal(perl_exception);
3013     XSRETURN(1);
3014   }
3015 \f
3016 #
3017 ###############################################################################
3018 #                                                                             #
3019 #                                                                             #
3020 #                                                                             #
3021 #   C l o n e                                                                 #
3022 #                                                                             #
3023 #                                                                             #
3024 #                                                                             #
3025 ###############################################################################
3026 #
3027 #
3028 void
3029 Clone(ref)
3030   Image::Magick ref=NO_INIT
3031   ALIAS:
3032     CopyImage   = 1
3033     copy        = 2
3034     copyimage   = 3
3035     CloneImage  = 4
3036     clone       = 5
3037     cloneimage  = 6
3038     Clone       = 7
3039   PPCODE:
3040   {
3041     AV
3042       *av;
3043
3044     ExceptionInfo
3045       *exception;
3046
3047     HV
3048       *hv;
3049
3050     Image
3051       *clone,
3052       *image;
3053
3054     struct PackageInfo
3055       *info;
3056
3057     SV
3058       *perl_exception,
3059       *reference,
3060       *rv,
3061       *sv;
3062
3063     PERL_UNUSED_VAR(ref);
3064     PERL_UNUSED_VAR(ix);
3065     exception=AcquireExceptionInfo();
3066     perl_exception=newSVpv("",0);
3067     sv=NULL;
3068     if (sv_isobject(ST(0)) == 0)
3069       {
3070         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3071           PackageName);
3072         goto PerlException;
3073       }
3074     reference=SvRV(ST(0));
3075     hv=SvSTASH(reference);
3076     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3077     if (image == (Image *) NULL)
3078       {
3079         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3080           PackageName);
3081         goto PerlException;
3082       }
3083     /*
3084       Create blessed Perl array for the returned image.
3085     */
3086     av=newAV();
3087     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3088     SvREFCNT_dec(av);
3089     for ( ; image; image=image->next)
3090     {
3091       clone=CloneImage(image,0,0,MagickTrue,exception);
3092       if (clone == (Image *) NULL)
3093         break;
3094       AddImageToRegistry(sv,clone);
3095       rv=newRV(sv);
3096       av_push(av,sv_bless(rv,hv));
3097       SvREFCNT_dec(sv);
3098     }
3099     exception=DestroyExceptionInfo(exception);
3100     SvREFCNT_dec(perl_exception);
3101     XSRETURN(1);
3102
3103   PerlException:
3104     InheritPerlException(exception,perl_exception);
3105     exception=DestroyExceptionInfo(exception);
3106     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3107     SvPOK_on(perl_exception);
3108     ST(0)=sv_2mortal(perl_exception);
3109     XSRETURN(1);
3110   }
3111 \f
3112 #
3113 ###############################################################################
3114 #                                                                             #
3115 #                                                                             #
3116 #                                                                             #
3117 #   C L O N E                                                                 #
3118 #                                                                             #
3119 #                                                                             #
3120 #                                                                             #
3121 ###############################################################################
3122 #
3123 #
3124 void
3125 CLONE(ref,...)
3126   SV *ref;
3127   CODE:
3128   {
3129     PERL_UNUSED_VAR(ref);
3130     if (magick_registry != (SplayTreeInfo *) NULL)
3131       {
3132         register Image
3133           *p;
3134
3135         ResetSplayTreeIterator(magick_registry);
3136         p=(Image *) GetNextKeyInSplayTree(magick_registry);
3137         while (p != (Image *) NULL)
3138         {
3139           ReferenceImage(p);
3140           p=(Image *) GetNextKeyInSplayTree(magick_registry);
3141         }
3142       }
3143   }
3144 \f
3145 #
3146 ###############################################################################
3147 #                                                                             #
3148 #                                                                             #
3149 #                                                                             #
3150 #   C o a l e s c e                                                           #
3151 #                                                                             #
3152 #                                                                             #
3153 #                                                                             #
3154 ###############################################################################
3155 #
3156 #
3157 void
3158 Coalesce(ref)
3159   Image::Magick ref=NO_INIT
3160   ALIAS:
3161     CoalesceImage   = 1
3162     coalesce        = 2
3163     coalesceimage   = 3
3164   PPCODE:
3165   {
3166     AV
3167       *av;
3168
3169     ExceptionInfo
3170       *exception;
3171
3172     HV
3173       *hv;
3174
3175     Image
3176       *image;
3177
3178     struct PackageInfo
3179       *info;
3180
3181     SV
3182       *av_reference,
3183       *perl_exception,
3184       *reference,
3185       *rv,
3186       *sv;
3187
3188     PERL_UNUSED_VAR(ref);
3189     PERL_UNUSED_VAR(ix);
3190     exception=AcquireExceptionInfo();
3191     perl_exception=newSVpv("",0);
3192     sv=NULL;
3193     if (sv_isobject(ST(0)) == 0)
3194       {
3195         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3196           PackageName);
3197         goto PerlException;
3198       }
3199     reference=SvRV(ST(0));
3200     hv=SvSTASH(reference);
3201     av=newAV();
3202     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3203     SvREFCNT_dec(av);
3204     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3205     if (image == (Image *) NULL)
3206       {
3207         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3208           PackageName);
3209         goto PerlException;
3210       }
3211     image=CoalesceImages(image,exception);
3212     if (image == (Image *) NULL)
3213       goto PerlException;
3214     for ( ; image; image=image->next)
3215     {
3216       AddImageToRegistry(sv,image);
3217       rv=newRV(sv);
3218       av_push(av,sv_bless(rv,hv));
3219       SvREFCNT_dec(sv);
3220     }
3221     exception=DestroyExceptionInfo(exception);
3222     ST(0)=av_reference;
3223     SvREFCNT_dec(perl_exception);
3224     XSRETURN(1);
3225
3226   PerlException:
3227     InheritPerlException(exception,perl_exception);
3228     exception=DestroyExceptionInfo(exception);
3229     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3230     SvPOK_on(perl_exception);
3231     ST(0)=sv_2mortal(perl_exception);
3232     XSRETURN(1);
3233   }
3234 \f
3235 #
3236 ###############################################################################
3237 #                                                                             #
3238 #                                                                             #
3239 #                                                                             #
3240 #   C o m p a r e                                                             #
3241 #                                                                             #
3242 #                                                                             #
3243 #                                                                             #
3244 ###############################################################################
3245 #
3246 #
3247 void
3248 Compare(ref,...)
3249   Image::Magick ref=NO_INIT
3250   ALIAS:
3251     CompareImages = 1
3252     compare      = 2
3253     compareimage = 3
3254   PPCODE:
3255   {
3256     AV
3257       *av;
3258
3259     char
3260       *attribute;
3261
3262     double
3263       distortion;
3264
3265     ExceptionInfo
3266       *exception;
3267
3268     HV
3269       *hv;
3270
3271     Image
3272       *difference_image,
3273       *image,
3274       *reconstruct_image;
3275
3276     MetricType
3277       metric;
3278
3279     register ssize_t
3280       i;
3281
3282     ssize_t
3283       option;
3284
3285     struct PackageInfo
3286       *info;
3287
3288     SV
3289       *av_reference,
3290       *perl_exception,
3291       *reference,
3292       *rv,
3293       *sv;
3294
3295     PERL_UNUSED_VAR(ref);
3296     PERL_UNUSED_VAR(ix);
3297     exception=AcquireExceptionInfo();
3298     perl_exception=newSVpv("",0);
3299     sv=NULL;
3300     av=NULL;
3301     attribute=NULL;
3302     if (sv_isobject(ST(0)) == 0)
3303       {
3304         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3305           PackageName);
3306         goto PerlException;
3307       }
3308     reference=SvRV(ST(0));
3309     hv=SvSTASH(reference);
3310     av=newAV();
3311     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3312     SvREFCNT_dec(av);
3313     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3314     if (image == (Image *) NULL)
3315       {
3316         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3317           PackageName);
3318         goto PerlException;
3319       }
3320     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3321     /*
3322       Get attribute.
3323     */
3324     reconstruct_image=image;
3325     metric=RootMeanSquaredErrorMetric;
3326     for (i=2; i < items; i+=2)
3327     {
3328       attribute=(char *) SvPV(ST(i-1),na);
3329       switch (*attribute)
3330       {
3331         case 'C':
3332         case 'c':
3333         {
3334           if (LocaleCompare(attribute,"channel") == 0)
3335             {
3336               ssize_t
3337                 option;
3338
3339               option=ParseChannelOption(SvPV(ST(i),na));
3340               if (option < 0)
3341                 {
3342                   ThrowPerlException(exception,OptionError,
3343                     "UnrecognizedType",SvPV(ST(i),na));
3344                   return;
3345                 }
3346               (void) SetPixelChannelMask(image,(ChannelType) option);
3347               break;
3348             }
3349           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3350             attribute);
3351           break;
3352         }
3353         case 'F':
3354         case 'f':
3355         {
3356           if (LocaleCompare(attribute,"fuzz") == 0)
3357             {
3358               image->fuzz=StringToDoubleInterval(SvPV(ST(i),na),100.0);
3359               break;
3360             }
3361           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3362             attribute);
3363           break;
3364         }
3365         case 'I':
3366         case 'i':
3367         {
3368           if (LocaleCompare(attribute,"image") == 0)
3369             {
3370               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3371                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3372               break;
3373             }
3374           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3375             attribute);
3376           break;
3377         }
3378         case 'M':
3379         case 'm':
3380         {
3381           if (LocaleCompare(attribute,"metric") == 0)
3382             {
3383               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3384                 SvPV(ST(i),na));
3385               if (option < 0)
3386                 {
3387                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3388                     SvPV(ST(i),na));
3389                   break;
3390                 }
3391               metric=(MetricType) option;
3392               break;
3393             }
3394           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3395             attribute);
3396           break;
3397         }
3398         default:
3399         {
3400           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3401             attribute);
3402           break;
3403         }
3404       }
3405     }
3406     difference_image=CompareImages(image,reconstruct_image,metric,&distortion,
3407       exception);
3408     if (difference_image != (Image *) NULL)
3409       {
3410         difference_image->error.mean_error_per_pixel=distortion;
3411         AddImageToRegistry(sv,difference_image);
3412         rv=newRV(sv);
3413         av_push(av,sv_bless(rv,hv));
3414         SvREFCNT_dec(sv);
3415       }
3416     exception=DestroyExceptionInfo(exception);
3417     ST(0)=av_reference;
3418     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3419     XSRETURN(1);
3420
3421   PerlException:
3422     InheritPerlException(exception,perl_exception);
3423     exception=DestroyExceptionInfo(exception);
3424     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3425     SvPOK_on(perl_exception);
3426     ST(0)=sv_2mortal(perl_exception);
3427     XSRETURN(1);
3428   }
3429 \f
3430 #
3431 ###############################################################################
3432 #                                                                             #
3433 #                                                                             #
3434 #                                                                             #
3435 #   C o m p l e x I m a g e s                                                 #
3436 #                                                                             #
3437 #                                                                             #
3438 #                                                                             #
3439 ###############################################################################
3440 #
3441 #
3442 void
3443 ComplexImages(ref)
3444   Image::Magick ref=NO_INIT
3445   ALIAS:
3446     ComplexImages   = 1
3447     compleximages   = 2
3448   PPCODE:
3449   {
3450     AV
3451       *av;
3452
3453     char
3454       *attribute,
3455       *p;
3456
3457     ComplexOperator
3458       op;
3459
3460     ExceptionInfo
3461       *exception;
3462
3463     HV
3464       *hv;
3465
3466     Image
3467       *image;
3468
3469     register ssize_t
3470       i;
3471
3472     struct PackageInfo
3473       *info;
3474
3475     SV
3476       *perl_exception,
3477       *reference,
3478       *rv,
3479       *sv;
3480
3481     PERL_UNUSED_VAR(ref);
3482     PERL_UNUSED_VAR(ix);
3483     exception=AcquireExceptionInfo();
3484     perl_exception=newSVpv("",0);
3485     sv=NULL;
3486     if (sv_isobject(ST(0)) == 0)
3487       {
3488         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3489           PackageName);
3490         goto PerlException;
3491       }
3492     reference=SvRV(ST(0));
3493     hv=SvSTASH(reference);
3494     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3495     if (image == (Image *) NULL)
3496       {
3497         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3498           PackageName);
3499         goto PerlException;
3500       }
3501     op=UndefinedComplexOperator;
3502     if (items == 2)
3503       {
3504         ssize_t
3505           in;
3506
3507         in=ParseCommandOption(MagickComplexOptions,MagickFalse,(char *)
3508           SvPV(ST(1),na));
3509         if (in < 0)
3510           {
3511             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3512               SvPV(ST(1),na));
3513             return;
3514           }
3515         op=(ComplexOperator) in;
3516       }
3517     else
3518       for (i=2; i < items; i+=2)
3519       {
3520         attribute=(char *) SvPV(ST(i-1),na);
3521         switch (*attribute)
3522         {
3523           case 'O':
3524           case 'o':
3525           {
3526             if (LocaleCompare(attribute,"operator") == 0)
3527               {
3528                 ssize_t
3529                   in;
3530
3531                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3532                   MagickComplexOptions,MagickFalse,SvPV(ST(i),na));
3533                 if (in < 0)
3534                   {
3535                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3536                       SvPV(ST(i),na));
3537                     return;
3538                   }
3539                 op=(ComplexOperator) in;
3540                 break;
3541               }
3542             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3543               attribute);
3544             break;
3545           }
3546           default:
3547           {
3548             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3549               attribute);
3550             break;
3551           }
3552         }
3553       }
3554     image=ComplexImages(image,op,exception);
3555     if (image == (Image *) NULL)
3556       goto PerlException;
3557     /*
3558       Create blessed Perl array for the returned image.
3559     */
3560     av=newAV();
3561     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3562     SvREFCNT_dec(av);
3563     AddImageToRegistry(sv,image);
3564     rv=newRV(sv);
3565     av_push(av,sv_bless(rv,hv));
3566     SvREFCNT_dec(sv);
3567     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3568     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
3569       "complex-%.*s",(int) (MagickPathExtent-9),
3570       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3571     (void) CopyMagickString(image->filename,info->image_info->filename,
3572       MagickPathExtent);
3573     SetImageInfo(info->image_info,0,exception);
3574     exception=DestroyExceptionInfo(exception);
3575     SvREFCNT_dec(perl_exception);
3576     XSRETURN(1);
3577
3578   PerlException:
3579     InheritPerlException(exception,perl_exception);
3580     exception=DestroyExceptionInfo(exception);
3581     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3582     SvPOK_on(perl_exception);
3583     ST(0)=sv_2mortal(perl_exception);
3584     XSRETURN(1);
3585   }
3586 \f
3587 #
3588 ###############################################################################
3589 #                                                                             #
3590 #                                                                             #
3591 #                                                                             #
3592 #   C o m p a r e L a y e r s                                                 #
3593 #                                                                             #
3594 #                                                                             #
3595 #                                                                             #
3596 ###############################################################################
3597 #
3598 #
3599 void
3600 CompareLayers(ref)
3601   Image::Magick ref=NO_INIT
3602   ALIAS:
3603     CompareImagesLayers   = 1
3604     comparelayers        = 2
3605     compareimagelayers   = 3
3606   PPCODE:
3607   {
3608     AV
3609       *av;
3610
3611     char
3612       *attribute;
3613
3614     ExceptionInfo
3615       *exception;
3616
3617     HV
3618       *hv;
3619
3620     Image
3621       *image;
3622
3623     LayerMethod
3624       method;
3625
3626     register ssize_t
3627       i;
3628
3629     ssize_t
3630       option;
3631
3632     struct PackageInfo
3633       *info;
3634
3635     SV
3636       *av_reference,
3637       *perl_exception,
3638       *reference,
3639       *rv,
3640       *sv;
3641
3642     PERL_UNUSED_VAR(ref);
3643     PERL_UNUSED_VAR(ix);
3644     exception=AcquireExceptionInfo();
3645     perl_exception=newSVpv("",0);
3646     sv=NULL;
3647     if (sv_isobject(ST(0)) == 0)
3648       {
3649         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3650           PackageName);
3651         goto PerlException;
3652       }
3653     reference=SvRV(ST(0));
3654     hv=SvSTASH(reference);
3655     av=newAV();
3656     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3657     SvREFCNT_dec(av);
3658     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3659     if (image == (Image *) NULL)
3660       {
3661         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3662           PackageName);
3663         goto PerlException;
3664       }
3665     method=CompareAnyLayer;
3666     for (i=2; i < items; i+=2)
3667     {
3668       attribute=(char *) SvPV(ST(i-1),na);
3669       switch (*attribute)
3670       {
3671         case 'M':
3672         case 'm':
3673         {
3674           if (LocaleCompare(attribute,"method") == 0)
3675             {
3676               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3677                 SvPV(ST(i),na));
3678               if (option < 0)
3679                 {
3680                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3681                     SvPV(ST(i),na));
3682                   break;
3683                 }
3684                method=(LayerMethod) option;
3685               break;
3686             }
3687           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3688             attribute);
3689           break;
3690         }
3691         default:
3692         {
3693           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3694             attribute);
3695           break;
3696         }
3697       }
3698     }
3699     image=CompareImagesLayers(image,method,exception);
3700     if (image == (Image *) NULL)
3701       goto PerlException;
3702     for ( ; image; image=image->next)
3703     {
3704       AddImageToRegistry(sv,image);
3705       rv=newRV(sv);
3706       av_push(av,sv_bless(rv,hv));
3707       SvREFCNT_dec(sv);
3708     }
3709     exception=DestroyExceptionInfo(exception);
3710     ST(0)=av_reference;
3711     SvREFCNT_dec(perl_exception);
3712     XSRETURN(1);
3713
3714   PerlException:
3715     InheritPerlException(exception,perl_exception);
3716     exception=DestroyExceptionInfo(exception);
3717     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3718     SvPOK_on(perl_exception);
3719     ST(0)=sv_2mortal(perl_exception);
3720     XSRETURN(1);
3721   }
3722 \f
3723 #
3724 ###############################################################################
3725 #                                                                             #
3726 #                                                                             #
3727 #                                                                             #
3728 #   D e s t r o y                                                             #
3729 #                                                                             #
3730 #                                                                             #
3731 #                                                                             #
3732 ###############################################################################
3733 #
3734 #
3735 void
3736 DESTROY(ref)
3737   Image::Magick ref=NO_INIT
3738   PPCODE:
3739   {
3740     SV
3741       *reference;
3742
3743     PERL_UNUSED_VAR(ref);
3744     if (sv_isobject(ST(0)) == 0)
3745       croak("ReferenceIsNotMyType");
3746     reference=SvRV(ST(0));
3747     switch (SvTYPE(reference))
3748     {
3749       case SVt_PVAV:
3750       {
3751         char
3752           message[MagickPathExtent];
3753
3754         const SV
3755           *key;
3756
3757         HV
3758           *hv;
3759
3760         GV
3761           **gvp;
3762
3763         struct PackageInfo
3764           *info;
3765
3766         SV
3767           *sv;
3768
3769         /*
3770           Array (AV *) reference
3771         */
3772         (void) FormatLocaleString(message,MagickPathExtent,"package%s%p",
3773           XS_VERSION,reference);
3774         hv=gv_stashpv(PackageName, FALSE);
3775         if (!hv)
3776           break;
3777         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3778         if (!gvp)
3779           break;
3780         sv=GvSV(*gvp);
3781         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3782           {
3783             info=INT2PTR(struct PackageInfo *,SvIV(sv));
3784             DestroyPackageInfo(info);
3785           }
3786         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3787         (void) key;
3788         break;
3789       }
3790       case SVt_PVMG:
3791       {
3792         Image
3793           *image;
3794
3795         /*
3796           Blessed scalar = (Image *) SvIV(reference)
3797         */
3798         image=INT2PTR(Image *,SvIV(reference));
3799         if (image != (Image *) NULL)
3800           DeleteImageFromRegistry(reference,image);
3801         break;
3802       }
3803       default:
3804         break;
3805     }
3806   }
3807 \f
3808 #
3809 ###############################################################################
3810 #                                                                             #
3811 #                                                                             #
3812 #                                                                             #
3813 #   D i s p l a y                                                             #
3814 #                                                                             #
3815 #                                                                             #
3816 #                                                                             #
3817 ###############################################################################
3818 #
3819 #
3820 void
3821 Display(ref,...)
3822   Image::Magick ref=NO_INIT
3823   ALIAS:
3824     DisplayImage  = 1
3825     display       = 2
3826     displayimage  = 3
3827   PPCODE:
3828   {
3829     ExceptionInfo
3830       *exception;
3831
3832     Image
3833       *image;
3834
3835     register ssize_t
3836       i;
3837
3838     struct PackageInfo
3839       *info,
3840       *package_info;
3841
3842     SV
3843       *perl_exception,
3844       *reference;
3845
3846     PERL_UNUSED_VAR(ref);
3847     PERL_UNUSED_VAR(ix);
3848     exception=AcquireExceptionInfo();
3849     perl_exception=newSVpv("",0);
3850     package_info=(struct PackageInfo *) NULL;
3851     if (sv_isobject(ST(0)) == 0)
3852       {
3853         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3854           PackageName);
3855         goto PerlException;
3856       }
3857     reference=SvRV(ST(0));
3858     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3859     if (image == (Image *) NULL)
3860       {
3861         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3862           PackageName);
3863         goto PerlException;
3864       }
3865     package_info=ClonePackageInfo(info,exception);
3866     if (items == 2)
3867       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3868     else
3869       if (items > 2)
3870         for (i=2; i < items; i+=2)
3871           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3872             exception);
3873     (void) DisplayImages(package_info->image_info,image,exception);
3874     (void) CatchImageException(image);
3875
3876   PerlException:
3877     if (package_info != (struct PackageInfo *) NULL)
3878       DestroyPackageInfo(package_info);
3879     InheritPerlException(exception,perl_exception);
3880     exception=DestroyExceptionInfo(exception);
3881     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3882     SvPOK_on(perl_exception);
3883     ST(0)=sv_2mortal(perl_exception);
3884     XSRETURN(1);
3885   }
3886 \f
3887 #
3888 ###############################################################################
3889 #                                                                             #
3890 #                                                                             #
3891 #                                                                             #
3892 #   E v a l u a t e I m a g e s                                               #
3893 #                                                                             #
3894 #                                                                             #
3895 #                                                                             #
3896 ###############################################################################
3897 #
3898 #
3899 void
3900 EvaluateImages(ref)
3901   Image::Magick ref=NO_INIT
3902   ALIAS:
3903     EvaluateImages   = 1
3904     evaluateimages   = 2
3905   PPCODE:
3906   {
3907     AV
3908       *av;
3909
3910     char
3911       *attribute,
3912       *p;
3913
3914     ExceptionInfo
3915       *exception;
3916
3917     HV
3918       *hv;
3919
3920     Image
3921       *image;
3922
3923     MagickEvaluateOperator
3924       op;
3925
3926     register ssize_t
3927       i;
3928
3929     struct PackageInfo
3930       *info;
3931
3932     SV
3933       *perl_exception,
3934       *reference,
3935       *rv,
3936       *sv;
3937
3938     PERL_UNUSED_VAR(ref);
3939     PERL_UNUSED_VAR(ix);
3940     exception=AcquireExceptionInfo();
3941     perl_exception=newSVpv("",0);
3942     sv=NULL;
3943     if (sv_isobject(ST(0)) == 0)
3944       {
3945         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3946           PackageName);
3947         goto PerlException;
3948       }
3949     reference=SvRV(ST(0));
3950     hv=SvSTASH(reference);
3951     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3952     if (image == (Image *) NULL)
3953       {
3954         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3955           PackageName);
3956         goto PerlException;
3957       }
3958     op=MeanEvaluateOperator;
3959     if (items == 2)
3960       {
3961         ssize_t
3962           in;
3963
3964         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3965           SvPV(ST(1),na));
3966         if (in < 0)
3967           {
3968             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3969               SvPV(ST(1),na));
3970             return;
3971           }
3972         op=(MagickEvaluateOperator) in;
3973       }
3974     else
3975       for (i=2; i < items; i+=2)
3976       {
3977         attribute=(char *) SvPV(ST(i-1),na);
3978         switch (*attribute)
3979         {
3980           case 'O':
3981           case 'o':
3982           {
3983             if (LocaleCompare(attribute,"operator") == 0)
3984               {
3985                 ssize_t
3986                   in;
3987
3988                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3989                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3990                 if (in < 0)
3991                   {
3992                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3993                       SvPV(ST(i),na));
3994                     return;
3995                   }
3996                 op=(MagickEvaluateOperator) in;
3997                 break;
3998               }
3999             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4000               attribute);
4001             break;
4002           }
4003           default:
4004           {
4005             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4006               attribute);
4007             break;
4008           }
4009         }
4010       }
4011     image=EvaluateImages(image,op,exception);
4012     if (image == (Image *) NULL)
4013       goto PerlException;
4014     /*
4015       Create blessed Perl array for the returned image.
4016     */
4017     av=newAV();
4018     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4019     SvREFCNT_dec(av);
4020     AddImageToRegistry(sv,image);
4021     rv=newRV(sv);
4022     av_push(av,sv_bless(rv,hv));
4023     SvREFCNT_dec(sv);
4024     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4025     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4026       "evaluate-%.*s",(int) (MagickPathExtent-9),
4027       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4028     (void) CopyMagickString(image->filename,info->image_info->filename,
4029       MagickPathExtent);
4030     SetImageInfo(info->image_info,0,exception);
4031     exception=DestroyExceptionInfo(exception);
4032     SvREFCNT_dec(perl_exception);
4033     XSRETURN(1);
4034
4035   PerlException:
4036     InheritPerlException(exception,perl_exception);
4037     exception=DestroyExceptionInfo(exception);
4038     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4039     SvPOK_on(perl_exception);
4040     ST(0)=sv_2mortal(perl_exception);
4041     XSRETURN(1);
4042   }
4043 \f
4044 #
4045 ###############################################################################
4046 #                                                                             #
4047 #                                                                             #
4048 #                                                                             #
4049 #   F e a t u r e s                                                           #
4050 #                                                                             #
4051 #                                                                             #
4052 #                                                                             #
4053 ###############################################################################
4054 #
4055 #
4056 void
4057 Features(ref,...)
4058   Image::Magick ref=NO_INIT
4059   ALIAS:
4060     FeaturesImage = 1
4061     features      = 2
4062     featuresimage = 3
4063   PPCODE:
4064   {
4065 #define ChannelFeatures(channel,direction) \
4066 { \
4067   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4068     channel_features[channel].angular_second_moment[direction]); \
4069   PUSHs(sv_2mortal(newSVpv(message,0))); \
4070   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4071     channel_features[channel].contrast[direction]); \
4072   PUSHs(sv_2mortal(newSVpv(message,0))); \
4073   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4074     channel_features[channel].contrast[direction]); \
4075   PUSHs(sv_2mortal(newSVpv(message,0))); \
4076   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4077     channel_features[channel].variance_sum_of_squares[direction]); \
4078   PUSHs(sv_2mortal(newSVpv(message,0))); \
4079   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4080     channel_features[channel].inverse_difference_moment[direction]); \
4081   PUSHs(sv_2mortal(newSVpv(message,0))); \
4082   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4083     channel_features[channel].sum_average[direction]); \
4084   PUSHs(sv_2mortal(newSVpv(message,0))); \
4085   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4086     channel_features[channel].sum_variance[direction]); \
4087   PUSHs(sv_2mortal(newSVpv(message,0))); \
4088   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4089     channel_features[channel].sum_entropy[direction]); \
4090   PUSHs(sv_2mortal(newSVpv(message,0))); \
4091   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4092     channel_features[channel].entropy[direction]); \
4093   PUSHs(sv_2mortal(newSVpv(message,0))); \
4094   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4095     channel_features[channel].difference_variance[direction]); \
4096   PUSHs(sv_2mortal(newSVpv(message,0))); \
4097   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4098     channel_features[channel].difference_entropy[direction]); \
4099   PUSHs(sv_2mortal(newSVpv(message,0))); \
4100   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4101     channel_features[channel].measure_of_correlation_1[direction]); \
4102   PUSHs(sv_2mortal(newSVpv(message,0))); \
4103   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4104     channel_features[channel].measure_of_correlation_2[direction]); \
4105   PUSHs(sv_2mortal(newSVpv(message,0))); \
4106   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
4107     channel_features[channel].maximum_correlation_coefficient[direction]); \
4108   PUSHs(sv_2mortal(newSVpv(message,0))); \
4109 }
4110
4111     AV
4112       *av;
4113
4114     char
4115       *attribute,
4116       message[MagickPathExtent];
4117
4118     ChannelFeatures
4119       *channel_features;
4120
4121     double
4122       distance;
4123
4124     ExceptionInfo
4125       *exception;
4126
4127     Image
4128       *image;
4129
4130     register ssize_t
4131       i;
4132
4133     ssize_t
4134       count;
4135
4136     struct PackageInfo
4137       *info;
4138
4139     SV
4140       *perl_exception,
4141       *reference;
4142
4143     PERL_UNUSED_VAR(ref);
4144     PERL_UNUSED_VAR(ix);
4145     exception=AcquireExceptionInfo();
4146     perl_exception=newSVpv("",0);
4147     av=NULL;
4148     if (sv_isobject(ST(0)) == 0)
4149       {
4150         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4151           PackageName);
4152         goto PerlException;
4153       }
4154     reference=SvRV(ST(0));
4155     av=newAV();
4156     SvREFCNT_dec(av);
4157     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4158     if (image == (Image *) NULL)
4159       {
4160         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4161           PackageName);
4162         goto PerlException;
4163       }
4164     distance=1.0;
4165     for (i=2; i < items; i+=2)
4166     {
4167       attribute=(char *) SvPV(ST(i-1),na);
4168       switch (*attribute)
4169       {
4170         case 'D':
4171         case 'd':
4172         {
4173           if (LocaleCompare(attribute,"distance") == 0)
4174             {
4175               distance=StringToLong((char *) SvPV(ST(1),na));
4176               break;
4177             }
4178           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4179             attribute);
4180           break;
4181         }
4182         default:
4183         {
4184           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4185             attribute);
4186           break;
4187         }
4188       }
4189     }
4190     count=0;
4191     for ( ; image; image=image->next)
4192     {
4193       channel_features=GetImageFeatures(image,distance,exception);
4194       if (channel_features == (ChannelFeatures *) NULL)
4195         continue;
4196       count++;
4197       EXTEND(sp,280*count);
4198       for (i=0; i < 4; i++)
4199       {
4200         ChannelFeatures(RedChannel,i);
4201         ChannelFeatures(GreenChannel,i);
4202         ChannelFeatures(BlueChannel,i);
4203         if (image->colorspace == CMYKColorspace)
4204           ChannelFeatures(BlackChannel,i);
4205         if (image->alpha_trait != UndefinedPixelTrait)
4206           ChannelFeatures(AlphaChannel,i);
4207       }
4208       channel_features=(ChannelFeatures *)
4209         RelinquishMagickMemory(channel_features);
4210     }
4211
4212   PerlException:
4213     InheritPerlException(exception,perl_exception);
4214     exception=DestroyExceptionInfo(exception);
4215     SvREFCNT_dec(perl_exception);
4216   }
4217 \f
4218 #
4219 ###############################################################################
4220 #                                                                             #
4221 #                                                                             #
4222 #                                                                             #
4223 #   F l a t t e n                                                             #
4224 #                                                                             #
4225 #                                                                             #
4226 #                                                                             #
4227 ###############################################################################
4228 #
4229 #
4230 void
4231 Flatten(ref)
4232   Image::Magick ref=NO_INIT
4233   ALIAS:
4234     FlattenImage   = 1
4235     flatten        = 2
4236     flattenimage   = 3
4237   PPCODE:
4238   {
4239     AV
4240       *av;
4241
4242     char
4243       *attribute,
4244       *p;
4245
4246     ExceptionInfo
4247       *exception;
4248
4249     HV
4250       *hv;
4251
4252     Image
4253       *image;
4254
4255     PixelInfo
4256       background_color;
4257
4258     register ssize_t
4259       i;
4260
4261     struct PackageInfo
4262       *info;
4263
4264     SV
4265       *perl_exception,
4266       *reference,
4267       *rv,
4268       *sv;
4269
4270     PERL_UNUSED_VAR(ref);
4271     PERL_UNUSED_VAR(ix);
4272     exception=AcquireExceptionInfo();
4273     perl_exception=newSVpv("",0);
4274     sv=NULL;
4275     if (sv_isobject(ST(0)) == 0)
4276       {
4277         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4278           PackageName);
4279         goto PerlException;
4280       }
4281     reference=SvRV(ST(0));
4282     hv=SvSTASH(reference);
4283     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4284     if (image == (Image *) NULL)
4285       {
4286         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4287           PackageName);
4288         goto PerlException;
4289       }
4290     background_color=image->background_color;
4291     if (items == 2)
4292       (void) QueryColorCompliance((char *) SvPV(ST(1),na),AllCompliance,
4293         &background_color,exception);
4294     else
4295       for (i=2; i < items; i+=2)
4296       {
4297         attribute=(char *) SvPV(ST(i-1),na);
4298         switch (*attribute)
4299         {
4300           case 'B':
4301           case 'b':
4302           {
4303             if (LocaleCompare(attribute,"background") == 0)
4304               {
4305                 (void) QueryColorCompliance((char *) SvPV(ST(1),na),
4306                   AllCompliance,&background_color,exception);
4307                 break;
4308               }
4309             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4310               attribute);
4311             break;
4312           }
4313           default:
4314           {
4315             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4316               attribute);
4317             break;
4318           }
4319         }
4320       }
4321     image->background_color=background_color;
4322     image=MergeImageLayers(image,FlattenLayer,exception);
4323     if (image == (Image *) NULL)
4324       goto PerlException;
4325     /*
4326       Create blessed Perl array for the returned image.
4327     */
4328     av=newAV();
4329     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4330     SvREFCNT_dec(av);
4331     AddImageToRegistry(sv,image);
4332     rv=newRV(sv);
4333     av_push(av,sv_bless(rv,hv));
4334     SvREFCNT_dec(sv);
4335     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4336     (void) FormatLocaleString(info->image_info->filename,MagickPathExtent,
4337       "flatten-%.*s",(int) (MagickPathExtent-9),
4338       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4339     (void) CopyMagickString(image->filename,info->image_info->filename,
4340       MagickPathExtent);
4341     SetImageInfo(info->image_info,0,exception);
4342     exception=DestroyExceptionInfo(exception);
4343     SvREFCNT_dec(perl_exception);
4344     XSRETURN(1);
4345
4346   PerlException:
4347     InheritPerlException(exception,perl_exception);
4348     exception=DestroyExceptionInfo(exception);
4349     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4350     SvPOK_on(perl_exception);  /* return messages in string context */
4351     ST(0)=sv_2mortal(perl_exception);
4352     XSRETURN(1);
4353   }
4354 \f
4355 #
4356 ###############################################################################
4357 #                                                                             #
4358 #                                                                             #
4359 #                                                                             #
4360 #   F x                                                                       #
4361 #                                                                             #
4362 #                                                                             #
4363 #                                                                             #
4364 ###############################################################################
4365 #
4366 #
4367 void
4368 Fx(ref,...)
4369   Image::Magick ref=NO_INIT
4370   ALIAS:
4371     FxImage  = 1
4372     fx       = 2
4373     fximage  = 3
4374   PPCODE:
4375   {
4376     AV
4377       *av;
4378
4379     char
4380       *attribute,
4381       expression[MagickPathExtent];
4382
4383     ChannelType
4384       channel,
4385       channel_mask;
4386
4387     ExceptionInfo
4388       *exception;
4389
4390     HV
4391       *hv;
4392
4393     Image
4394       *image;
4395
4396     register ssize_t
4397       i;
4398
4399     struct PackageInfo
4400       *info;
4401
4402     SV
4403       *av_reference,
4404       *perl_exception,
4405       *reference,
4406       *rv,
4407       *sv;
4408
4409     PERL_UNUSED_VAR(ref);
4410     PERL_UNUSED_VAR(ix);
4411     exception=AcquireExceptionInfo();
4412     perl_exception=newSVpv("",0);
4413     sv=NULL;
4414     attribute=NULL;
4415     av=NULL;
4416     if (sv_isobject(ST(0)) == 0)
4417       {
4418         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4419           PackageName);
4420         goto PerlException;
4421       }
4422     reference=SvRV(ST(0));
4423     hv=SvSTASH(reference);
4424     av=newAV();
4425     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4426     SvREFCNT_dec(av);
4427     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4428     if (image == (Image *) NULL)
4429       {
4430         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4431           PackageName);
4432         goto PerlException;
4433       }
4434     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4435     /*
4436       Get options.
4437     */
4438     channel=DefaultChannels;
4439     (void) CopyMagickString(expression,"u",MagickPathExtent);
4440     if (items == 2)
4441       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MagickPathExtent);
4442     else
4443       for (i=2; i < items; i+=2)
4444       {
4445         attribute=(char *) SvPV(ST(i-1),na);
4446         switch (*attribute)
4447         {
4448           case 'C':
4449           case 'c':
4450           {
4451             if (LocaleCompare(attribute,"channel") == 0)
4452               {
4453                 ssize_t
4454                   option;
4455
4456                 option=ParseChannelOption(SvPV(ST(i),na));
4457                 if (option < 0)
4458                   {
4459                     ThrowPerlException(exception,OptionError,
4460                       "UnrecognizedType",SvPV(ST(i),na));
4461                     return;
4462                   }
4463                 channel=(ChannelType) option;
4464                 break;
4465               }
4466             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4467               attribute);
4468             break;
4469           }
4470           case 'E':
4471           case 'e':
4472           {
4473             if (LocaleCompare(attribute,"expression") == 0)
4474               {
4475                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4476                   MagickPathExtent);
4477                 break;
4478               }
4479             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4480               attribute);
4481             break;
4482           }
4483           default:
4484           {
4485             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4486               attribute);
4487             break;
4488           }
4489         }
4490       }
4491     channel_mask=SetImageChannelMask(image,channel);
4492     image=FxImage(image,expression,exception);
4493     if (image != (Image *) NULL)
4494       (void) SetImageChannelMask(image,channel_mask);
4495     if (image == (Image *) NULL)
4496       goto PerlException;
4497     for ( ; image; image=image->next)
4498     {
4499       AddImageToRegistry(sv,image);
4500       rv=newRV(sv);
4501       av_push(av,sv_bless(rv,hv));
4502       SvREFCNT_dec(sv);
4503     }
4504     exception=DestroyExceptionInfo(exception);
4505     ST(0)=av_reference;
4506     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4507     XSRETURN(1);
4508
4509   PerlException:
4510     InheritPerlException(exception,perl_exception);
4511     exception=DestroyExceptionInfo(exception);
4512     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4513     SvPOK_on(perl_exception);
4514     ST(0)=sv_2mortal(perl_exception);
4515     XSRETURN(1);
4516   }
4517 \f
4518 #
4519 ###############################################################################
4520 #                                                                             #
4521 #                                                                             #
4522 #                                                                             #
4523 #   G e t                                                                     #
4524 #                                                                             #
4525 #                                                                             #
4526 #                                                                             #
4527 ###############################################################################
4528 #
4529 #
4530 void
4531 Get(ref,...)
4532   Image::Magick ref=NO_INIT
4533   ALIAS:
4534     GetAttributes = 1
4535     GetAttribute  = 2
4536     get           = 3
4537     getattributes = 4
4538     getattribute  = 5
4539   PPCODE:
4540   {
4541     char
4542       *attribute,
4543       color[MagickPathExtent];
4544
4545     const char
4546       *value;
4547
4548     ExceptionInfo
4549       *exception;
4550
4551     Image
4552       *image;
4553
4554     long
4555       j;
4556
4557     register ssize_t
4558       i;
4559
4560     struct PackageInfo
4561       *info;
4562
4563     SV
4564       *perl_exception,
4565       *reference,
4566       *s;
4567
4568     PERL_UNUSED_VAR(ref);
4569     PERL_UNUSED_VAR(ix);
4570     exception=AcquireExceptionInfo();
4571     perl_exception=newSVpv("",0);
4572     if (sv_isobject(ST(0)) == 0)
4573       {
4574         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4575           PackageName);
4576         XSRETURN_EMPTY;
4577       }
4578     reference=SvRV(ST(0));
4579     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4580     if (image == (Image *) NULL && !info)
4581       XSRETURN_EMPTY;
4582     EXTEND(sp,items);
4583     for (i=1; i < items; i++)
4584     {
4585       attribute=(char *) SvPV(ST(i),na);
4586       s=NULL;
4587       switch (*attribute)
4588       {
4589         case 'A':
4590         case 'a':
4591         {
4592           if (LocaleCompare(attribute,"adjoin") == 0)
4593             {
4594               if (info)
4595                 s=newSViv((ssize_t) info->image_info->adjoin);
4596               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4597               continue;
4598             }
4599           if (LocaleCompare(attribute,"antialias") == 0)
4600             {
4601               if (info)
4602                 s=newSViv((ssize_t) info->image_info->antialias);
4603               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4604               continue;
4605             }
4606           if (LocaleCompare(attribute,"area") == 0)
4607             {
4608               s=newSViv(GetMagickResource(AreaResource));
4609               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4610               continue;
4611             }
4612           if (LocaleCompare(attribute,"attenuate") == 0)
4613             {
4614               const char
4615                 *value;
4616
4617               value=GetImageProperty(image,attribute,exception);
4618               if (value != (const char *) NULL)
4619                 s=newSVpv(value,0);
4620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4621               continue;
4622             }
4623           if (LocaleCompare(attribute,"authenticate") == 0)
4624             {
4625               if (info)
4626                 {
4627                   const char
4628                     *option;
4629
4630                   option=GetImageOption(info->image_info,attribute);
4631                   if (option != (const char *) NULL)
4632                     s=newSVpv(option,0);
4633                 }
4634               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4635               continue;
4636             }
4637           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4638             attribute);
4639           break;
4640         }
4641         case 'B':
4642         case 'b':
4643         {
4644           if (LocaleCompare(attribute,"background") == 0)
4645             {
4646               if (image == (Image *) NULL)
4647                 break;
4648               (void) FormatLocaleString(color,MagickPathExtent,
4649                 "%.20g,%.20g,%.20g,%.20g",(double) image->background_color.red,
4650                 (double) image->background_color.green,
4651                 (double) image->background_color.blue,
4652                 (double) image->background_color.alpha);
4653               s=newSVpv(color,0);
4654               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4655               continue;
4656             }
4657           if (LocaleCompare(attribute,"base-columns") == 0)
4658             {
4659               if (image != (Image *) NULL)
4660                 s=newSViv((ssize_t) image->magick_columns);
4661               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4662               continue;
4663             }
4664           if (LocaleCompare(attribute,"base-filename") == 0)
4665             {
4666               if (image != (Image *) NULL)
4667                 s=newSVpv(image->magick_filename,0);
4668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4669               continue;
4670             }
4671           if (LocaleCompare(attribute,"base-height") == 0)
4672             {
4673               if (image != (Image *) NULL)
4674                 s=newSViv((ssize_t) image->magick_rows);
4675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4676               continue;
4677             }
4678           if (LocaleCompare(attribute,"base-rows") == 0)
4679             {
4680               if (image != (Image *) NULL)
4681                 s=newSViv((ssize_t) image->magick_rows);
4682               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4683               continue;
4684             }
4685           if (LocaleCompare(attribute,"base-width") == 0)
4686             {
4687               if (image != (Image *) NULL)
4688                 s=newSViv((ssize_t) image->magick_columns);
4689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4690               continue;
4691             }
4692           if (LocaleCompare(attribute,"blue-primary") == 0)
4693             {
4694               if (image == (Image *) NULL)
4695                 break;
4696               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
4697                 image->chromaticity.blue_primary.x,
4698                 image->chromaticity.blue_primary.y);
4699               s=newSVpv(color,0);
4700               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4701               continue;
4702             }
4703           if (LocaleCompare(attribute,"bordercolor") == 0)
4704             {
4705               if (image == (Image *) NULL)
4706                 break;
4707               (void) FormatLocaleString(color,MagickPathExtent,
4708                 "%.20g,%.20g,%.20g,%.20g",(double) image->border_color.red,
4709                 (double) image->border_color.green,
4710                 (double) image->border_color.blue,
4711                 (double) image->border_color.alpha);
4712               s=newSVpv(color,0);
4713               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4714               continue;
4715             }
4716           if (LocaleCompare(attribute,"bounding-box") == 0)
4717             {
4718               char
4719                 geometry[MagickPathExtent];
4720
4721               RectangleInfo
4722                 page;
4723
4724               if (image == (Image *) NULL)
4725                 break;
4726               page=GetImageBoundingBox(image,exception);
4727               (void) FormatLocaleString(geometry,MagickPathExtent,
4728                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4729                 page.height,(double) page.x,(double) page.y);
4730               s=newSVpv(geometry,0);
4731               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4732               continue;
4733             }
4734           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4735             attribute);
4736           break;
4737         }
4738         case 'C':
4739         case 'c':
4740         {
4741           if (LocaleCompare(attribute,"class") == 0)
4742             {
4743               if (image == (Image *) NULL)
4744                 break;
4745               s=newSViv(image->storage_class);
4746               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4747                 image->storage_class));
4748               SvIOK_on(s);
4749               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4750               continue;
4751             }
4752           if (LocaleCompare(attribute,"clip-mask") == 0)
4753             {
4754               if (image != (Image *) NULL)
4755                 {
4756                   Image
4757                     *mask_image;
4758
4759                   SV
4760                     *sv;
4761
4762                   sv=NULL;
4763                   if (image->read_mask == MagickFalse)
4764                     ClipImage(image,exception);
4765                   mask_image=GetImageMask(image,exception);
4766                   if (mask_image != (Image *) NULL)
4767                     {
4768                       AddImageToRegistry(sv,mask_image);
4769                       s=sv_bless(newRV(sv),SvSTASH(reference));
4770                     }
4771                 }
4772               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4773               continue;
4774             }
4775           if (LocaleCompare(attribute,"clip-path") == 0)
4776             {
4777               if (image != (Image *) NULL)
4778                 {
4779                   Image
4780                     *mask_image;
4781
4782                   SV
4783                     *sv;
4784
4785                   sv=NULL;
4786                   if (image->read_mask != MagickFalse)
4787                     ClipImage(image,exception);
4788                   mask_image=GetImageMask(image,exception);
4789                   if (mask_image != (Image *) NULL)
4790                     {
4791                       AddImageToRegistry(sv,mask_image);
4792                       s=sv_bless(newRV(sv),SvSTASH(reference));
4793                     }
4794                 }
4795               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4796               continue;
4797             }
4798           if (LocaleCompare(attribute,"compression") == 0)
4799             {
4800               j=info ? info->image_info->compression : image ?
4801                 image->compression : UndefinedCompression;
4802               if (info)
4803                 if (info->image_info->compression == UndefinedCompression)
4804                   j=image->compression;
4805               s=newSViv(j);
4806               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4807                 j));
4808               SvIOK_on(s);
4809               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4810               continue;
4811             }
4812           if (LocaleCompare(attribute,"colorspace") == 0)
4813             {
4814               j=image ? image->colorspace : RGBColorspace;
4815               s=newSViv(j);
4816               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4817                 j));
4818               SvIOK_on(s);
4819               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4820               continue;
4821             }
4822           if (LocaleCompare(attribute,"colors") == 0)
4823             {
4824               if (image != (Image *) NULL)
4825                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4826                   exception));
4827               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4828               continue;
4829             }
4830           if (LocaleNCompare(attribute,"colormap",8) == 0)
4831             {
4832               int
4833                 items;
4834
4835               if (image == (Image *) NULL || !image->colormap)
4836                 break;
4837               j=0;
4838               items=sscanf(attribute,"%*[^[][%ld",&j);
4839               (void) items;
4840               if (j > (ssize_t) image->colors)
4841                 j%=image->colors;
4842               (void) FormatLocaleString(color,MagickPathExtent,
4843                 "%.20g,%.20g,%.20g,%.20g",(double) image->colormap[j].red,
4844                 (double) image->colormap[j].green,
4845                 (double) image->colormap[j].blue,
4846                 (double) image->colormap[j].alpha);
4847               s=newSVpv(color,0);
4848               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4849               continue;
4850             }
4851           if (LocaleCompare(attribute,"columns") == 0)
4852             {
4853               if (image != (Image *) NULL)
4854                 s=newSViv((ssize_t) image->columns);
4855               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4856               continue;
4857             }
4858           if (LocaleCompare(attribute,"comment") == 0)
4859             {
4860               const char
4861                 *value;
4862
4863               value=GetImageProperty(image,attribute,exception);
4864               if (value != (const char *) NULL)
4865                 s=newSVpv(value,0);
4866               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4867               continue;
4868             }
4869           if (LocaleCompare(attribute,"copyright") == 0)
4870             {
4871               s=newSVpv(GetMagickCopyright(),0);
4872               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4873               continue;
4874             }
4875           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4876             attribute);
4877           break;
4878         }
4879         case 'D':
4880         case 'd':
4881         {
4882           if (LocaleCompare(attribute,"density") == 0)
4883             {
4884               char
4885                 geometry[MagickPathExtent];
4886
4887               if (image == (Image *) NULL)
4888                 break;
4889               (void) FormatLocaleString(geometry,MagickPathExtent,"%.15gx%.15g",
4890                 image->resolution.x,image->resolution.y);
4891               s=newSVpv(geometry,0);
4892               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4893               continue;
4894             }
4895           if (LocaleCompare(attribute,"delay") == 0)
4896             {
4897               if (image != (Image *) NULL)
4898                 s=newSViv((ssize_t) image->delay);
4899               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4900               continue;
4901             }
4902           if (LocaleCompare(attribute,"depth") == 0)
4903             {
4904               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4905               if (image != (Image *) NULL)
4906                 s=newSViv((ssize_t) GetImageDepth(image,exception));
4907               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4908               continue;
4909             }
4910           if (LocaleCompare(attribute,"directory") == 0)
4911             {
4912               if (image && image->directory)
4913                 s=newSVpv(image->directory,0);
4914               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4915               continue;
4916             }
4917           if (LocaleCompare(attribute,"dispose") == 0)
4918             {
4919               if (image == (Image *) NULL)
4920                 break;
4921
4922               s=newSViv(image->dispose);
4923               (void) sv_setpv(s,
4924                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4925               SvIOK_on(s);
4926               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4927               continue;
4928             }
4929           if (LocaleCompare(attribute,"disk") == 0)
4930             {
4931               s=newSViv(GetMagickResource(DiskResource));
4932               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4933               continue;
4934             }
4935           if (LocaleCompare(attribute,"dither") == 0)
4936             {
4937               if (info)
4938                 s=newSViv((ssize_t) info->image_info->dither);
4939               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4940               continue;
4941             }
4942           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4943             {
4944               if (info && info->image_info->server_name)
4945                 s=newSVpv(info->image_info->server_name,0);
4946               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4947               continue;
4948             }
4949           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4950             attribute);
4951           break;
4952         }
4953         case 'E':
4954         case 'e':
4955         {
4956           if (LocaleCompare(attribute,"elapsed-time") == 0)
4957             {
4958               if (image != (Image *) NULL)
4959                 s=newSVnv(GetElapsedTime(&image->timer));
4960               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4961               continue;
4962             }
4963           if (LocaleCompare(attribute,"endian") == 0)
4964             {
4965               j=info ? info->image_info->endian : image ? image->endian :
4966                 UndefinedEndian;
4967               s=newSViv(j);
4968               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4969               SvIOK_on(s);
4970               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4971               continue;
4972             }
4973           if (LocaleCompare(attribute,"error") == 0)
4974             {
4975               if (image != (Image *) NULL)
4976                 s=newSVnv(image->error.mean_error_per_pixel);
4977               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4978               continue;
4979             }
4980           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4981             attribute);
4982           break;
4983         }
4984         case 'F':
4985         case 'f':
4986         {
4987           if (LocaleCompare(attribute,"filesize") == 0)
4988             {
4989               if (image != (Image *) NULL)
4990                 s=newSViv((ssize_t) GetBlobSize(image));
4991               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4992               continue;
4993             }
4994           if (LocaleCompare(attribute,"filename") == 0)
4995             {
4996               if (info && info->image_info->filename &&
4997                   *info->image_info->filename)
4998                 s=newSVpv(info->image_info->filename,0);
4999               if (image != (Image *) NULL)
5000                 s=newSVpv(image->filename,0);
5001               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002               continue;
5003             }
5004           if (LocaleCompare(attribute,"filter") == 0)
5005             {
5006               s=image ? newSViv(image->filter) : newSViv(0);
5007               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
5008                 image->filter));
5009               SvIOK_on(s);
5010               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5011               continue;
5012             }
5013           if (LocaleCompare(attribute,"font") == 0)
5014             {
5015               if (info && info->image_info->font)
5016                 s=newSVpv(info->image_info->font,0);
5017               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5018               continue;
5019             }
5020           if (LocaleCompare(attribute,"foreground") == 0)
5021             continue;
5022           if (LocaleCompare(attribute,"format") == 0)
5023             {
5024               const MagickInfo
5025                 *magick_info;
5026
5027               magick_info=(const MagickInfo *) NULL;
5028               if (info && (*info->image_info->magick != '\0'))
5029                 magick_info=GetMagickInfo(info->image_info->magick,exception);
5030               if (image != (Image *) NULL)
5031                 magick_info=GetMagickInfo(image->magick,exception);
5032               if ((magick_info != (const MagickInfo *) NULL) &&
5033                   (*magick_info->description != '\0'))
5034                 s=newSVpv((char *) magick_info->description,0);
5035               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5036               continue;
5037             }
5038           if (LocaleCompare(attribute,"fuzz") == 0)
5039             {
5040               if (info)
5041                 s=newSVnv(info->image_info->fuzz);
5042               if (image != (Image *) NULL)
5043                 s=newSVnv(image->fuzz);
5044               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5045               continue;
5046             }
5047           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5048             attribute);
5049           break;
5050         }
5051         case 'G':
5052         case 'g':
5053         {
5054           if (LocaleCompare(attribute,"gamma") == 0)
5055             {
5056               if (image != (Image *) NULL)
5057                 s=newSVnv(image->gamma);
5058               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5059               continue;
5060             }
5061           if (LocaleCompare(attribute,"geometry") == 0)
5062             {
5063               if (image && image->geometry)
5064                 s=newSVpv(image->geometry,0);
5065               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5066               continue;
5067             }
5068           if (LocaleCompare(attribute,"gravity") == 0)
5069             {
5070               s=image ? newSViv(image->gravity) : newSViv(0);
5071               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
5072                 image->gravity));
5073               SvIOK_on(s);
5074               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5075               continue;
5076             }
5077           if (LocaleCompare(attribute,"green-primary") == 0)
5078             {
5079               if (image == (Image *) NULL)
5080                 break;
5081               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5082                 image->chromaticity.green_primary.x,
5083                 image->chromaticity.green_primary.y);
5084               s=newSVpv(color,0);
5085               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5086               continue;
5087             }
5088           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5089             attribute);
5090           break;
5091         }
5092         case 'H':
5093         case 'h':
5094         {
5095           if (LocaleCompare(attribute,"height") == 0)
5096             {
5097               if (image != (Image *) NULL)
5098                 s=newSViv((ssize_t) image->rows);
5099               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5100               continue;
5101             }
5102           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5103             attribute);
5104           break;
5105         }
5106         case 'I':
5107         case 'i':
5108         {
5109           if (LocaleCompare(attribute,"icc") == 0)
5110             {
5111               if (image != (Image *) NULL)
5112                 {
5113                   const StringInfo
5114                     *profile;
5115
5116                   profile=GetImageProfile(image,"icc");
5117                   if (profile != (StringInfo *) NULL)
5118                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5119                       GetStringInfoLength(profile));
5120                 }
5121               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5122               continue;
5123             }
5124           if (LocaleCompare(attribute,"icm") == 0)
5125             {
5126               if (image != (Image *) NULL)
5127                 {
5128                   const StringInfo
5129                     *profile;
5130
5131                   profile=GetImageProfile(image,"icm");
5132                   if (profile != (const StringInfo *) NULL)
5133                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5134                       GetStringInfoLength(profile));
5135                 }
5136               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5137               continue;
5138             }
5139           if (LocaleCompare(attribute,"id") == 0)
5140             {
5141               if (image != (Image *) NULL)
5142                 {
5143                   char
5144                     key[MagickPathExtent];
5145
5146                   MagickBooleanType
5147                     status;
5148
5149                   static ssize_t
5150                     id = 0;
5151
5152                   (void) FormatLocaleString(key,MagickPathExtent,"%.20g\n",(double)
5153                     id);
5154                   status=SetImageRegistry(ImageRegistryType,key,image,
5155                     exception);
5156                   (void) status;
5157                   s=newSViv(id++);
5158                 }
5159               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5160               continue;
5161             }
5162           if (LocaleNCompare(attribute,"index",5) == 0)
5163             {
5164               char
5165                 name[MagickPathExtent];
5166
5167               int
5168                 items;
5169
5170               long
5171                 x,
5172                 y;
5173
5174               register const Quantum
5175                 *p;
5176
5177               CacheView
5178                 *image_view;
5179
5180               if (image == (Image *) NULL)
5181                 break;
5182               if (image->storage_class != PseudoClass)
5183                 break;
5184               x=0;
5185               y=0;
5186               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5187               (void) items;
5188               image_view=AcquireVirtualCacheView(image,exception);
5189               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,exception);
5190               if (p != (const Quantum *) NULL)
5191                 {
5192                   (void) FormatLocaleString(name,MagickPathExtent,QuantumFormat,
5193                     GetPixelIndex(image,p));
5194                   s=newSVpv(name,0);
5195                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
5196                 }
5197               image_view=DestroyCacheView(image_view);
5198               continue;
5199             }
5200           if (LocaleCompare(attribute,"iptc") == 0)
5201             {
5202               if (image != (Image *) NULL)
5203                 {
5204                   const StringInfo
5205                     *profile;
5206
5207                   profile=GetImageProfile(image,"iptc");
5208                   if (profile != (const StringInfo *) NULL)
5209                     s=newSVpv((const char *) GetStringInfoDatum(profile),
5210                       GetStringInfoLength(profile));
5211                 }
5212               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5213               continue;
5214             }
5215           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
5216             {
5217               if (image != (Image *) NULL)
5218                 s=newSViv((ssize_t) image->iterations);
5219               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5220               continue;
5221             }
5222           if (LocaleCompare(attribute,"interlace") == 0)
5223             {
5224               j=info ? info->image_info->interlace : image ? image->interlace :
5225                 UndefinedInterlace;
5226               s=newSViv(j);
5227               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
5228                 j));
5229               SvIOK_on(s);
5230               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5231               continue;
5232             }
5233           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5234             attribute);
5235           break;
5236         }
5237         case 'L':
5238         case 'l':
5239         {
5240           if (LocaleCompare(attribute,"label") == 0)
5241             {
5242               const char
5243                 *value;
5244
5245               if (image == (Image *) NULL)
5246                 break;
5247               value=GetImageProperty(image,"Label",exception);
5248               if (value != (const char *) NULL)
5249                 s=newSVpv(value,0);
5250               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5251               continue;
5252             }
5253           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
5254             {
5255               if (image != (Image *) NULL)
5256                 s=newSViv((ssize_t) image->iterations);
5257               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5258               continue;
5259             }
5260           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5261             attribute);
5262           break;
5263         }
5264         case 'M':
5265         case 'm':
5266         {
5267           if (LocaleCompare(attribute,"magick") == 0)
5268             {
5269               if (info && *info->image_info->magick)
5270                 s=newSVpv(info->image_info->magick,0);
5271               if (image != (Image *) NULL)
5272                 s=newSVpv(image->magick,0);
5273               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5274               continue;
5275             }
5276           if (LocaleCompare(attribute,"map") == 0)
5277             {
5278               s=newSViv(GetMagickResource(MapResource));
5279               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5280               continue;
5281             }
5282           if (LocaleCompare(attribute,"maximum-error") == 0)
5283             {
5284               if (image != (Image *) NULL)
5285                 s=newSVnv(image->error.normalized_maximum_error);
5286               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5287               continue;
5288             }
5289           if (LocaleCompare(attribute,"memory") == 0)
5290             {
5291               s=newSViv(GetMagickResource(MemoryResource));
5292               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5293               continue;
5294             }
5295           if (LocaleCompare(attribute,"mean-error") == 0)
5296             {
5297               if (image != (Image *) NULL)
5298                 s=newSVnv(image->error.normalized_mean_error);
5299               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5300               continue;
5301             }
5302           if (LocaleCompare(attribute,"mime") == 0)
5303             {
5304               if (info && *info->image_info->magick)
5305                 s=newSVpv(MagickToMime(info->image_info->magick),0);
5306               if (image != (Image *) NULL)
5307                 s=newSVpv(MagickToMime(image->magick),0);
5308               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5309               continue;
5310             }
5311           if (LocaleCompare(attribute,"mattecolor") == 0)
5312             {
5313               if (image == (Image *) NULL)
5314                 break;
5315               (void) FormatLocaleString(color,MagickPathExtent,
5316                 "%.20g,%.20g,%.20g,%.20g",(double) image->matte_color.red,
5317                 (double) image->matte_color.green,
5318                 (double) image->matte_color.blue,
5319                 (double) image->matte_color.alpha);
5320               s=newSVpv(color,0);
5321               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5322               continue;
5323             }
5324           if (LocaleCompare(attribute,"matte") == 0)
5325             {
5326               if (image != (Image *) NULL)
5327                 s=newSViv((ssize_t) image->alpha_trait != UndefinedPixelTrait ?
5328                   1 : 0);
5329               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5330               continue;
5331             }
5332           if (LocaleCompare(attribute,"mime") == 0)
5333             {
5334               const char
5335                 *magick;
5336
5337               magick=NULL;
5338               if (info && *info->image_info->magick)
5339                 magick=info->image_info->magick;
5340               if (image != (Image *) NULL)
5341                 magick=image->magick;
5342               if (magick)
5343                 {
5344                   char
5345                     *mime;
5346
5347                   mime=MagickToMime(magick);
5348                   s=newSVpv(mime,0);
5349                   mime=(char *) RelinquishMagickMemory(mime);
5350                 }
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           if (LocaleCompare(attribute,"monochrome") == 0)
5355             {
5356               if (image == (Image *) NULL)
5357                 continue;
5358               j=info ? info->image_info->monochrome :
5359                 SetImageMonochrome(image,exception);
5360               s=newSViv(j);
5361               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5362               continue;
5363             }
5364           if (LocaleCompare(attribute,"montage") == 0)
5365             {
5366               if (image && image->montage)
5367                 s=newSVpv(image->montage,0);
5368               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5369               continue;
5370             }
5371           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5372             attribute);
5373           break;
5374         }
5375         case 'O':
5376         case 'o':
5377         {
5378           if (LocaleCompare(attribute,"orientation") == 0)
5379             {
5380               j=info ? info->image_info->orientation : image ?
5381                 image->orientation : UndefinedOrientation;
5382               s=newSViv(j);
5383               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5384                 j));
5385               SvIOK_on(s);
5386               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5387               continue;
5388             }
5389           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5390             attribute);
5391           break;
5392         }
5393         case 'P':
5394         case 'p':
5395         {
5396           if (LocaleCompare(attribute,"page") == 0)
5397             {
5398               if (info && info->image_info->page)
5399                 s=newSVpv(info->image_info->page,0);
5400               if (image != (Image *) NULL)
5401                 {
5402                   char
5403                     geometry[MagickPathExtent];
5404
5405                   (void) FormatLocaleString(geometry,MagickPathExtent,
5406                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5407                     (double) image->page.height,(double) image->page.x,(double)
5408                     image->page.y);
5409                   s=newSVpv(geometry,0);
5410                 }
5411               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5412               continue;
5413             }
5414           if (LocaleCompare(attribute,"page.x") == 0)
5415             {
5416               if (image != (Image *) NULL)
5417                 s=newSViv((ssize_t) image->page.x);
5418               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5419               continue;
5420             }
5421           if (LocaleCompare(attribute,"page.y") == 0)
5422             {
5423               if (image != (Image *) NULL)
5424                 s=newSViv((ssize_t) image->page.y);
5425               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5426               continue;
5427             }
5428           if (LocaleNCompare(attribute,"pixel",5) == 0)
5429             {
5430               char
5431                 tuple[MagickPathExtent];
5432
5433               int
5434                 items;
5435
5436               long
5437                 x,
5438                 y;
5439
5440               register const Quantum
5441                 *p;
5442
5443               if (image == (Image *) NULL)
5444                 break;
5445               x=0;
5446               y=0;
5447               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5448               (void) items;
5449               p=GetVirtualPixels(image,x,y,1,1,exception);
5450               if (image->colorspace != CMYKColorspace)
5451                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5452                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5453                   GetPixelRed(image,p),GetPixelGreen(image,p),
5454                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5455               else
5456                 (void) FormatLocaleString(tuple,MagickPathExtent,QuantumFormat ","
5457                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5458                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5459                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5460                   GetPixelAlpha(image,p));
5461               s=newSVpv(tuple,0);
5462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5463               continue;
5464             }
5465           if (LocaleCompare(attribute,"pointsize") == 0)
5466             {
5467               if (info)
5468                 s=newSViv((ssize_t) info->image_info->pointsize);
5469               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5470               continue;
5471             }
5472           if (LocaleCompare(attribute,"preview") == 0)
5473             {
5474               s=newSViv(info->image_info->preview_type);
5475               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5476                 info->image_info->preview_type));
5477               SvIOK_on(s);
5478               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5479               continue;
5480             }
5481           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5482             attribute);
5483           break;
5484         }
5485         case 'Q':
5486         case 'q':
5487         {
5488           if (LocaleCompare(attribute,"quality") == 0)
5489             {
5490               if (info)
5491                 s=newSViv((ssize_t) info->image_info->quality);
5492               if (image != (Image *) NULL)
5493                 s=newSViv((ssize_t) image->quality);
5494               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5495               continue;
5496             }
5497           if (LocaleCompare(attribute,"quantum") == 0)
5498             {
5499               if (info)
5500                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5501               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5502               continue;
5503             }
5504           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5505             attribute);
5506           break;
5507         }
5508         case 'R':
5509         case 'r':
5510         {
5511           if (LocaleCompare(attribute,"rendering-intent") == 0)
5512             {
5513               s=newSViv(image->rendering_intent);
5514               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5515                 image->rendering_intent));
5516               SvIOK_on(s);
5517               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5518               continue;
5519             }
5520           if (LocaleCompare(attribute,"red-primary") == 0)
5521             {
5522               if (image == (Image *) NULL)
5523                 break;
5524               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5525                 image->chromaticity.red_primary.x,
5526                 image->chromaticity.red_primary.y);
5527               s=newSVpv(color,0);
5528               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5529               continue;
5530             }
5531           if (LocaleCompare(attribute,"rows") == 0)
5532             {
5533               if (image != (Image *) NULL)
5534                 s=newSViv((ssize_t) image->rows);
5535               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5536               continue;
5537             }
5538           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5539             attribute);
5540           break;
5541         }
5542         case 'S':
5543         case 's':
5544         {
5545           if (LocaleCompare(attribute,"sampling-factor") == 0)
5546             {
5547               if (info && info->image_info->sampling_factor)
5548                 s=newSVpv(info->image_info->sampling_factor,0);
5549               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5550               continue;
5551             }
5552           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5553             {
5554               if (info && info->image_info->server_name)
5555                 s=newSVpv(info->image_info->server_name,0);
5556               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5557               continue;
5558             }
5559           if (LocaleCompare(attribute,"size") == 0)
5560             {
5561               if (info && info->image_info->size)
5562                 s=newSVpv(info->image_info->size,0);
5563               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5564               continue;
5565             }
5566           if (LocaleCompare(attribute,"scene") == 0)
5567             {
5568               if (image != (Image *) NULL)
5569                 s=newSViv((ssize_t) image->scene);
5570               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5571               continue;
5572             }
5573           if (LocaleCompare(attribute,"scenes") == 0)
5574             {
5575               if (image != (Image *) NULL)
5576                 s=newSViv((ssize_t) info->image_info->number_scenes);
5577               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5578               continue;
5579             }
5580           if (LocaleCompare(attribute,"signature") == 0)
5581             {
5582               const char
5583                 *value;
5584
5585               if (image == (Image *) NULL)
5586                 break;
5587               (void) SignatureImage(image,exception);
5588               value=GetImageProperty(image,"Signature",exception);
5589               if (value != (const char *) NULL)
5590                 s=newSVpv(value,0);
5591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5592               continue;
5593             }
5594           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5595             attribute);
5596           break;
5597         }
5598         case 'T':
5599         case 't':
5600         {
5601           if (LocaleCompare(attribute,"taint") == 0)
5602             {
5603               if (image != (Image *) NULL)
5604                 s=newSViv((ssize_t) IsTaintImage(image));
5605               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5606               continue;
5607             }
5608           if (LocaleCompare(attribute,"texture") == 0)
5609             {
5610               if (info && info->image_info->texture)
5611                 s=newSVpv(info->image_info->texture,0);
5612               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5613               continue;
5614             }
5615           if (LocaleCompare(attribute,"total-ink-density") == 0)
5616             {
5617               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5618               if (image != (Image *) NULL)
5619                 s=newSVnv(GetImageTotalInkDensity(image,exception));
5620               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5621               continue;
5622             }
5623           if (LocaleCompare(attribute,"transparent-color") == 0)
5624             {
5625               if (image == (Image *) NULL)
5626                 break;
5627               (void) FormatLocaleString(color,MagickPathExtent,
5628                 "%.20g,%.20g,%.20g,%.20g",(double) image->transparent_color.red,
5629                 (double) image->transparent_color.green,
5630                 (double) image->transparent_color.blue,
5631                 (double) image->transparent_color.alpha);
5632               s=newSVpv(color,0);
5633               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5634               continue;
5635             }
5636           if (LocaleCompare(attribute,"type") == 0)
5637             {
5638               if (image == (Image *) NULL)
5639                 break;
5640               j=(ssize_t) GetImageType(image,exception);
5641               s=newSViv(j);
5642               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5643               SvIOK_on(s);
5644               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5645               continue;
5646             }
5647           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5648             attribute);
5649           break;
5650         }
5651         case 'U':
5652         case 'u':
5653         {
5654           if (LocaleCompare(attribute,"units") == 0)
5655             {
5656               j=info ? info->image_info->units : image ? image->units :
5657                 UndefinedResolution;
5658               if (info && (info->image_info->units == UndefinedResolution))
5659                 if (image)
5660                   j=image->units;
5661               if (j == UndefinedResolution)
5662                 s=newSVpv("undefined units",0);
5663               else
5664                 if (j == PixelsPerInchResolution)
5665                   s=newSVpv("pixels / inch",0);
5666                 else
5667                   s=newSVpv("pixels / centimeter",0);
5668               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5669               continue;
5670             }
5671           if (LocaleCompare(attribute,"user-time") == 0)
5672             {
5673               if (image != (Image *) NULL)
5674                 s=newSVnv(GetUserTime(&image->timer));
5675               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5676               continue;
5677             }
5678           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5679             attribute);
5680           break;
5681         }
5682         case 'V':
5683         case 'v':
5684         {
5685           if (LocaleCompare(attribute,"verbose") == 0)
5686             {
5687               if (info)
5688                 s=newSViv((ssize_t) info->image_info->verbose);
5689               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5690               continue;
5691             }
5692           if (LocaleCompare(attribute,"version") == 0)
5693             {
5694               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5695               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5696               continue;
5697             }
5698           if (LocaleCompare(attribute,"view") == 0)
5699             {
5700               if (info && info->image_info->view)
5701                 s=newSVpv(info->image_info->view,0);
5702               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5703               continue;
5704             }
5705           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5706             {
5707               if (image == (Image *) NULL)
5708                 break;
5709               j=(ssize_t) GetImageVirtualPixelMethod(image);
5710               s=newSViv(j);
5711               (void) sv_setpv(s,CommandOptionToMnemonic(
5712                 MagickVirtualPixelOptions,j));
5713               SvIOK_on(s);
5714               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5715               continue;
5716             }
5717           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5718             attribute);
5719           break;
5720         }
5721         case 'W':
5722         case 'w':
5723         {
5724           if (LocaleCompare(attribute,"white-point") == 0)
5725             {
5726               if (image == (Image *) NULL)
5727                 break;
5728               (void) FormatLocaleString(color,MagickPathExtent,"%.15g,%.15g",
5729                 image->chromaticity.white_point.x,
5730                 image->chromaticity.white_point.y);
5731               s=newSVpv(color,0);
5732               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5733               continue;
5734             }
5735           if (LocaleCompare(attribute,"width") == 0)
5736             {
5737               if (image != (Image *) NULL)
5738                 s=newSViv((ssize_t) image->columns);
5739               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5740               continue;
5741             }
5742           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5743              attribute);
5744           break;
5745         }
5746         case 'X':
5747         case 'x':
5748         {
5749           if (LocaleCompare(attribute,"x-resolution") == 0)
5750             {
5751               if (image != (Image *) NULL)
5752                 s=newSVnv(image->resolution.x);
5753               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5754               continue;
5755             }
5756           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5757             attribute);
5758           break;
5759         }
5760         case 'Y':
5761         case 'y':
5762         {
5763           if (LocaleCompare(attribute,"y-resolution") == 0)
5764             {
5765               if (image != (Image *) NULL)
5766                 s=newSVnv(image->resolution.y);
5767               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5768               continue;
5769             }
5770           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5771             attribute);
5772           break;
5773         }
5774         default:
5775           break;
5776       }
5777       if (image == (Image *) NULL)
5778         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5779           attribute)
5780       else
5781         {
5782           value=GetImageProperty(image,attribute,exception);
5783           if (value != (const char *) NULL)
5784             {
5785               s=newSVpv(value,0);
5786               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5787             }
5788           else
5789             if (*attribute != '%')
5790               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5791                 attribute)
5792             else
5793               {
5794                  char
5795                    *meta;
5796
5797                  meta=InterpretImageProperties(info ? info->image_info :
5798                    (ImageInfo *) NULL,image,attribute,exception);
5799                  s=newSVpv(meta,0);
5800                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5801                  meta=(char *) RelinquishMagickMemory(meta);
5802               }
5803         }
5804     }
5805     exception=DestroyExceptionInfo(exception);
5806     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5807   }
5808 \f
5809 #
5810 ###############################################################################
5811 #                                                                             #
5812 #                                                                             #
5813 #                                                                             #
5814 #   G e t A u t h e n t i c P i x e l s                                       #
5815 #                                                                             #
5816 #                                                                             #
5817 #                                                                             #
5818 ###############################################################################
5819 #
5820 #
5821 void *
5822 GetAuthenticPixels(ref,...)
5823   Image::Magick ref = NO_INIT
5824   ALIAS:
5825     getauthenticpixels = 1
5826     GetImagePixels = 2
5827     getimagepixels = 3
5828   CODE:
5829   {
5830     char
5831       *attribute;
5832
5833     ExceptionInfo
5834       *exception;
5835
5836     Image
5837       *image;
5838
5839     RectangleInfo
5840       region;
5841
5842     ssize_t
5843       i;
5844
5845     struct PackageInfo
5846       *info;
5847
5848     SV
5849       *perl_exception,
5850       *reference;
5851
5852     void
5853       *blob = NULL;
5854
5855     PERL_UNUSED_VAR(ref);
5856     PERL_UNUSED_VAR(ix);
5857     exception=AcquireExceptionInfo();
5858     perl_exception=newSVpv("",0);
5859     if (sv_isobject(ST(0)) == 0)
5860       {
5861         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5862           PackageName);
5863         goto PerlException;
5864       }
5865     reference=SvRV(ST(0));
5866
5867     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5868     if (image == (Image *) NULL)
5869       {
5870         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5871           PackageName);
5872         goto PerlException;
5873       }
5874
5875     region.x=0;
5876     region.y=0;
5877     region.width=image->columns;
5878     region.height=1;
5879     if (items == 1)
5880       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5881     for (i=2; i < items; i+=2)
5882     {
5883       attribute=(char *) SvPV(ST(i-1),na);
5884       switch (*attribute)
5885       {
5886         case 'g':
5887         case 'G':
5888         {
5889           if (LocaleCompare(attribute,"geometry") == 0)
5890             {
5891               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5892               break;
5893             }
5894           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5895             attribute);
5896           break;
5897         }
5898         case 'H':
5899         case 'h':
5900         {
5901           if (LocaleCompare(attribute,"height") == 0)
5902             {
5903               region.height=SvIV(ST(i));
5904               continue;
5905             }
5906           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5907             attribute);
5908           break;
5909         }
5910         case 'X':
5911         case 'x':
5912         {
5913           if (LocaleCompare(attribute,"x") == 0)
5914             {
5915               region.x=SvIV(ST(i));
5916               continue;
5917             }
5918           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5919             attribute);
5920           break;
5921         }
5922         case 'Y':
5923         case 'y':
5924         {
5925           if (LocaleCompare(attribute,"y") == 0)
5926             {
5927               region.y=SvIV(ST(i));
5928               continue;
5929             }
5930           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5931             attribute);
5932           break;
5933         }
5934         case 'W':
5935         case 'w':
5936         {
5937           if (LocaleCompare(attribute,"width") == 0)
5938             {
5939               region.width=SvIV(ST(i));
5940               continue;
5941             }
5942           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5943             attribute);
5944           break;
5945         }
5946       }
5947     }
5948     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5949       region.height,exception);
5950     if (blob != (void *) NULL)
5951       goto PerlEnd;
5952
5953   PerlException:
5954     InheritPerlException(exception,perl_exception);
5955     exception=DestroyExceptionInfo(exception);
5956     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5957
5958   PerlEnd:
5959     RETVAL = blob;
5960   }
5961   OUTPUT:
5962     RETVAL
5963 \f
5964 #
5965 ###############################################################################
5966 #                                                                             #
5967 #                                                                             #
5968 #                                                                             #
5969 #   G e t V i r t u a l P i x e l s                                           #
5970 #                                                                             #
5971 #                                                                             #
5972 #                                                                             #
5973 ###############################################################################
5974 #
5975 #
5976 void *
5977 GetVirtualPixels(ref,...)
5978   Image::Magick ref = NO_INIT
5979   ALIAS:
5980     getvirtualpixels = 1
5981     AcquireImagePixels = 2
5982     acquireimagepixels = 3
5983   CODE:
5984   {
5985     char
5986       *attribute;
5987
5988     const void
5989       *blob = NULL;
5990
5991     ExceptionInfo
5992       *exception;
5993
5994     Image
5995       *image;
5996
5997     RectangleInfo
5998       region;
5999
6000     ssize_t
6001       i;
6002
6003     struct PackageInfo
6004       *info;
6005
6006     SV
6007       *perl_exception,
6008       *reference;
6009
6010     PERL_UNUSED_VAR(ref);
6011     PERL_UNUSED_VAR(ix);
6012     exception=AcquireExceptionInfo();
6013     perl_exception=newSVpv("",0);
6014     if (sv_isobject(ST(0)) == 0)
6015       {
6016         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6017           PackageName);
6018         goto PerlException;
6019       }
6020     reference=SvRV(ST(0));
6021
6022     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6023     if (image == (Image *) NULL)
6024       {
6025         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6026           PackageName);
6027         goto PerlException;
6028       }
6029
6030     region.x=0;
6031     region.y=0;
6032     region.width=image->columns;
6033     region.height=1;
6034     if (items == 1)
6035       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6036     for (i=2; i < items; i+=2)
6037     {
6038       attribute=(char *) SvPV(ST(i-1),na);
6039       switch (*attribute)
6040       {
6041         case 'g':
6042         case 'G':
6043         {
6044           if (LocaleCompare(attribute,"geometry") == 0)
6045             {
6046               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6047               break;
6048             }
6049           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6050             attribute);
6051           break;
6052         }
6053         case 'H':
6054         case 'h':
6055         {
6056           if (LocaleCompare(attribute,"height") == 0)
6057             {
6058               region.height=SvIV(ST(i));
6059               continue;
6060             }
6061           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6062             attribute);
6063           break;
6064         }
6065         case 'X':
6066         case 'x':
6067         {
6068           if (LocaleCompare(attribute,"x") == 0)
6069             {
6070               region.x=SvIV(ST(i));
6071               continue;
6072             }
6073           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6074             attribute);
6075           break;
6076         }
6077         case 'Y':
6078         case 'y':
6079         {
6080           if (LocaleCompare(attribute,"y") == 0)
6081             {
6082               region.y=SvIV(ST(i));
6083               continue;
6084             }
6085           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6086             attribute);
6087           break;
6088         }
6089         case 'W':
6090         case 'w':
6091         {
6092           if (LocaleCompare(attribute,"width") == 0)
6093             {
6094               region.width=SvIV(ST(i));
6095               continue;
6096             }
6097           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
6098             attribute);
6099           break;
6100         }
6101       }
6102     }
6103     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
6104       region.height,exception);
6105     if (blob != (void *) NULL)
6106       goto PerlEnd;
6107
6108   PerlException:
6109     InheritPerlException(exception,perl_exception);
6110     exception=DestroyExceptionInfo(exception);
6111     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6112
6113   PerlEnd:
6114     RETVAL = (void *) blob;
6115   }
6116   OUTPUT:
6117     RETVAL
6118 \f
6119 #
6120 ###############################################################################
6121 #                                                                             #
6122 #                                                                             #
6123 #                                                                             #
6124 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
6125 #                                                                             #
6126 #                                                                             #
6127 #                                                                             #
6128 ###############################################################################
6129 #
6130 #
6131 void *
6132 GetAuthenticMetacontent(ref,...)
6133   Image::Magick ref = NO_INIT
6134   ALIAS:
6135     getauthenticmetacontent = 1
6136     GetMetacontent = 2
6137     getmetacontent = 3
6138   CODE:
6139   {
6140     ExceptionInfo
6141       *exception;
6142
6143     Image
6144       *image;
6145
6146     struct PackageInfo
6147       *info;
6148
6149     SV
6150       *perl_exception,
6151       *reference;
6152
6153     void
6154       *blob = NULL;
6155
6156     PERL_UNUSED_VAR(ref);
6157     PERL_UNUSED_VAR(ix);
6158     exception=AcquireExceptionInfo();
6159     perl_exception=newSVpv("",0);
6160     if (sv_isobject(ST(0)) == 0)
6161       {
6162         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6163           PackageName);
6164         goto PerlException;
6165       }
6166     reference=SvRV(ST(0));
6167
6168     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6169     if (image == (Image *) NULL)
6170       {
6171         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6172           PackageName);
6173         goto PerlException;
6174       }
6175
6176     blob=(void *) GetAuthenticMetacontent(image);
6177     if (blob != (void *) NULL)
6178       goto PerlEnd;
6179
6180   PerlException:
6181     InheritPerlException(exception,perl_exception);
6182     exception=DestroyExceptionInfo(exception);
6183     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6184
6185   PerlEnd:
6186     RETVAL = blob;
6187   }
6188   OUTPUT:
6189     RETVAL
6190 \f
6191 #
6192 ###############################################################################
6193 #                                                                             #
6194 #                                                                             #
6195 #                                                                             #
6196 #   G e t V i r t u a l M e t a c o n t e n t                                 #
6197 #                                                                             #
6198 #                                                                             #
6199 #                                                                             #
6200 ###############################################################################
6201 #
6202 #
6203 void *
6204 GetVirtualMetacontent(ref,...)
6205   Image::Magick ref = NO_INIT
6206   ALIAS:
6207     getvirtualmetacontent = 1
6208   CODE:
6209   {
6210     ExceptionInfo
6211       *exception;
6212
6213     Image
6214       *image;
6215
6216     struct PackageInfo
6217       *info;
6218
6219     SV
6220       *perl_exception,
6221       *reference;
6222
6223     void
6224       *blob = NULL;
6225
6226     PERL_UNUSED_VAR(ref);
6227     PERL_UNUSED_VAR(ix);
6228     exception=AcquireExceptionInfo();
6229     perl_exception=newSVpv("",0);
6230     if (sv_isobject(ST(0)) == 0)
6231       {
6232         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6233           PackageName);
6234         goto PerlException;
6235       }
6236     reference=SvRV(ST(0));
6237
6238     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6239     if (image == (Image *) NULL)
6240       {
6241         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6242           PackageName);
6243         goto PerlException;
6244       }
6245
6246     blob=(void *) GetVirtualMetacontent(image);
6247     if (blob != (void *) NULL)
6248       goto PerlEnd;
6249
6250   PerlException:
6251     InheritPerlException(exception,perl_exception);
6252     exception=DestroyExceptionInfo(exception);
6253     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6254
6255   PerlEnd:
6256     RETVAL = blob;
6257   }
6258   OUTPUT:
6259     RETVAL
6260 \f
6261 #
6262 ###############################################################################
6263 #                                                                             #
6264 #                                                                             #
6265 #                                                                             #
6266 #   H i s t o g r a m                                                         #
6267 #                                                                             #
6268 #                                                                             #
6269 #                                                                             #
6270 ###############################################################################
6271 #
6272 #
6273 void
6274 Histogram(ref,...)
6275   Image::Magick ref=NO_INIT
6276   ALIAS:
6277     HistogramImage = 1
6278     histogram      = 2
6279     histogramimage = 3
6280   PPCODE:
6281   {
6282     AV
6283       *av;
6284
6285     char
6286       message[MagickPathExtent];
6287
6288     PixelInfo
6289       *histogram;
6290
6291     ExceptionInfo
6292       *exception;
6293
6294     Image
6295       *image;
6296
6297     register ssize_t
6298       i;
6299
6300     ssize_t
6301       count;
6302
6303     struct PackageInfo
6304       *info;
6305
6306     SV
6307       *perl_exception,
6308       *reference;
6309
6310     size_t
6311       number_colors;
6312
6313     PERL_UNUSED_VAR(ref);
6314     PERL_UNUSED_VAR(ix);
6315     exception=AcquireExceptionInfo();
6316     perl_exception=newSVpv("",0);
6317     av=NULL;
6318     if (sv_isobject(ST(0)) == 0)
6319       {
6320         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6321           PackageName);
6322         goto PerlException;
6323       }
6324     reference=SvRV(ST(0));
6325     av=newAV();
6326     SvREFCNT_dec(av);
6327     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6328     if (image == (Image *) NULL)
6329       {
6330         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6331           PackageName);
6332         goto PerlException;
6333       }
6334     count=0;
6335     for ( ; image; image=image->next)
6336     {
6337       histogram=GetImageHistogram(image,&number_colors,exception);
6338       if (histogram == (PixelInfo *) NULL)
6339         continue;
6340       count+=(ssize_t) number_colors;
6341       EXTEND(sp,6*count);
6342       for (i=0; i < (ssize_t) number_colors; i++)
6343       {
6344         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6345           histogram[i].red);
6346         PUSHs(sv_2mortal(newSVpv(message,0)));
6347         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6348           histogram[i].green);
6349         PUSHs(sv_2mortal(newSVpv(message,0)));
6350         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6351           histogram[i].blue);
6352         PUSHs(sv_2mortal(newSVpv(message,0)));
6353         if (image->colorspace == CMYKColorspace)
6354           {
6355             (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6356               histogram[i].black);
6357             PUSHs(sv_2mortal(newSVpv(message,0)));
6358           }
6359         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",
6360           histogram[i].alpha);
6361         PUSHs(sv_2mortal(newSVpv(message,0)));
6362         (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
6363           histogram[i].count);
6364         PUSHs(sv_2mortal(newSVpv(message,0)));
6365       }
6366       histogram=(PixelInfo *) RelinquishMagickMemory(histogram);
6367     }
6368
6369   PerlException:
6370     InheritPerlException(exception,perl_exception);
6371     exception=DestroyExceptionInfo(exception);
6372     SvREFCNT_dec(perl_exception);
6373   }
6374 \f
6375 #
6376 ###############################################################################
6377 #                                                                             #
6378 #                                                                             #
6379 #                                                                             #
6380 #   G e t P i x e l                                                           #
6381 #                                                                             #
6382 #                                                                             #
6383 #                                                                             #
6384 ###############################################################################
6385 #
6386 #
6387 void
6388 GetPixel(ref,...)
6389   Image::Magick ref=NO_INIT
6390   ALIAS:
6391     getpixel = 1
6392     getPixel = 2
6393   PPCODE:
6394   {
6395     AV
6396       *av;
6397
6398     char
6399       *attribute;
6400
6401     ExceptionInfo
6402       *exception;
6403
6404     Image
6405       *image;
6406
6407     MagickBooleanType
6408       normalize;
6409
6410     RectangleInfo
6411       region;
6412
6413     register const Quantum
6414       *p;
6415
6416     register ssize_t
6417       i;
6418
6419     ssize_t
6420       option;
6421
6422     struct PackageInfo
6423       *info;
6424
6425     SV
6426       *perl_exception,
6427       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6428
6429     PERL_UNUSED_VAR(ref);
6430     PERL_UNUSED_VAR(ix);
6431     exception=AcquireExceptionInfo();
6432     perl_exception=newSVpv("",0);
6433     reference=SvRV(ST(0));
6434     av=(AV *) reference;
6435     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6436       exception);
6437     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6438     if (image == (Image *) NULL)
6439       {
6440         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6441           PackageName);
6442         goto PerlException;
6443       }
6444     normalize=MagickTrue;
6445     region.x=0;
6446     region.y=0;
6447     region.width=image->columns;
6448     region.height=1;
6449     if (items == 1)
6450       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6451     for (i=2; i < items; i+=2)
6452     {
6453       attribute=(char *) SvPV(ST(i-1),na);
6454       switch (*attribute)
6455       {
6456         case 'C':
6457         case 'c':
6458         {
6459           if (LocaleCompare(attribute,"channel") == 0)
6460             {
6461               ssize_t
6462                 option;
6463
6464               option=ParseChannelOption(SvPV(ST(i),na));
6465               if (option < 0)
6466                 {
6467                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6468                     SvPV(ST(i),na));
6469                   return;
6470                 }
6471               (void) SetPixelChannelMask(image,(ChannelType) option);
6472               break;
6473             }
6474           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6475             attribute);
6476           break;
6477         }
6478         case 'g':
6479         case 'G':
6480         {
6481           if (LocaleCompare(attribute,"geometry") == 0)
6482             {
6483               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6484               break;
6485             }
6486           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6487             attribute);
6488           break;
6489         }
6490         case 'N':
6491         case 'n':
6492         {
6493           if (LocaleCompare(attribute,"normalize") == 0)
6494             {
6495               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6496                 SvPV(ST(i),na));
6497               if (option < 0)
6498                 {
6499                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6500                     SvPV(ST(i),na));
6501                   break;
6502                 }
6503              normalize=option != 0 ? MagickTrue : MagickFalse;
6504              break;
6505             }
6506           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6507             attribute);
6508           break;
6509         }
6510         case 'x':
6511         case 'X':
6512         {
6513           if (LocaleCompare(attribute,"x") == 0)
6514             {
6515               region.x=SvIV(ST(i));
6516               break;
6517             }
6518           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6519             attribute);
6520           break;
6521         }
6522         case 'y':
6523         case 'Y':
6524         {
6525           if (LocaleCompare(attribute,"y") == 0)
6526             {
6527               region.y=SvIV(ST(i));
6528               break;
6529             }
6530           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6531             attribute);
6532           break;
6533         }
6534         default:
6535         {
6536           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6537             attribute);
6538           break;
6539         }
6540       }
6541     }
6542     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6543     if (p == (const Quantum *) NULL)
6544       PUSHs(&sv_undef);
6545     else
6546       {
6547         double
6548           scale;
6549
6550         scale=1.0;
6551         if (normalize != MagickFalse)
6552           scale=1.0/QuantumRange;
6553         if ((GetPixelRedTraits(image) & UpdatePixelTrait) != 0)
6554           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6555         if ((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0)
6556           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6557         if ((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0)
6558           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6559         if (((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
6560             (image->colorspace == CMYKColorspace))
6561           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6562         if ((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0)
6563           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6564       }
6565
6566   PerlException:
6567     InheritPerlException(exception,perl_exception);
6568     exception=DestroyExceptionInfo(exception);
6569     SvREFCNT_dec(perl_exception);
6570   }
6571 \f
6572 #
6573 ###############################################################################
6574 #                                                                             #
6575 #                                                                             #
6576 #                                                                             #
6577 #   G e t P i x e l s                                                         #
6578 #                                                                             #
6579 #                                                                             #
6580 #                                                                             #
6581 ###############################################################################
6582 #
6583 #
6584 void
6585 GetPixels(ref,...)
6586   Image::Magick ref=NO_INIT
6587   ALIAS:
6588     getpixels = 1
6589     getPixels = 2
6590   PPCODE:
6591   {
6592     AV
6593       *av;
6594
6595     char
6596       *attribute;
6597
6598     const char
6599       *map;
6600
6601     ExceptionInfo
6602       *exception;
6603
6604     Image
6605       *image;
6606
6607     MagickBooleanType
6608       normalize,
6609       status;
6610
6611     RectangleInfo
6612       region;
6613
6614     register ssize_t
6615       i;
6616
6617     ssize_t
6618       option;
6619
6620     struct PackageInfo
6621       *info;
6622
6623     SV
6624       *perl_exception,
6625       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6626
6627     PERL_UNUSED_VAR(ref);
6628     PERL_UNUSED_VAR(ix);
6629     exception=AcquireExceptionInfo();
6630     perl_exception=newSVpv("",0);
6631     reference=SvRV(ST(0));
6632     av=(AV *) reference;
6633     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6634       exception);
6635     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6636     if (image == (Image *) NULL)
6637       {
6638         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6639           PackageName);
6640         goto PerlException;
6641       }
6642     map="RGB";
6643     if (image->alpha_trait != UndefinedPixelTrait)
6644       map="RGBA";
6645     if (image->colorspace == CMYKColorspace)
6646       {
6647         map="CMYK";
6648         if (image->alpha_trait != UndefinedPixelTrait)
6649           map="CMYKA";
6650       }
6651     normalize=MagickFalse;
6652     region.x=0;
6653     region.y=0;
6654     region.width=image->columns;
6655     region.height=1;
6656     if (items == 1)
6657       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6658     for (i=2; i < items; i+=2)
6659     {
6660       attribute=(char *) SvPV(ST(i-1),na);
6661       switch (*attribute)
6662       {
6663         case 'g':
6664         case 'G':
6665         {
6666           if (LocaleCompare(attribute,"geometry") == 0)
6667             {
6668               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6669               break;
6670             }
6671           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6672             attribute);
6673           break;
6674         }
6675         case 'H':
6676         case 'h':
6677         {
6678           if (LocaleCompare(attribute,"height") == 0)
6679             {
6680               region.height=SvIV(ST(i));
6681               break;
6682             }
6683           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6684             attribute);
6685           break;
6686         }
6687         case 'M':
6688         case 'm':
6689         {
6690           if (LocaleCompare(attribute,"map") == 0)
6691             {
6692               map=SvPV(ST(i),na);
6693               break;
6694             }
6695           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6696             attribute);
6697           break;
6698         }
6699         case 'N':
6700         case 'n':
6701         {
6702           if (LocaleCompare(attribute,"normalize") == 0)
6703             {
6704               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6705                 SvPV(ST(i),na));
6706               if (option < 0)
6707                 {
6708                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6709                     SvPV(ST(i),na));
6710                   break;
6711                 }
6712              normalize=option != 0 ? MagickTrue : MagickFalse;
6713              break;
6714             }
6715           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6716             attribute);
6717           break;
6718         }
6719         case 'W':
6720         case 'w':
6721         {
6722           if (LocaleCompare(attribute,"width") == 0)
6723             {
6724               region.width=SvIV(ST(i));
6725               break;
6726             }
6727           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6728             attribute);
6729           break;
6730         }
6731         case 'x':
6732         case 'X':
6733         {
6734           if (LocaleCompare(attribute,"x") == 0)
6735             {
6736               region.x=SvIV(ST(i));
6737               break;
6738             }
6739           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6740             attribute);
6741           break;
6742         }
6743         case 'y':
6744         case 'Y':
6745         {
6746           if (LocaleCompare(attribute,"y") == 0)
6747             {
6748               region.y=SvIV(ST(i));
6749               break;
6750             }
6751           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6752             attribute);
6753           break;
6754         }
6755         default:
6756         {
6757           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6758             attribute);
6759           break;
6760         }
6761       }
6762     }
6763     if (normalize != MagickFalse)
6764       {
6765         float
6766           *pixels;
6767
6768         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6769           region.height*sizeof(*pixels));
6770         if (pixels == (float *) NULL)
6771           {
6772             ThrowPerlException(exception,ResourceLimitError,
6773               "MemoryAllocationFailed",PackageName);
6774             goto PerlException;
6775           }
6776         status=ExportImagePixels(image,region.x,region.y,region.width,
6777           region.height,map,FloatPixel,pixels,exception);
6778         if (status == MagickFalse)
6779           PUSHs(&sv_undef);
6780         else
6781           {
6782             EXTEND(sp,strlen(map)*region.width*region.height);
6783             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6784               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6785           }
6786         pixels=(float *) RelinquishMagickMemory(pixels);
6787       }
6788     else
6789       {
6790         Quantum
6791           *pixels;
6792
6793         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6794           region.height*sizeof(*pixels));
6795         if (pixels == (Quantum *) NULL)
6796           {
6797             ThrowPerlException(exception,ResourceLimitError,
6798               "MemoryAllocationFailed",PackageName);
6799             goto PerlException;
6800           }
6801         status=ExportImagePixels(image,region.x,region.y,region.width,
6802           region.height,map,QuantumPixel,pixels,exception);
6803         if (status == MagickFalse)
6804           PUSHs(&sv_undef);
6805         else
6806           {
6807             EXTEND(sp,strlen(map)*region.width*region.height);
6808             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6809               PUSHs(sv_2mortal(newSViv(pixels[i])));
6810           }
6811         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6812       }
6813
6814   PerlException:
6815     InheritPerlException(exception,perl_exception);
6816     exception=DestroyExceptionInfo(exception);
6817     SvREFCNT_dec(perl_exception);
6818   }
6819 \f
6820 #
6821 ###############################################################################
6822 #                                                                             #
6823 #                                                                             #
6824 #                                                                             #
6825 #   I m a g e T o B l o b                                                     #
6826 #                                                                             #
6827 #                                                                             #
6828 #                                                                             #
6829 ###############################################################################
6830 #
6831 #
6832 void
6833 ImageToBlob(ref,...)
6834   Image::Magick ref=NO_INIT
6835   ALIAS:
6836     ImageToBlob  = 1
6837     imagetoblob  = 2
6838     toblob       = 3
6839     blob         = 4
6840   PPCODE:
6841   {
6842     char
6843       filename[MagickPathExtent];
6844
6845     ExceptionInfo
6846       *exception;
6847
6848     Image
6849       *image,
6850       *next;
6851
6852     register ssize_t
6853       i;
6854
6855     struct PackageInfo
6856       *info,
6857       *package_info;
6858
6859     size_t
6860       length;
6861
6862     ssize_t
6863       scene;
6864
6865     SV
6866       *perl_exception,
6867       *reference;
6868
6869     void
6870       *blob;
6871
6872     PERL_UNUSED_VAR(ref);
6873     PERL_UNUSED_VAR(ix);
6874     exception=AcquireExceptionInfo();
6875     perl_exception=newSVpv("",0);
6876     package_info=(struct PackageInfo *) NULL;
6877     if (sv_isobject(ST(0)) == 0)
6878       {
6879         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6880           PackageName);
6881         goto PerlException;
6882       }
6883     reference=SvRV(ST(0));
6884     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6885     if (image == (Image *) NULL)
6886       {
6887         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6888           PackageName);
6889         goto PerlException;
6890       }
6891     package_info=ClonePackageInfo(info,exception);
6892     for (i=2; i < items; i+=2)
6893       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6894     (void) CopyMagickString(filename,package_info->image_info->filename,
6895       MagickPathExtent);
6896     scene=0;
6897     for (next=image; next; next=next->next)
6898     {
6899       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
6900       next->scene=scene++;
6901     }
6902     SetImageInfo(package_info->image_info,(unsigned int)
6903       GetImageListLength(image),exception);
6904     EXTEND(sp,(ssize_t) GetImageListLength(image));
6905     for ( ; image; image=image->next)
6906     {
6907       length=0;
6908       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6909       if (blob != (char *) NULL)
6910         {
6911           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6912           blob=(unsigned char *) RelinquishMagickMemory(blob);
6913         }
6914       if (package_info->image_info->adjoin)
6915         break;
6916     }
6917
6918   PerlException:
6919     if (package_info != (struct PackageInfo *) NULL)
6920       DestroyPackageInfo(package_info);
6921     InheritPerlException(exception,perl_exception);
6922     exception=DestroyExceptionInfo(exception);
6923     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6924   }
6925 \f
6926 #
6927 ###############################################################################
6928 #                                                                             #
6929 #                                                                             #
6930 #                                                                             #
6931 #   L a y e r s                                                               #
6932 #                                                                             #
6933 #                                                                             #
6934 #                                                                             #
6935 ###############################################################################
6936 #
6937 #
6938 void
6939 Layers(ref,...)
6940   Image::Magick ref=NO_INIT
6941   ALIAS:
6942     Layers                = 1
6943     layers           = 2
6944     OptimizeImageLayers   = 3
6945     optimizelayers        = 4
6946     optimizeimagelayers   = 5
6947   PPCODE:
6948   {
6949     AV
6950       *av;
6951
6952     char
6953       *attribute;
6954
6955     CompositeOperator
6956       compose;
6957
6958     ExceptionInfo
6959       *exception;
6960
6961     HV
6962       *hv;
6963
6964     Image
6965       *image,
6966       *layers;
6967
6968     LayerMethod
6969       method;
6970
6971     register ssize_t
6972       i;
6973
6974     ssize_t
6975       option,
6976       sp;
6977
6978     struct PackageInfo
6979       *info;
6980
6981     SV
6982       *av_reference,
6983       *perl_exception,
6984       *reference,
6985       *rv,
6986       *sv;
6987
6988     PERL_UNUSED_VAR(ref);
6989     PERL_UNUSED_VAR(ix);
6990     exception=AcquireExceptionInfo();
6991     perl_exception=newSVpv("",0);
6992     sv=NULL;
6993     if (sv_isobject(ST(0)) == 0)
6994       {
6995         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6996           PackageName);
6997         goto PerlException;
6998       }
6999     reference=SvRV(ST(0));
7000     hv=SvSTASH(reference);
7001     av=newAV();
7002     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
7003     SvREFCNT_dec(av);
7004     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
7005     if (image == (Image *) NULL)
7006       {
7007         ThrowPerlException(exception,OptionError,"NoImagesDefined",
7008           PackageName);
7009         goto PerlException;
7010       }
7011     compose=image->compose;
7012     method=OptimizeLayer;
7013     for (i=2; i < items; i+=2)
7014     {
7015       attribute=(char *) SvPV(ST(i-1),na);
7016       switch (*attribute)
7017       {
7018         case 'C':
7019         case 'c':
7020         {
7021           if (LocaleCompare(attribute,"compose") == 0)
7022             {
7023               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
7024                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
7025               if (sp < 0)
7026                 {
7027                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7028                     SvPV(ST(i),na));
7029                   break;
7030                 }
7031               compose=(CompositeOperator) sp;
7032               break;
7033             }
7034           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7035             attribute);
7036           break;
7037         }
7038         case 'M':
7039         case 'm':
7040         {
7041           if (LocaleCompare(attribute,"method") == 0)
7042             {
7043               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
7044                 SvPV(ST(i),na));
7045               if (option < 0)
7046                 {
7047                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
7048                     SvPV(ST(i),na));
7049                   break;
7050                 }
7051               method=(LayerMethod) option;
7052               break;
7053             }
7054           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7055             attribute);
7056           break;
7057         }
7058         default:
7059         {
7060           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
7061             attribute);
7062           break;
7063         }
7064       }
7065     }
7066     layers=(Image *) NULL;
7067     switch (method)
7068     {
7069       case CompareAnyLayer:
7070       case CompareClearLayer:
7071       case CompareOverlayLayer:
7072       default:
7073       {
7074         layers=CompareImagesLayers(image,method,exception);
7075         break;
7076       }
7077       case MergeLayer:
7078       case FlattenLayer:
7079       case MosaicLayer:
7080       {
7081         layers=MergeImageLayers(image,method,exception);
7082         break;
7083       }
7084       case DisposeLayer:
7085       {
7086         layers=DisposeImages(image,exception);
7087         break;
7088       }
7089       case OptimizeImageLayer:
7090       {
7091         layers=OptimizeImageLayers(image,exception);
7092         break;
7093       }
7094       case OptimizePlusLayer:
7095       {
7096         layers=OptimizePlusImageLayers(image,exception);
7097         break;
7098       }
7099       case OptimizeTransLayer:
7100       {
7101         OptimizeImageTransparency(image,exception);
7102         break;
7103       }
7104       case RemoveDupsLayer:
7105       {
7106         RemoveDuplicateLayers(&image,exception);
7107         break;
7108       }
7109       case RemoveZeroLayer:
7110       {
7111         RemoveZeroDelayLayers(&image,exception);
7112         break;
7113       }
7114       case OptimizeLayer:
7115       {
7116         QuantizeInfo
7117           *quantize_info;
7118
7119         /*
7120           General Purpose, GIF Animation Optimizer.
7121         */
7122         layers=CoalesceImages(image,exception);
7123         if (layers == (Image *) NULL)
7124           break;
7125         image=layers;
7126         layers=OptimizeImageLayers(image,exception);
7127         if (layers == (Image *) NULL)
7128           break;
7129         image=DestroyImageList(image);
7130         image=layers;
7131         layers=(Image *) NULL;
7132         OptimizeImageTransparency(image,exception);
7133         quantize_info=AcquireQuantizeInfo(info->image_info);
7134         (void) RemapImages(quantize_info,image,(Image *) NULL,exception);
7135         quantize_info=DestroyQuantizeInfo(quantize_info);
7136         break;
7137       }
7138       case CompositeLayer:
7139       {
7140         Image
7141           *source;
7142
7143         RectangleInfo
7144           geometry;
7145
7146         /*
7147           Split image sequence at the first 'NULL:' image.
7148         */
7149         source=image;
7150         while (source != (Image *) NULL)
7151         {
7152           source=GetNextImageInList(source);
7153           if ((source != (Image *) NULL) &&
7154               (LocaleCompare(source->magick,"NULL") == 0))
7155             break;
7156         }
7157         if (source != (Image *) NULL)
7158           {
7159             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
7160                 (GetNextImageInList(source) == (Image *) NULL))
7161               source=(Image *) NULL;
7162             else
7163               {
7164                 /*
7165                   Separate the two lists, junk the null: image.
7166                 */
7167                 source=SplitImageList(source->previous);
7168                 DeleteImageFromList(&source);
7169               }
7170           }
7171         if (source == (Image *) NULL)
7172           {
7173             (void) ThrowMagickException(exception,GetMagickModule(),
7174               OptionError,"MissingNullSeparator","layers Composite");
7175             break;
7176           }
7177         /*
7178           Adjust offset with gravity and virtual canvas.
7179         */
7180         SetGeometry(image,&geometry);
7181         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
7182         geometry.width=source->page.width != 0 ? source->page.width :
7183           source->columns;
7184         geometry.height=source->page.height != 0 ? source->page.height :
7185           source->rows;
7186         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
7187           image->columns,image->page.height != 0 ? image->page.height :
7188           image->rows,image->gravity,&geometry);
7189         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
7190         source=DestroyImageList(source);
7191         break;
7192       }
7193     }
7194     if (layers != (Image *) NULL)
7195       image=layers;
7196     else
7197       image=CloneImage(image,0,0,MagickTrue,exception);
7198     if (image == (Image *) NULL)
7199       goto PerlException;
7200     for ( ; image; image=image->next)
7201     {
7202       AddImageToRegistry(sv,image);
7203       rv=newRV(sv);
7204       av_push(av,sv_bless(rv,hv));
7205       SvREFCNT_dec(sv);
7206     }
7207     exception=DestroyExceptionInfo(exception);
7208     ST(0)=av_reference;
7209     SvREFCNT_dec(perl_exception);
7210     XSRETURN(1);
7211
7212   PerlException:
7213     InheritPerlException(exception,perl_exception);
7214     exception=DestroyExceptionInfo(exception);
7215     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
7216     SvPOK_on(perl_exception);
7217     ST(0)=sv_2mortal(perl_exception);
7218     XSRETURN(1);
7219   }
7220 \f
7221 #
7222 ###############################################################################
7223 #                                                                             #
7224 #                                                                             #
7225 #                                                                             #
7226 #   M a g i c k T o M i m e                                                   #
7227 #                                                                             #
7228 #                                                                             #
7229 #                                                                             #
7230 ###############################################################################
7231 #
7232 #
7233 SV *
7234 MagickToMime(ref,name)
7235   Image::Magick ref=NO_INIT
7236   char *name
7237   ALIAS:
7238     magicktomime = 1
7239   CODE:
7240   {
7241     char
7242       *mime;
7243
7244     PERL_UNUSED_VAR(ref);
7245     PERL_UNUSED_VAR(ix);
7246     mime=MagickToMime(name);
7247     RETVAL=newSVpv(mime,0);
7248     mime=(char *) RelinquishMagickMemory(mime);
7249   }
7250   OUTPUT:
7251     RETVAL
7252 \f
7253 #
7254 ###############################################################################
7255 #                                                                             #
7256 #                                                                             #
7257 #                                                                             #
7258 #   M o g r i f y                                                             #
7259 #                                                                             #
7260 #                                                                             #
7261 #                                                                             #
7262 ###############################################################################
7263 #
7264 #
7265 void
7266 Mogrify(ref,...)
7267   Image::Magick ref=NO_INIT
7268   ALIAS:
7269     Comment            =   1
7270     CommentImage       =   2
7271     Label              =   3
7272     LabelImage         =   4
7273     AddNoise           =   5
7274     AddNoiseImage      =   6
7275     Colorize           =   7
7276     ColorizeImage      =   8
7277     Border             =   9
7278     BorderImage        =  10
7279     Blur               =  11
7280     BlurImage          =  12
7281     Chop               =  13
7282     ChopImage          =  14
7283     Crop               =  15
7284     CropImage          =  16
7285     Despeckle          =  17
7286     DespeckleImage     =  18
7287     Edge               =  19
7288     EdgeImage          =  20
7289     Emboss             =  21
7290     EmbossImage        =  22
7291     Enhance            =  23
7292     EnhanceImage       =  24
7293     Flip               =  25
7294     FlipImage          =  26
7295     Flop               =  27
7296     FlopImage          =  28
7297     Frame              =  29
7298     FrameImage         =  30
7299     Implode            =  31
7300     ImplodeImage       =  32
7301     Magnify            =  33
7302     MagnifyImage       =  34
7303     MedianFilter       =  35
7304     MedianConvolveImage  =  36
7305     Minify             =  37
7306     MinifyImage        =  38
7307     OilPaint           =  39
7308     OilPaintImage      =  40
7309     ReduceNoise        =  41
7310     ReduceNoiseImage   =  42
7311     Roll               =  43
7312     RollImage          =  44
7313     Rotate             =  45
7314     RotateImage        =  46
7315     Sample             =  47
7316     SampleImage        =  48
7317     Scale              =  49
7318     ScaleImage         =  50
7319     Shade              =  51
7320     ShadeImage         =  52
7321     Sharpen            =  53
7322     SharpenImage       =  54
7323     Shear              =  55
7324     ShearImage         =  56
7325     Spread             =  57
7326     SpreadImage        =  58
7327     Swirl              =  59
7328     SwirlImage         =  60
7329     Resize             =  61
7330     ResizeImage        =  62
7331     Zoom               =  63
7332     ZoomImage          =  64
7333     Annotate           =  65
7334     AnnotateImage      =  66
7335     ColorFloodfill     =  67
7336     ColorFloodfillImage=  68
7337     Composite          =  69
7338     CompositeImage     =  70
7339     Contrast           =  71
7340     ContrastImage      =  72
7341     CycleColormap      =  73
7342     CycleColormapImage =  74
7343     Draw               =  75
7344     DrawImage          =  76
7345     Equalize           =  77
7346     EqualizeImage      =  78
7347     Gamma              =  79
7348     GammaImage         =  80
7349     Map                =  81
7350     MapImage           =  82
7351     MatteFloodfill     =  83
7352     MatteFloodfillImage=  84
7353     Modulate           =  85
7354     ModulateImage      =  86
7355     Negate             =  87
7356     NegateImage        =  88
7357     Normalize          =  89
7358     NormalizeImage     =  90
7359     NumberColors       =  91
7360     NumberColorsImage  =  92
7361     Opaque             =  93
7362     OpaqueImage        =  94
7363     Quantize           =  95
7364     QuantizeImage      =  96
7365     Raise              =  97
7366     RaiseImage         =  98
7367     Segment            =  99
7368     SegmentImage       = 100
7369     Signature          = 101
7370     SignatureImage     = 102
7371     Solarize           = 103
7372     SolarizeImage      = 104
7373     Sync               = 105
7374     SyncImage          = 106
7375     Texture            = 107
7376     TextureImage       = 108
7377     Evaluate           = 109
7378     EvaluateImage      = 110
7379     Transparent        = 111
7380     TransparentImage   = 112
7381     Threshold          = 113
7382     ThresholdImage     = 114
7383     Charcoal           = 115
7384     CharcoalImage      = 116
7385     Trim               = 117
7386     TrimImage          = 118
7387     Wave               = 119
7388     WaveImage          = 120
7389     Separate           = 121
7390     SeparateImage      = 122
7391     Stereo             = 125
7392     StereoImage        = 126
7393     Stegano            = 127
7394     SteganoImage       = 128
7395     Deconstruct        = 129
7396     DeconstructImage   = 130
7397     GaussianBlur       = 131
7398     GaussianBlurImage  = 132
7399     Convolve           = 133
7400     ConvolveImage      = 134
7401     Profile            = 135
7402     ProfileImage       = 136
7403     UnsharpMask        = 137
7404     UnsharpMaskImage   = 138
7405     MotionBlur         = 139
7406     MotionBlurImage    = 140
7407     OrderedDither      = 141
7408     OrderedDitherImage = 142
7409     Shave              = 143
7410     ShaveImage         = 144
7411     Level              = 145
7412     LevelImage         = 146
7413     Clip               = 147
7414     ClipImage          = 148
7415     AffineTransform    = 149
7416     AffineTransformImage = 150
7417     Difference         = 151
7418     DifferenceImage    = 152
7419     AdaptiveThreshold  = 153
7420     AdaptiveThresholdImage = 154
7421     Resample           = 155
7422     ResampleImage      = 156
7423     Describe           = 157
7424     DescribeImage      = 158
7425     BlackThreshold     = 159
7426     BlackThresholdImage= 160
7427     WhiteThreshold     = 161
7428     WhiteThresholdImage= 162
7429     RotationalBlur     = 163
7430     RotationalBlurImage= 164
7431     Thumbnail          = 165
7432     ThumbnailImage     = 166
7433     Strip              = 167
7434     StripImage         = 168
7435     Tint               = 169
7436     TintImage          = 170
7437     Channel            = 171
7438     ChannelImage       = 172
7439     Splice             = 173
7440     SpliceImage        = 174
7441     Posterize          = 175
7442     PosterizeImage     = 176
7443     Shadow             = 177
7444     ShadowImage        = 178
7445     Identify           = 179
7446     IdentifyImage      = 180
7447     SepiaTone          = 181
7448     SepiaToneImage     = 182
7449     SigmoidalContrast  = 183
7450     SigmoidalContrastImage = 184
7451     Extent             = 185
7452     ExtentImage        = 186
7453     Vignette           = 187
7454     VignetteImage      = 188
7455     ContrastStretch    = 189
7456     ContrastStretchImage = 190
7457     Sans0              = 191
7458     Sans0Image         = 192
7459     Sans1              = 193
7460     Sans1Image         = 194
7461     AdaptiveSharpen    = 195
7462     AdaptiveSharpenImage = 196
7463     Transpose          = 197
7464     TransposeImage     = 198
7465     Transverse         = 199
7466     TransverseImage    = 200
7467     AutoOrient         = 201
7468     AutoOrientImage    = 202
7469     AdaptiveBlur       = 203
7470     AdaptiveBlurImage  = 204
7471     Sketch             = 205
7472     SketchImage        = 206
7473     UniqueColors       = 207
7474     UniqueColorsImage  = 208
7475     AdaptiveResize     = 209
7476     AdaptiveResizeImage= 210
7477     ClipMask           = 211
7478     ClipMaskImage      = 212
7479     LinearStretch      = 213
7480     LinearStretchImage = 214
7481     ColorMatrix        = 215
7482     ColorMatrixImage   = 216
7483     Mask               = 217
7484     MaskImage          = 218
7485     Polaroid           = 219
7486     PolaroidImage      = 220
7487     FloodfillPaint     = 221
7488     FloodfillPaintImage= 222
7489     Distort            = 223
7490     DistortImage       = 224
7491     Clut               = 225
7492     ClutImage          = 226
7493     LiquidRescale      = 227
7494     LiquidRescaleImage = 228
7495     Encipher           = 229
7496     EncipherImage      = 230
7497     Decipher           = 231
7498     DecipherImage      = 232
7499     Deskew             = 233
7500     DeskewImage        = 234
7501     Remap              = 235
7502     RemapImage         = 236
7503     SparseColor        = 237
7504     SparseColorImage   = 238
7505     Function           = 239
7506     FunctionImage      = 240
7507     SelectiveBlur      = 241
7508     SelectiveBlurImage = 242
7509     HaldClut           = 243
7510     HaldClutImage      = 244
7511     BlueShift          = 245
7512     BlueShiftImage     = 246
7513     ForwardFourierTransform  = 247
7514     ForwardFourierTransformImage = 248
7515     InverseFourierTransform = 249
7516     InverseFourierTransformImage = 250
7517     ColorDecisionList  = 251
7518     ColorDecisionListImage = 252
7519     AutoGamma          = 253
7520     AutoGammaImage     = 254
7521     AutoLevel          = 255
7522     AutoLevelImage     = 256
7523     LevelColors        = 257
7524     LevelImageColors   = 258
7525     Clamp              = 259
7526     ClampImage         = 260
7527     BrightnessContrast = 261
7528     BrightnessContrastImage = 262
7529     Morphology         = 263
7530     MorphologyImage    = 264
7531     Color              = 265
7532     ColorImage         = 266
7533     Mode               = 267
7534     ModeImage          = 268
7535     Statistic          = 269
7536     StatisticImage     = 270
7537     Perceptible        = 271
7538     PerceptibleImage   = 272
7539     Poly               = 273
7540     PolyImage          = 274
7541     Grayscale          = 275
7542     GrayscaleImage     = 276
7543     CannyEdge          = 278
7544     CannyEdgeImage     = 279
7545     HoughLine          = 280
7546     HoughLineImage     = 281
7547     MeanShift          = 282
7548     MeanShiftImage     = 283
7549     Kuwahara           = 284
7550     KuwaharaImage      = 285
7551     ConnectedComponent = 286
7552     ConnectedComponentImage = 287
7553     MogrifyRegion      = 666
7554   PPCODE:
7555   {
7556     AffineMatrix
7557       affine,
7558       current;
7559
7560     char
7561       attribute_flag[MaxArguments],
7562       message[MagickPathExtent];
7563
7564     ChannelType
7565       channel,
7566       channel_mask;
7567
7568     CompositeOperator
7569       compose;
7570
7571     const char
7572       *attribute,
7573       *value;
7574
7575     double
7576       angle;
7577
7578     ExceptionInfo
7579       *exception;
7580
7581     GeometryInfo
7582       geometry_info;
7583
7584     Image
7585       *image,
7586       *next,
7587       *region_image;
7588
7589     MagickBooleanType
7590       status;
7591
7592     MagickStatusType
7593       flags;
7594
7595     PixelInfo
7596       fill_color;
7597
7598     RectangleInfo
7599       geometry,
7600       region_info;
7601
7602     register ssize_t
7603       i;
7604
7605     ssize_t
7606       base,
7607       j,
7608       number_images;
7609
7610     struct Methods
7611       *rp;
7612
7613     struct PackageInfo
7614       *info;
7615
7616     SV
7617       *perl_exception,
7618       **pv,
7619       *reference,
7620       **reference_vector;
7621
7622     struct ArgumentList
7623       argument_list[MaxArguments];
7624
7625     PERL_UNUSED_VAR(ref);
7626     PERL_UNUSED_VAR(ix);
7627     exception=AcquireExceptionInfo();
7628     perl_exception=newSVpv("",0);
7629     reference_vector=NULL;
7630     region_image=NULL;
7631     number_images=0;
7632     base=2;
7633     if (sv_isobject(ST(0)) == 0)
7634       {
7635         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7636           PackageName);
7637         goto PerlException;
7638       }
7639     reference=SvRV(ST(0));
7640     region_info.width=0;
7641     region_info.height=0;
7642     region_info.x=0;
7643     region_info.y=0;
7644     region_image=(Image *) NULL;
7645     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7646     if (ix && (ix != 666))
7647       {
7648         /*
7649           Called as Method(...)
7650         */
7651         ix=(ix+1)/2;
7652         rp=(&Methods[ix-1]);
7653         attribute=rp->name;
7654       }
7655     else
7656       {
7657         /*
7658           Called as Mogrify("Method",...)
7659         */
7660         attribute=(char *) SvPV(ST(1),na);
7661         if (ix)
7662           {
7663             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7664             attribute=(char *) SvPV(ST(2),na);
7665             base++;
7666           }
7667         for (rp=Methods; ; rp++)
7668         {
7669           if (rp >= EndOf(Methods))
7670             {
7671               ThrowPerlException(exception,OptionError,
7672                 "UnrecognizedPerlMagickMethod",attribute);
7673               goto PerlException;
7674             }
7675           if (strEQcase(attribute,rp->name))
7676             break;
7677         }
7678         ix=rp-Methods+1;
7679         base++;
7680       }
7681     if (image == (Image *) NULL)
7682       {
7683         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7684         goto PerlException;
7685       }
7686     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7687     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7688     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7689     {
7690       Arguments
7691         *pp,
7692         *qq;
7693
7694       ssize_t
7695         ssize_test;
7696
7697       struct ArgumentList
7698         *al;
7699
7700       SV
7701         *sv;
7702
7703       sv=NULL;
7704       ssize_test=0;
7705       pp=(Arguments *) NULL;
7706       qq=rp->arguments;
7707       if (i == items)
7708         {
7709           pp=rp->arguments,
7710           sv=ST(i-1);
7711         }
7712       else
7713         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7714         {
7715           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7716             break;
7717           if (strEQcase(attribute,qq->method) > ssize_test)
7718             {
7719               pp=qq;
7720               ssize_test=strEQcase(attribute,qq->method);
7721             }
7722         }
7723       if (pp == (Arguments *) NULL)
7724         {
7725           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7726             attribute);
7727           goto continue_outer_loop;
7728         }
7729       al=(&argument_list[pp-rp->arguments]);
7730       switch (pp->type)
7731       {
7732         case ArrayReference:
7733         {
7734           if (SvTYPE(sv) != SVt_RV)
7735             {
7736               (void) FormatLocaleString(message,MagickPathExtent,
7737                 "invalid %.60s value",pp->method);
7738               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7739               goto continue_outer_loop;
7740             }
7741           al->array_reference=SvRV(sv);
7742           break;
7743         }
7744         case RealReference:
7745         {
7746           al->real_reference=SvNV(sv);
7747           break;
7748         }
7749         case FileReference:
7750         {
7751           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7752           break;
7753         }
7754         case ImageReference:
7755         {
7756           if (!sv_isobject(sv) ||
7757               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7758                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7759             {
7760               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7761                 PackageName);
7762               goto PerlException;
7763             }
7764           break;
7765         }
7766         case IntegerReference:
7767         {
7768           al->integer_reference=SvIV(sv);
7769           break;
7770         }
7771         case StringReference:
7772         {
7773           al->string_reference=(char *) SvPV(sv,al->length);
7774           if (sv_isobject(sv))
7775             al->image_reference=SetupList(aTHX_ SvRV(sv),
7776               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7777           break;
7778         }
7779         default:
7780         {
7781           /*
7782             Is a string; look up name.
7783           */
7784           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7785             {
7786               al->string_reference=(char *) SvPV(sv,al->length);
7787               al->integer_reference=(-1);
7788               break;
7789             }
7790           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7791             MagickFalse,SvPV(sv,na));
7792           if (pp->type == MagickChannelOptions)
7793             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7794           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7795             {
7796               (void) FormatLocaleString(message,MagickPathExtent,
7797                 "invalid %.60s value",pp->method);
7798               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7799               goto continue_outer_loop;
7800             }
7801           break;
7802         }
7803       }
7804       attribute_flag[pp-rp->arguments]++;
7805       continue_outer_loop: ;
7806     }
7807     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7808     pv=reference_vector;
7809     SetGeometryInfo(&geometry_info);
7810     channel=DefaultChannels;
7811     for (next=image; next; next=next->next)
7812     {
7813       image=next;
7814       SetGeometry(image,&geometry);
7815       if ((region_info.width*region_info.height) != 0)
7816         {
7817           region_image=image;
7818           image=CropImage(image,&region_info,exception);
7819         }
7820       switch (ix)
7821       {
7822         default:
7823         {
7824           (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double) ix);
7825           ThrowPerlException(exception,OptionError,
7826             "UnrecognizedPerlMagickMethod",message);
7827           goto PerlException;
7828         }
7829         case 1:  /* Comment */
7830         {
7831           if (attribute_flag[0] == 0)
7832             argument_list[0].string_reference=(char *) NULL;
7833           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7834             info ? info->image_info : (ImageInfo *) NULL,image,
7835             argument_list[0].string_reference,exception),exception);
7836           break;
7837         }
7838         case 2:  /* Label */
7839         {
7840           if (attribute_flag[0] == 0)
7841             argument_list[0].string_reference=(char *) NULL;
7842           (void) SetImageProperty(image,"label",InterpretImageProperties(
7843             info ? info->image_info : (ImageInfo *) NULL,image,
7844             argument_list[0].string_reference,exception),exception);
7845           break;
7846         }
7847         case 3:  /* AddNoise */
7848         {
7849           double
7850             attenuate;
7851
7852           if (attribute_flag[0] == 0)
7853             argument_list[0].integer_reference=UniformNoise;
7854           attenuate=1.0;
7855           if (attribute_flag[1] != 0)
7856             attenuate=argument_list[1].real_reference;
7857           if (attribute_flag[2] != 0)
7858             channel=(ChannelType) argument_list[2].integer_reference;
7859           channel_mask=SetImageChannelMask(image,channel);
7860           image=AddNoiseImage(image,(NoiseType)
7861             argument_list[0].integer_reference,attenuate,exception);
7862           if (image != (Image *) NULL)
7863             (void) SetImageChannelMask(image,channel_mask);
7864           break;
7865         }
7866         case 4:  /* Colorize */
7867         {
7868           PixelInfo
7869             target;
7870
7871           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
7872             0,0,&target,exception);
7873           if (attribute_flag[0] != 0)
7874             (void) QueryColorCompliance(argument_list[0].string_reference,
7875               AllCompliance,&target,exception);
7876           if (attribute_flag[1] == 0)
7877             argument_list[1].string_reference="100%";
7878           image=ColorizeImage(image,argument_list[1].string_reference,&target,
7879             exception);
7880           break;
7881         }
7882         case 5:  /* Border */
7883         {
7884           CompositeOperator
7885             compose;
7886
7887           geometry.width=0;
7888           geometry.height=0;
7889           if (attribute_flag[0] != 0)
7890             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7891               &geometry,exception);
7892           if (attribute_flag[1] != 0)
7893             geometry.width=argument_list[1].integer_reference;
7894           if (attribute_flag[2] != 0)
7895             geometry.height=argument_list[2].integer_reference;
7896           if (attribute_flag[3] != 0)
7897             QueryColorCompliance(argument_list[3].string_reference,
7898               AllCompliance,&image->border_color,exception);
7899           if (attribute_flag[4] != 0)
7900             QueryColorCompliance(argument_list[4].string_reference,
7901               AllCompliance,&image->border_color,exception);
7902           if (attribute_flag[5] != 0)
7903             QueryColorCompliance(argument_list[5].string_reference,
7904               AllCompliance,&image->border_color,exception);
7905           compose=image->compose;
7906           if (attribute_flag[6] != 0)
7907             compose=(CompositeOperator) argument_list[6].integer_reference;
7908           image=BorderImage(image,&geometry,compose,exception);
7909           break;
7910         }
7911         case 6:  /* Blur */
7912         {
7913           if (attribute_flag[0] != 0)
7914             {
7915               flags=ParseGeometry(argument_list[0].string_reference,
7916                 &geometry_info);
7917               if ((flags & SigmaValue) == 0)
7918                 geometry_info.sigma=1.0;
7919             }
7920           if (attribute_flag[1] != 0)
7921             geometry_info.rho=argument_list[1].real_reference;
7922           if (attribute_flag[2] != 0)
7923             geometry_info.sigma=argument_list[2].real_reference;
7924           if (attribute_flag[3] != 0)
7925             channel=(ChannelType) argument_list[3].integer_reference;
7926           channel_mask=SetImageChannelMask(image,channel);
7927           image=BlurImage(image,geometry_info.rho,geometry_info.sigma,
7928             exception);
7929           if (image != (Image *) NULL)
7930             (void) SetImageChannelMask(image,channel_mask);
7931           break;
7932         }
7933         case 7:  /* Chop */
7934         {
7935           if (attribute_flag[5] != 0)
7936             image->gravity=(GravityType) argument_list[5].integer_reference;
7937           if (attribute_flag[0] != 0)
7938             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7939               &geometry,exception);
7940           if (attribute_flag[1] != 0)
7941             geometry.width=argument_list[1].integer_reference;
7942           if (attribute_flag[2] != 0)
7943             geometry.height=argument_list[2].integer_reference;
7944           if (attribute_flag[3] != 0)
7945             geometry.x=argument_list[3].integer_reference;
7946           if (attribute_flag[4] != 0)
7947             geometry.y=argument_list[4].integer_reference;
7948           image=ChopImage(image,&geometry,exception);
7949           break;
7950         }
7951         case 8:  /* Crop */
7952         {
7953           if (attribute_flag[6] != 0)
7954             image->gravity=(GravityType) argument_list[6].integer_reference;
7955           if (attribute_flag[0] != 0)
7956             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7957               &geometry,exception);
7958           if (attribute_flag[1] != 0)
7959             geometry.width=argument_list[1].integer_reference;
7960           if (attribute_flag[2] != 0)
7961             geometry.height=argument_list[2].integer_reference;
7962           if (attribute_flag[3] != 0)
7963             geometry.x=argument_list[3].integer_reference;
7964           if (attribute_flag[4] != 0)
7965             geometry.y=argument_list[4].integer_reference;
7966           if (attribute_flag[5] != 0)
7967             image->fuzz=StringToDoubleInterval(
7968               argument_list[5].string_reference,(double) QuantumRange+1.0);
7969           image=CropImage(image,&geometry,exception);
7970           break;
7971         }
7972         case 9:  /* Despeckle */
7973         {
7974           image=DespeckleImage(image,exception);
7975           break;
7976         }
7977         case 10:  /* Edge */
7978         {
7979           if (attribute_flag[0] != 0)
7980             geometry_info.rho=argument_list[0].real_reference;
7981           image=EdgeImage(image,geometry_info.rho,exception);
7982           break;
7983         }
7984         case 11:  /* Emboss */
7985         {
7986           if (attribute_flag[0] != 0)
7987             {
7988               flags=ParseGeometry(argument_list[0].string_reference,
7989                 &geometry_info);
7990               if ((flags & SigmaValue) == 0)
7991                 geometry_info.sigma=1.0;
7992             }
7993           if (attribute_flag[1] != 0)
7994             geometry_info.rho=argument_list[1].real_reference;
7995           if (attribute_flag[2] != 0)
7996             geometry_info.sigma=argument_list[2].real_reference;
7997           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7998             exception);
7999           break;
8000         }
8001         case 12:  /* Enhance */
8002         {
8003           image=EnhanceImage(image,exception);
8004           break;
8005         }
8006         case 13:  /* Flip */
8007         {
8008           image=FlipImage(image,exception);
8009           break;
8010         }
8011         case 14:  /* Flop */
8012         {
8013           image=FlopImage(image,exception);
8014           break;
8015         }
8016         case 15:  /* Frame */
8017         {
8018           CompositeOperator
8019             compose;
8020
8021           FrameInfo
8022             frame_info;
8023
8024           if (attribute_flag[0] != 0)
8025             {
8026               flags=ParsePageGeometry(image,argument_list[0].string_reference,
8027                 &geometry,exception);
8028               frame_info.width=geometry.width;
8029               frame_info.height=geometry.height;
8030               frame_info.outer_bevel=geometry.x;
8031               frame_info.inner_bevel=geometry.y;
8032             }
8033           if (attribute_flag[1] != 0)
8034             frame_info.width=argument_list[1].integer_reference;
8035           if (attribute_flag[2] != 0)
8036             frame_info.height=argument_list[2].integer_reference;
8037           if (attribute_flag[3] != 0)
8038             frame_info.inner_bevel=argument_list[3].integer_reference;
8039           if (attribute_flag[4] != 0)
8040             frame_info.outer_bevel=argument_list[4].integer_reference;
8041           if (attribute_flag[5] != 0)
8042             QueryColorCompliance(argument_list[5].string_reference,
8043               AllCompliance,&fill_color,exception);
8044           if (attribute_flag[6] != 0)
8045             QueryColorCompliance(argument_list[6].string_reference,
8046               AllCompliance,&fill_color,exception);
8047           frame_info.x=(ssize_t) frame_info.width;
8048           frame_info.y=(ssize_t) frame_info.height;
8049           frame_info.width=image->columns+2*frame_info.x;
8050           frame_info.height=image->rows+2*frame_info.y;
8051           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
8052             image->matte_color=fill_color;
8053           compose=image->compose;
8054           if (attribute_flag[7] != 0)
8055             compose=(CompositeOperator) argument_list[7].integer_reference;
8056           image=FrameImage(image,&frame_info,compose,exception);
8057           break;
8058         }
8059         case 16:  /* Implode */
8060         {
8061           PixelInterpolateMethod
8062             method;
8063
8064           if (attribute_flag[0] == 0)
8065             argument_list[0].real_reference=0.5;
8066           method=UndefinedInterpolatePixel;
8067           if (attribute_flag[1] != 0)
8068             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8069           image=ImplodeImage(image,argument_list[0].real_reference,
8070             method,exception);
8071           break;
8072         }
8073         case 17:  /* Magnify */
8074         {
8075           image=MagnifyImage(image,exception);
8076           break;
8077         }
8078         case 18:  /* MedianFilter */
8079         {
8080           if (attribute_flag[0] != 0)
8081             {
8082               flags=ParseGeometry(argument_list[0].string_reference,
8083                 &geometry_info);
8084               if ((flags & SigmaValue) == 0)
8085                 geometry_info.sigma=geometry_info.rho;
8086             }
8087           if (attribute_flag[1] != 0)
8088             geometry_info.rho=argument_list[1].real_reference;
8089           if (attribute_flag[2] != 0)
8090             geometry_info.sigma=argument_list[2].real_reference;
8091           if (attribute_flag[3] != 0)
8092             channel=(ChannelType) argument_list[3].integer_reference;
8093           channel_mask=SetImageChannelMask(image,channel);
8094           image=StatisticImage(image,MedianStatistic,(size_t) geometry_info.rho,
8095             (size_t) geometry_info.sigma,exception);
8096           if (image != (Image *) NULL)
8097             (void) SetImageChannelMask(image,channel_mask);
8098           break;
8099         }
8100         case 19:  /* Minify */
8101         {
8102           image=MinifyImage(image,exception);
8103           break;
8104         }
8105         case 20:  /* OilPaint */
8106         {
8107           if (attribute_flag[0] == 0)
8108             argument_list[0].real_reference=0.0;
8109           if (attribute_flag[1] == 0)
8110             argument_list[1].real_reference=1.0;
8111           image=OilPaintImage(image,argument_list[0].real_reference,
8112             argument_list[1].real_reference,exception);
8113           break;
8114         }
8115         case 21:  /* ReduceNoise */
8116         {
8117           if (attribute_flag[0] != 0)
8118             {
8119               flags=ParseGeometry(argument_list[0].string_reference,
8120                 &geometry_info);
8121               if ((flags & SigmaValue) == 0)
8122                 geometry_info.sigma=1.0;
8123             }
8124           if (attribute_flag[1] != 0)
8125             geometry_info.rho=argument_list[1].real_reference;
8126           if (attribute_flag[2] != 0)
8127             geometry_info.sigma=argument_list[2].real_reference;
8128           if (attribute_flag[3] != 0)
8129             channel=(ChannelType) argument_list[3].integer_reference;
8130           channel_mask=SetImageChannelMask(image,channel);
8131           image=StatisticImage(image,NonpeakStatistic,(size_t)
8132             geometry_info.rho,(size_t) geometry_info.sigma,exception);
8133           if (image != (Image *) NULL)
8134             (void) SetImageChannelMask(image,channel_mask);
8135           break;
8136         }
8137         case 22:  /* Roll */
8138         {
8139           if (attribute_flag[0] != 0)
8140             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8141               &geometry,exception);
8142           if (attribute_flag[1] != 0)
8143             geometry.x=argument_list[1].integer_reference;
8144           if (attribute_flag[2] != 0)
8145             geometry.y=argument_list[2].integer_reference;
8146           image=RollImage(image,geometry.x,geometry.y,exception);
8147           break;
8148         }
8149         case 23:  /* Rotate */
8150         {
8151           if (attribute_flag[0] == 0)
8152             argument_list[0].real_reference=90.0;
8153           if (attribute_flag[1] != 0)
8154             {
8155               QueryColorCompliance(argument_list[1].string_reference,
8156                 AllCompliance,&image->background_color,exception);
8157               if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
8158                   (image->alpha_trait == UndefinedPixelTrait))
8159                 (void) SetImageAlpha(image,OpaqueAlpha,exception);
8160             }
8161           image=RotateImage(image,argument_list[0].real_reference,exception);
8162           break;
8163         }
8164         case 24:  /* Sample */
8165         {
8166           if (attribute_flag[0] != 0)
8167             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8168               &geometry,exception);
8169           if (attribute_flag[1] != 0)
8170             geometry.width=argument_list[1].integer_reference;
8171           if (attribute_flag[2] != 0)
8172             geometry.height=argument_list[2].integer_reference;
8173           image=SampleImage(image,geometry.width,geometry.height,exception);
8174           break;
8175         }
8176         case 25:  /* Scale */
8177         {
8178           if (attribute_flag[0] != 0)
8179             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8180               &geometry,exception);
8181           if (attribute_flag[1] != 0)
8182             geometry.width=argument_list[1].integer_reference;
8183           if (attribute_flag[2] != 0)
8184             geometry.height=argument_list[2].integer_reference;
8185           image=ScaleImage(image,geometry.width,geometry.height,exception);
8186           break;
8187         }
8188         case 26:  /* Shade */
8189         {
8190           if (attribute_flag[0] != 0)
8191             {
8192               flags=ParseGeometry(argument_list[0].string_reference,
8193                 &geometry_info);
8194               if ((flags & SigmaValue) == 0)
8195                 geometry_info.sigma=0.0;
8196             }
8197           if (attribute_flag[1] != 0)
8198             geometry_info.rho=argument_list[1].real_reference;
8199           if (attribute_flag[2] != 0)
8200             geometry_info.sigma=argument_list[2].real_reference;
8201           image=ShadeImage(image,
8202             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
8203             geometry_info.rho,geometry_info.sigma,exception);
8204           break;
8205         }
8206         case 27:  /* Sharpen */
8207         {
8208           if (attribute_flag[0] != 0)
8209             {
8210               flags=ParseGeometry(argument_list[0].string_reference,
8211                 &geometry_info);
8212               if ((flags & SigmaValue) == 0)
8213                 geometry_info.sigma=1.0;
8214             }
8215           if (attribute_flag[1] != 0)
8216             geometry_info.rho=argument_list[1].real_reference;
8217           if (attribute_flag[2] != 0)
8218             geometry_info.sigma=argument_list[2].real_reference;
8219           if (attribute_flag[3] != 0)
8220             channel=(ChannelType) argument_list[3].integer_reference;
8221           channel_mask=SetImageChannelMask(image,channel);
8222           image=SharpenImage(image,geometry_info.rho,geometry_info.sigma,
8223             exception);
8224           if (image != (Image *) NULL)
8225             (void) SetImageChannelMask(image,channel_mask);
8226           break;
8227         }
8228         case 28:  /* Shear */
8229         {
8230           if (attribute_flag[0] != 0)
8231             {
8232               flags=ParseGeometry(argument_list[0].string_reference,
8233                 &geometry_info);
8234               if ((flags & SigmaValue) == 0)
8235                 geometry_info.sigma=geometry_info.rho;
8236             }
8237           if (attribute_flag[1] != 0)
8238             geometry_info.rho=argument_list[1].real_reference;
8239           if (attribute_flag[2] != 0)
8240             geometry_info.sigma=argument_list[2].real_reference;
8241           if (attribute_flag[3] != 0)
8242             QueryColorCompliance(argument_list[3].string_reference,
8243               AllCompliance,&image->background_color,exception);
8244           if (attribute_flag[4] != 0)
8245             QueryColorCompliance(argument_list[4].string_reference,
8246               AllCompliance,&image->background_color,exception);
8247           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
8248             exception);
8249           break;
8250         }
8251         case 29:  /* Spread */
8252         {
8253           PixelInterpolateMethod
8254             method;
8255
8256           if (attribute_flag[0] == 0)
8257             argument_list[0].real_reference=1.0;
8258           method=UndefinedInterpolatePixel;
8259           if (attribute_flag[1] != 0)
8260             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8261           image=SpreadImage(image,argument_list[0].real_reference,method,
8262             exception);
8263           break;
8264         }
8265         case 30:  /* Swirl */
8266         {
8267           PixelInterpolateMethod
8268             method;
8269
8270           if (attribute_flag[0] == 0)
8271             argument_list[0].real_reference=50.0;
8272           method=UndefinedInterpolatePixel;
8273           if (attribute_flag[1] != 0)
8274             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
8275           image=SwirlImage(image,argument_list[0].real_reference,
8276             method,exception);
8277           break;
8278         }
8279         case 31:  /* Resize */
8280         case 32:  /* Zoom */
8281         {
8282           if (attribute_flag[0] != 0)
8283             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
8284               &geometry,exception);
8285           if (attribute_flag[1] != 0)
8286             geometry.width=argument_list[1].integer_reference;
8287           if (attribute_flag[2] != 0)
8288             geometry.height=argument_list[2].integer_reference;
8289           if (attribute_flag[3] == 0)
8290             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
8291           if (attribute_flag[4] != 0)
8292             SetImageArtifact(image,"filter:support",
8293               argument_list[4].string_reference);
8294           image=ResizeImage(image,geometry.width,geometry.height,
8295             (FilterTypes) argument_list[3].integer_reference,
8296             exception);
8297           break;
8298         }
8299         case 33:  /* Annotate */
8300         {
8301           DrawInfo
8302             *draw_info;
8303
8304           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8305             (DrawInfo *) NULL);
8306           if (attribute_flag[0] != 0)
8307             {
8308               char
8309                 *text;
8310
8311               text=InterpretImageProperties(info ? info->image_info :
8312                 (ImageInfo *) NULL,image,argument_list[0].string_reference,
8313                 exception);
8314               (void) CloneString(&draw_info->text,text);
8315               text=DestroyString(text);
8316             }
8317           if (attribute_flag[1] != 0)
8318             (void) CloneString(&draw_info->font,
8319               argument_list[1].string_reference);
8320           if (attribute_flag[2] != 0)
8321             draw_info->pointsize=argument_list[2].real_reference;
8322           if (attribute_flag[3] != 0)
8323             (void) CloneString(&draw_info->density,
8324               argument_list[3].string_reference);
8325           if (attribute_flag[4] != 0)
8326             (void) QueryColorCompliance(argument_list[4].string_reference,
8327               AllCompliance,&draw_info->undercolor,exception);
8328           if (attribute_flag[5] != 0)
8329             {
8330               (void) QueryColorCompliance(argument_list[5].string_reference,
8331                 AllCompliance,&draw_info->stroke,exception);
8332               if (argument_list[5].image_reference != (Image *) NULL)
8333                 draw_info->stroke_pattern=CloneImage(
8334                   argument_list[5].image_reference,0,0,MagickTrue,exception);
8335             }
8336           if (attribute_flag[6] != 0)
8337             {
8338               (void) QueryColorCompliance(argument_list[6].string_reference,
8339                 AllCompliance,&draw_info->fill,exception);
8340               if (argument_list[6].image_reference != (Image *) NULL)
8341                 draw_info->fill_pattern=CloneImage(
8342                   argument_list[6].image_reference,0,0,MagickTrue,exception);
8343             }
8344           if (attribute_flag[7] != 0)
8345             {
8346               (void) CloneString(&draw_info->geometry,
8347                 argument_list[7].string_reference);
8348               flags=ParsePageGeometry(image,argument_list[7].string_reference,
8349                 &geometry,exception);
8350               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
8351                 geometry_info.sigma=geometry_info.xi;
8352             }
8353           if (attribute_flag[8] != 0)
8354             (void) QueryColorCompliance(argument_list[8].string_reference,
8355               AllCompliance,&draw_info->fill,exception);
8356           if (attribute_flag[11] != 0)
8357             draw_info->gravity=(GravityType)
8358               argument_list[11].integer_reference;
8359           if (attribute_flag[25] != 0)
8360             {
8361               AV
8362                 *av;
8363
8364               av=(AV *) argument_list[25].array_reference;
8365               if ((av_len(av) != 3) && (av_len(av) != 5))
8366                 {
8367                   ThrowPerlException(exception,OptionError,
8368                     "affine matrix must have 4 or 6 elements",PackageName);
8369                   goto PerlException;
8370                 }
8371               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8372               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8373               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8374               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8375               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8376                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8377                 {
8378                   ThrowPerlException(exception,OptionError,
8379                     "affine matrix is singular",PackageName);
8380                    goto PerlException;
8381                 }
8382               if (av_len(av) == 5)
8383                 {
8384                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8385                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8386                 }
8387             }
8388           for (j=12; j < 17; j++)
8389           {
8390             if (attribute_flag[j] == 0)
8391               continue;
8392             value=argument_list[j].string_reference;
8393             angle=argument_list[j].real_reference;
8394             current=draw_info->affine;
8395             GetAffineMatrix(&affine);
8396             switch (j)
8397             {
8398               case 12:
8399               {
8400                 /*
8401                   Translate.
8402                 */
8403                 flags=ParseGeometry(value,&geometry_info);
8404                 affine.tx=geometry_info.xi;
8405                 affine.ty=geometry_info.psi;
8406                 if ((flags & PsiValue) == 0)
8407                   affine.ty=affine.tx;
8408                 break;
8409               }
8410               case 13:
8411               {
8412                 /*
8413                   Scale.
8414                 */
8415                 flags=ParseGeometry(value,&geometry_info);
8416                 affine.sx=geometry_info.rho;
8417                 affine.sy=geometry_info.sigma;
8418                 if ((flags & SigmaValue) == 0)
8419                   affine.sy=affine.sx;
8420                 break;
8421               }
8422               case 14:
8423               {
8424                 /*
8425                   Rotate.
8426                 */
8427                 if (angle == 0.0)
8428                   break;
8429                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8430                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8431                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8432                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8433                 break;
8434               }
8435               case 15:
8436               {
8437                 /*
8438                   SkewX.
8439                 */
8440                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8441                 break;
8442               }
8443               case 16:
8444               {
8445                 /*
8446                   SkewY.
8447                 */
8448                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8449                 break;
8450               }
8451             }
8452             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8453             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8454             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8455             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8456             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8457               current.tx;
8458             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8459               current.ty;
8460           }
8461           if (attribute_flag[9] == 0)
8462             argument_list[9].real_reference=0.0;
8463           if (attribute_flag[10] == 0)
8464             argument_list[10].real_reference=0.0;
8465           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8466             {
8467               char
8468                 geometry[MagickPathExtent];
8469
8470               (void) FormatLocaleString(geometry,MagickPathExtent,"%+f%+f",
8471                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8472                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8473               (void) CloneString(&draw_info->geometry,geometry);
8474             }
8475           if (attribute_flag[17] != 0)
8476             draw_info->stroke_width=argument_list[17].real_reference;
8477           if (attribute_flag[18] != 0)
8478             {
8479               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8480                 MagickTrue : MagickFalse;
8481               draw_info->stroke_antialias=draw_info->text_antialias;
8482             }
8483           if (attribute_flag[19] != 0)
8484             (void) CloneString(&draw_info->family,
8485               argument_list[19].string_reference);
8486           if (attribute_flag[20] != 0)
8487             draw_info->style=(StyleType) argument_list[20].integer_reference;
8488           if (attribute_flag[21] != 0)
8489             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8490           if (attribute_flag[22] != 0)
8491             draw_info->weight=argument_list[22].integer_reference;
8492           if (attribute_flag[23] != 0)
8493             draw_info->align=(AlignType) argument_list[23].integer_reference;
8494           if (attribute_flag[24] != 0)
8495             (void) CloneString(&draw_info->encoding,
8496               argument_list[24].string_reference);
8497           if (attribute_flag[25] != 0)
8498             draw_info->fill_pattern=CloneImage(
8499               argument_list[25].image_reference,0,0,MagickTrue,exception);
8500           if (attribute_flag[26] != 0)
8501             draw_info->fill_pattern=CloneImage(
8502               argument_list[26].image_reference,0,0,MagickTrue,exception);
8503           if (attribute_flag[27] != 0)
8504             draw_info->stroke_pattern=CloneImage(
8505               argument_list[27].image_reference,0,0,MagickTrue,exception);
8506           if (attribute_flag[29] != 0)
8507             draw_info->kerning=argument_list[29].real_reference;
8508           if (attribute_flag[30] != 0)
8509             draw_info->interline_spacing=argument_list[30].real_reference;
8510           if (attribute_flag[31] != 0)
8511             draw_info->interword_spacing=argument_list[31].real_reference;
8512           if (attribute_flag[32] != 0)
8513             draw_info->direction=(DirectionType)
8514               argument_list[32].integer_reference;
8515           (void) AnnotateImage(image,draw_info,exception);
8516           draw_info=DestroyDrawInfo(draw_info);
8517           break;
8518         }
8519         case 34:  /* ColorFloodfill */
8520         {
8521           DrawInfo
8522             *draw_info;
8523
8524           MagickBooleanType
8525             invert;
8526
8527           PixelInfo
8528             target;
8529
8530           draw_info=CloneDrawInfo(info ? info->image_info :
8531             (ImageInfo *) NULL,(DrawInfo *) NULL);
8532           if (attribute_flag[0] != 0)
8533             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8534               &geometry,exception);
8535           if (attribute_flag[1] != 0)
8536             geometry.x=argument_list[1].integer_reference;
8537           if (attribute_flag[2] != 0)
8538             geometry.y=argument_list[2].integer_reference;
8539           if (attribute_flag[3] != 0)
8540             (void) QueryColorCompliance(argument_list[3].string_reference,
8541               AllCompliance,&draw_info->fill,exception);
8542           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
8543             geometry.x,geometry.y,&target,exception);
8544           invert=MagickFalse;
8545           if (attribute_flag[4] != 0)
8546             {
8547               QueryColorCompliance(argument_list[4].string_reference,
8548                 AllCompliance,&target,exception);
8549               invert=MagickTrue;
8550             }
8551           if (attribute_flag[5] != 0)
8552             image->fuzz=StringToDoubleInterval(
8553               argument_list[5].string_reference,(double) QuantumRange+1.0);
8554           if (attribute_flag[6] != 0)
8555             invert=(MagickBooleanType) argument_list[6].integer_reference;
8556           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
8557             geometry.y,invert,exception);
8558           draw_info=DestroyDrawInfo(draw_info);
8559           break;
8560         }
8561         case 35:  /* Composite */
8562         {
8563           char
8564             composite_geometry[MagickPathExtent];
8565
8566           Image
8567             *composite_image,
8568             *rotate_image;
8569
8570           MagickBooleanType
8571             clip_to_self;
8572
8573           compose=OverCompositeOp;
8574           if (attribute_flag[0] != 0)
8575             composite_image=argument_list[0].image_reference;
8576           else
8577             {
8578               ThrowPerlException(exception,OptionError,
8579                 "CompositeImageRequired",PackageName);
8580               goto PerlException;
8581             }
8582           /*
8583             Parameter Handling used for BOTH normal and tiled composition.
8584           */
8585           if (attribute_flag[1] != 0) /* compose */
8586             compose=(CompositeOperator) argument_list[1].integer_reference;
8587           if (attribute_flag[6] != 0) /* opacity  */
8588             {
8589               if (compose != DissolveCompositeOp)
8590                 (void) SetImageAlpha(composite_image,(Quantum)
8591                   StringToDoubleInterval(argument_list[6].string_reference,
8592                   (double) QuantumRange+1.0),exception);
8593               else
8594                 {
8595                   CacheView
8596                     *composite_view;
8597
8598                   double
8599                     opacity;
8600
8601                   MagickBooleanType
8602                     sync;
8603
8604                   register ssize_t
8605                     x;
8606
8607                   register Quantum
8608                     *q;
8609
8610                   ssize_t
8611                     y;
8612
8613                   /*
8614                     Handle dissolve composite operator (patch by
8615                     Kevin A. McGrail).
8616                   */
8617                   (void) CloneString(&image->geometry,
8618                     argument_list[6].string_reference);
8619                   opacity=(Quantum) StringToDoubleInterval(
8620                     argument_list[6].string_reference,(double) QuantumRange+
8621                     1.0);
8622                   if (composite_image->alpha_trait != UndefinedPixelTrait)
8623                     (void) SetImageAlpha(composite_image,OpaqueAlpha,exception);
8624                   composite_view=AcquireAuthenticCacheView(composite_image,exception);
8625                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8626                   {
8627                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8628                       composite_image->columns,1,exception);
8629                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8630                     {
8631                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8632                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),
8633                           q);
8634                       q+=GetPixelChannels(composite_image);
8635                     }
8636                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8637                     if (sync == MagickFalse)
8638                       break;
8639                   }
8640                   composite_view=DestroyCacheView(composite_view);
8641                 }
8642             }
8643           if (attribute_flag[9] != 0)    /* "color=>" */
8644             QueryColorCompliance(argument_list[9].string_reference,
8645               AllCompliance,&composite_image->background_color,exception);
8646           if (attribute_flag[12] != 0) /* "interpolate=>" */
8647             image->interpolate=(PixelInterpolateMethod)
8648               argument_list[12].integer_reference;
8649           if (attribute_flag[13] != 0)   /* "args=>" */
8650             (void) SetImageArtifact(composite_image,"compose:args",
8651               argument_list[13].string_reference);
8652           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8653             (void) SetImageArtifact(composite_image,"compose:args",
8654               argument_list[14].string_reference);
8655           clip_to_self=MagickTrue;
8656           if (attribute_flag[15] != 0)
8657             clip_to_self=(MagickBooleanType)
8658               argument_list[15].integer_reference;
8659           /*
8660             Tiling Composition (with orthogonal rotate).
8661           */
8662           rotate_image=(Image *) NULL;
8663           if (attribute_flag[8] != 0)   /* "rotate=>" */
8664             {
8665                /*
8666                  Rotate image.
8667                */
8668                rotate_image=RotateImage(composite_image,
8669                  argument_list[8].real_reference,exception);
8670                if (rotate_image == (Image *) NULL)
8671                  break;
8672             }
8673           if ((attribute_flag[7] != 0) &&
8674               (argument_list[7].integer_reference != 0)) /* tile */
8675             {
8676               ssize_t
8677                 x,
8678                 y;
8679
8680               /*
8681                 Tile the composite image.
8682               */
8683              if (attribute_flag[8] != 0)   /* "tile=>" */
8684                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8685                  "false");
8686              else
8687                (void) SetImageArtifact(composite_image,
8688                  "compose:outside-overlay","false");
8689              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8690                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8691                 {
8692                   if (attribute_flag[8] != 0) /* rotate */
8693                     (void) CompositeImage(image,rotate_image,compose,
8694                       MagickTrue,x,y,exception);
8695                   else
8696                     (void) CompositeImage(image,composite_image,compose,
8697                       MagickTrue,x,y,exception);
8698                 }
8699               if (attribute_flag[8] != 0) /* rotate */
8700                 rotate_image=DestroyImage(rotate_image);
8701               break;
8702             }
8703           /*
8704             Parameter Handling used used ONLY for normal composition.
8705           */
8706           if (attribute_flag[5] != 0) /* gravity */
8707             image->gravity=(GravityType) argument_list[5].integer_reference;
8708           if (attribute_flag[2] != 0) /* geometry offset */
8709             {
8710               SetGeometry(image,&geometry);
8711               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8712                 &geometry);
8713               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8714                 &geometry);
8715             }
8716           if (attribute_flag[3] != 0) /* x offset */
8717             geometry.x=argument_list[3].integer_reference;
8718           if (attribute_flag[4] != 0) /* y offset */
8719             geometry.y=argument_list[4].integer_reference;
8720           if (attribute_flag[10] != 0) /* mask */
8721             {
8722               if ((image->compose == DisplaceCompositeOp) ||
8723                   (image->compose == DistortCompositeOp))
8724                 {
8725                   /*
8726                     Merge Y displacement into X displacement image.
8727                   */
8728                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8729                     exception);
8730                   (void) CompositeImage(composite_image,
8731                     argument_list[10].image_reference,CopyGreenCompositeOp,
8732                     MagickTrue,0,0,exception);
8733                 }
8734               else
8735                 {
8736                   Image
8737                     *mask_image;
8738
8739                   /*
8740                     Set a blending mask for the composition.
8741                   */
8742                   mask_image=CloneImage(argument_list[10].image_reference,0,0,
8743                     MagickTrue,exception);
8744                   (void) SetImageMask(composite_image,mask_image,exception);
8745                   mask_image=DestroyImage(mask_image);
8746                 }
8747             }
8748           if (attribute_flag[11] != 0) /* channel */
8749             channel=(ChannelType) argument_list[11].integer_reference;
8750           /*
8751             Composite two images (normal composition).
8752           */
8753           (void) FormatLocaleString(composite_geometry,MagickPathExtent,
8754             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8755             (double) composite_image->rows,(double) geometry.x,(double)
8756             geometry.y);
8757           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8758             exception);
8759           channel_mask=SetImageChannelMask(image,channel);
8760           if (attribute_flag[8] == 0) /* no rotate */
8761             CompositeImage(image,composite_image,compose,clip_to_self,
8762               geometry.x,geometry.y,exception);
8763           else
8764             {
8765               /*
8766                 Position adjust rotated image then composite.
8767               */
8768               geometry.x-=(ssize_t) (rotate_image->columns-
8769                 composite_image->columns)/2;
8770               geometry.y-=(ssize_t) (rotate_image->rows-
8771                 composite_image->rows)/2;
8772               CompositeImage(image,rotate_image,compose,clip_to_self,geometry.x,
8773                 geometry.y,exception);
8774               rotate_image=DestroyImage(rotate_image);
8775             }
8776           if (attribute_flag[10] != 0) /* mask */
8777             {
8778               if ((image->compose == DisplaceCompositeOp) ||
8779                   (image->compose == DistortCompositeOp))
8780                 composite_image=DestroyImage(composite_image);
8781               else
8782                 (void) SetImageMask(image,(Image *) NULL,exception);
8783             }
8784           (void) SetImageChannelMask(image,channel_mask);
8785           break;
8786         }
8787         case 36:  /* Contrast */
8788         {
8789           if (attribute_flag[0] == 0)
8790             argument_list[0].integer_reference=0;
8791           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8792             MagickTrue : MagickFalse,exception);
8793           break;
8794         }
8795         case 37:  /* CycleColormap */
8796         {
8797           if (attribute_flag[0] == 0)
8798             argument_list[0].integer_reference=6;
8799           (void) CycleColormapImage(image,argument_list[0].integer_reference,
8800             exception);
8801           break;
8802         }
8803         case 38:  /* Draw */
8804         {
8805           DrawInfo
8806             *draw_info;
8807
8808           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8809             (DrawInfo *) NULL);
8810           (void) CloneString(&draw_info->primitive,"point");
8811           if (attribute_flag[0] != 0)
8812             {
8813               if (argument_list[0].integer_reference < 0)
8814                 (void) CloneString(&draw_info->primitive,
8815                   argument_list[0].string_reference);
8816               else
8817                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8818                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8819             }
8820           if (attribute_flag[1] != 0)
8821             {
8822               if (LocaleCompare(draw_info->primitive,"path") == 0)
8823                 {
8824                   (void) ConcatenateString(&draw_info->primitive," '");
8825                   ConcatenateString(&draw_info->primitive,
8826                     argument_list[1].string_reference);
8827                   (void) ConcatenateString(&draw_info->primitive,"'");
8828                 }
8829               else
8830                 {
8831                   (void) ConcatenateString(&draw_info->primitive," ");
8832                   ConcatenateString(&draw_info->primitive,
8833                     argument_list[1].string_reference);
8834                 }
8835             }
8836           if (attribute_flag[2] != 0)
8837             {
8838               (void) ConcatenateString(&draw_info->primitive," ");
8839               (void) ConcatenateString(&draw_info->primitive,
8840                 CommandOptionToMnemonic(MagickMethodOptions,
8841                 argument_list[2].integer_reference));
8842             }
8843           if (attribute_flag[3] != 0)
8844             {
8845               (void) QueryColorCompliance(argument_list[3].string_reference,
8846                 AllCompliance,&draw_info->stroke,exception);
8847               if (argument_list[3].image_reference != (Image *) NULL)
8848                 draw_info->stroke_pattern=CloneImage(
8849                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8850             }
8851           if (attribute_flag[4] != 0)
8852             {
8853               (void) QueryColorCompliance(argument_list[4].string_reference,
8854                 AllCompliance,&draw_info->fill,exception);
8855               if (argument_list[4].image_reference != (Image *) NULL)
8856                 draw_info->fill_pattern=CloneImage(
8857                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8858             }
8859           if (attribute_flag[5] != 0)
8860             draw_info->stroke_width=argument_list[5].real_reference;
8861           if (attribute_flag[6] != 0)
8862             (void) CloneString(&draw_info->font,
8863               argument_list[6].string_reference);
8864           if (attribute_flag[7] != 0)
8865             (void) QueryColorCompliance(argument_list[7].string_reference,
8866               AllCompliance,&draw_info->border_color,exception);
8867           if (attribute_flag[8] != 0)
8868             draw_info->affine.tx=argument_list[8].real_reference;
8869           if (attribute_flag[9] != 0)
8870             draw_info->affine.ty=argument_list[9].real_reference;
8871           if (attribute_flag[20] != 0)
8872             {
8873               AV
8874                 *av;
8875
8876               av=(AV *) argument_list[20].array_reference;
8877               if ((av_len(av) != 3) && (av_len(av) != 5))
8878                 {
8879                   ThrowPerlException(exception,OptionError,
8880                     "affine matrix must have 4 or 6 elements",PackageName);
8881                   goto PerlException;
8882                 }
8883               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8884               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8885               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8886               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8887               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8888                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8889                 {
8890                   ThrowPerlException(exception,OptionError,
8891                     "affine matrix is singular",PackageName);
8892                    goto PerlException;
8893                 }
8894               if (av_len(av) == 5)
8895                 {
8896                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8897                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8898                 }
8899             }
8900           for (j=10; j < 15; j++)
8901           {
8902             if (attribute_flag[j] == 0)
8903               continue;
8904             value=argument_list[j].string_reference;
8905             angle=argument_list[j].real_reference;
8906             current=draw_info->affine;
8907             GetAffineMatrix(&affine);
8908             switch (j)
8909             {
8910               case 10:
8911               {
8912                 /*
8913                   Translate.
8914                 */
8915                 flags=ParseGeometry(value,&geometry_info);
8916                 affine.tx=geometry_info.xi;
8917                 affine.ty=geometry_info.psi;
8918                 if ((flags & PsiValue) == 0)
8919                   affine.ty=affine.tx;
8920                 break;
8921               }
8922               case 11:
8923               {
8924                 /*
8925                   Scale.
8926                 */
8927                 flags=ParseGeometry(value,&geometry_info);
8928                 affine.sx=geometry_info.rho;
8929                 affine.sy=geometry_info.sigma;
8930                 if ((flags & SigmaValue) == 0)
8931                   affine.sy=affine.sx;
8932                 break;
8933               }
8934               case 12:
8935               {
8936                 /*
8937                   Rotate.
8938                 */
8939                 if (angle == 0.0)
8940                   break;
8941                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8942                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8943                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8944                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8945                 break;
8946               }
8947               case 13:
8948               {
8949                 /*
8950                   SkewX.
8951                 */
8952                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8953                 break;
8954               }
8955               case 14:
8956               {
8957                 /*
8958                   SkewY.
8959                 */
8960                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8961                 break;
8962               }
8963             }
8964             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8965             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8966             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8967             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8968             draw_info->affine.tx=
8969               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8970             draw_info->affine.ty=
8971               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8972           }
8973           if (attribute_flag[15] != 0)
8974             draw_info->fill_pattern=CloneImage(
8975               argument_list[15].image_reference,0,0,MagickTrue,exception);
8976           if (attribute_flag[16] != 0)
8977             draw_info->pointsize=argument_list[16].real_reference;
8978           if (attribute_flag[17] != 0)
8979             {
8980               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8981                 ? MagickTrue : MagickFalse;
8982               draw_info->text_antialias=draw_info->stroke_antialias;
8983             }
8984           if (attribute_flag[18] != 0)
8985             (void) CloneString(&draw_info->density,
8986               argument_list[18].string_reference);
8987           if (attribute_flag[19] != 0)
8988             draw_info->stroke_width=argument_list[19].real_reference;
8989           if (attribute_flag[21] != 0)
8990             draw_info->dash_offset=argument_list[21].real_reference;
8991           if (attribute_flag[22] != 0)
8992             {
8993               AV
8994                 *av;
8995
8996               av=(AV *) argument_list[22].array_reference;
8997               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8998                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8999               if (draw_info->dash_pattern != (double *) NULL)
9000                 {
9001                   for (i=0; i <= av_len(av); i++)
9002                     draw_info->dash_pattern[i]=(double)
9003                       SvNV(*(av_fetch(av,i,0)));
9004                   draw_info->dash_pattern[i]=0.0;
9005                 }
9006             }
9007           if (attribute_flag[23] != 0)
9008             image->interpolate=(PixelInterpolateMethod)
9009               argument_list[23].integer_reference;
9010           if ((attribute_flag[24] != 0) &&
9011               (draw_info->fill_pattern != (Image *) NULL))
9012             flags=ParsePageGeometry(draw_info->fill_pattern,
9013               argument_list[24].string_reference,
9014               &draw_info->fill_pattern->tile_offset,exception);
9015           if (attribute_flag[25] != 0)
9016             {
9017               (void) ConcatenateString(&draw_info->primitive," '");
9018               (void) ConcatenateString(&draw_info->primitive,
9019                 argument_list[25].string_reference);
9020               (void) ConcatenateString(&draw_info->primitive,"'");
9021             }
9022           if (attribute_flag[26] != 0)
9023             draw_info->fill_pattern=CloneImage(
9024               argument_list[26].image_reference,0,0,MagickTrue,exception);
9025           if (attribute_flag[27] != 0)
9026             draw_info->stroke_pattern=CloneImage(
9027               argument_list[27].image_reference,0,0,MagickTrue,exception);
9028           if (attribute_flag[28] != 0)
9029             (void) CloneString(&draw_info->primitive,
9030               argument_list[28].string_reference);
9031           if (attribute_flag[29] != 0)
9032             draw_info->kerning=argument_list[29].real_reference;
9033           if (attribute_flag[30] != 0)
9034             draw_info->interline_spacing=argument_list[30].real_reference;
9035           if (attribute_flag[31] != 0)
9036             draw_info->interword_spacing=argument_list[31].real_reference;
9037           if (attribute_flag[32] != 0)
9038             draw_info->direction=(DirectionType)
9039               argument_list[32].integer_reference;
9040           DrawImage(image,draw_info,exception);
9041           draw_info=DestroyDrawInfo(draw_info);
9042           break;
9043         }
9044         case 39:  /* Equalize */
9045         {
9046           if (attribute_flag[0] != 0)
9047             channel=(ChannelType) argument_list[0].integer_reference;
9048           channel_mask=SetImageChannelMask(image,channel);
9049           EqualizeImage(image,exception);
9050           (void) SetImageChannelMask(image,channel_mask);
9051           break;
9052         }
9053         case 40:  /* Gamma */
9054         {
9055           if (attribute_flag[1] != 0)
9056             channel=(ChannelType) argument_list[1].integer_reference;
9057           if (attribute_flag[2] == 0)
9058             argument_list[2].real_reference=1.0;
9059           if (attribute_flag[3] == 0)
9060             argument_list[3].real_reference=1.0;
9061           if (attribute_flag[4] == 0)
9062             argument_list[4].real_reference=1.0;
9063           if (attribute_flag[0] == 0)
9064             {
9065               (void) FormatLocaleString(message,MagickPathExtent,
9066                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
9067                 (double) argument_list[3].real_reference,
9068                 (double) argument_list[4].real_reference);
9069               argument_list[0].string_reference=message;
9070             }
9071           (void) GammaImage(image,StringToDouble(
9072             argument_list[0].string_reference,(char **) NULL),exception);
9073           break;
9074         }
9075         case 41:  /* Map */
9076         {
9077           QuantizeInfo
9078             *quantize_info;
9079
9080           if (attribute_flag[0] == 0)
9081             {
9082               ThrowPerlException(exception,OptionError,"MapImageRequired",
9083                 PackageName);
9084               goto PerlException;
9085             }
9086           quantize_info=AcquireQuantizeInfo(info->image_info);
9087           if (attribute_flag[1] != 0)
9088             quantize_info->dither_method=(DitherMethod)
9089               argument_list[1].integer_reference;
9090           (void) RemapImages(quantize_info,image,
9091             argument_list[0].image_reference,exception);
9092           quantize_info=DestroyQuantizeInfo(quantize_info);
9093           break;
9094         }
9095         case 42:  /* MatteFloodfill */
9096         {
9097           DrawInfo
9098             *draw_info;
9099
9100           MagickBooleanType
9101             invert;
9102
9103           PixelInfo
9104             target;
9105
9106           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9107             (DrawInfo *) NULL);
9108           if (attribute_flag[0] != 0)
9109             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9110               &geometry,exception);
9111           if (attribute_flag[1] != 0)
9112             geometry.x=argument_list[1].integer_reference;
9113           if (attribute_flag[2] != 0)
9114             geometry.y=argument_list[2].integer_reference;
9115           if (image->alpha_trait == UndefinedPixelTrait)
9116             (void) SetImageAlpha(image,OpaqueAlpha,exception);
9117           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
9118             geometry.x,geometry.y,&target,exception);
9119           if (attribute_flag[4] != 0)
9120             QueryColorCompliance(argument_list[4].string_reference,
9121               AllCompliance,&target,exception);
9122           if (attribute_flag[3] != 0)
9123             target.alpha=StringToDoubleInterval(
9124               argument_list[3].string_reference,(double) (double) QuantumRange+
9125               1.0);
9126           if (attribute_flag[5] != 0)
9127             image->fuzz=StringToDoubleInterval(
9128               argument_list[5].string_reference,(double) QuantumRange+1.0);
9129           invert=MagickFalse;
9130           if (attribute_flag[6] != 0)
9131             invert=(MagickBooleanType) argument_list[6].integer_reference;
9132           channel_mask=SetImageChannelMask(image,AlphaChannel);
9133           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
9134             geometry.y,invert,exception);
9135           (void) SetImageChannelMask(image,channel_mask);
9136           draw_info=DestroyDrawInfo(draw_info);
9137           break;
9138         }
9139         case 43:  /* Modulate */
9140         {
9141           char
9142             modulate[MagickPathExtent];
9143
9144           geometry_info.rho=100.0;
9145           geometry_info.sigma=100.0;
9146           geometry_info.xi=100.0;
9147           if (attribute_flag[0] != 0)
9148             (void)ParseGeometry(argument_list[0].string_reference,
9149               &geometry_info);
9150           if (attribute_flag[1] != 0)
9151             geometry_info.xi=argument_list[1].real_reference;
9152           if (attribute_flag[2] != 0)
9153             geometry_info.sigma=argument_list[2].real_reference;
9154           if (attribute_flag[3] != 0)
9155             {
9156               geometry_info.sigma=argument_list[3].real_reference;
9157               SetImageArtifact(image,"modulate:colorspace","HWB");
9158             }
9159           if (attribute_flag[4] != 0)
9160             {
9161               geometry_info.rho=argument_list[4].real_reference;
9162               SetImageArtifact(image,"modulate:colorspace","HSB");
9163             }
9164           if (attribute_flag[5] != 0)
9165             {
9166               geometry_info.sigma=argument_list[5].real_reference;
9167               SetImageArtifact(image,"modulate:colorspace","HSL");
9168             }
9169           if (attribute_flag[6] != 0)
9170             {
9171               geometry_info.rho=argument_list[6].real_reference;
9172               SetImageArtifact(image,"modulate:colorspace","HWB");
9173             }
9174           (void) FormatLocaleString(modulate,MagickPathExtent,"%.15g,%.15g,%.15g",
9175             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
9176           (void) ModulateImage(image,modulate,exception);
9177           break;
9178         }
9179         case 44:  /* Negate */
9180         {
9181           if (attribute_flag[0] == 0)
9182             argument_list[0].integer_reference=0;
9183           if (attribute_flag[1] != 0)
9184             channel=(ChannelType) argument_list[1].integer_reference;
9185           channel_mask=SetImageChannelMask(image,channel);
9186           (void) NegateImage(image,argument_list[0].integer_reference != 0 ?
9187             MagickTrue : MagickFalse,exception);
9188           (void) SetImageChannelMask(image,channel_mask);
9189           break;
9190         }
9191         case 45:  /* Normalize */
9192         {
9193           if (attribute_flag[0] != 0)
9194             channel=(ChannelType) argument_list[0].integer_reference;
9195           channel_mask=SetImageChannelMask(image,channel);
9196           NormalizeImage(image,exception);
9197           (void) SetImageChannelMask(image,channel_mask);
9198           break;
9199         }
9200         case 46:  /* NumberColors */
9201           break;
9202         case 47:  /* Opaque */
9203         {
9204           MagickBooleanType
9205             invert;
9206
9207           PixelInfo
9208             fill_color,
9209             target;
9210
9211           (void) QueryColorCompliance("none",AllCompliance,&target,
9212              exception);
9213           (void) QueryColorCompliance("none",AllCompliance,&fill_color,
9214             exception);
9215           if (attribute_flag[0] != 0)
9216             (void) QueryColorCompliance(argument_list[0].string_reference,
9217               AllCompliance,&target,exception);
9218           if (attribute_flag[1] != 0)
9219             (void) QueryColorCompliance(argument_list[1].string_reference,
9220               AllCompliance,&fill_color,exception);
9221           if (attribute_flag[2] != 0)
9222             image->fuzz=StringToDoubleInterval(
9223               argument_list[2].string_reference,(double) QuantumRange+1.0);
9224           if (attribute_flag[3] != 0)
9225             channel=(ChannelType) argument_list[3].integer_reference;
9226           invert=MagickFalse;
9227           if (attribute_flag[4] != 0)
9228             invert=(MagickBooleanType) argument_list[4].integer_reference;
9229           channel_mask=SetImageChannelMask(image,channel);
9230           (void) OpaquePaintImage(image,&target,&fill_color,invert,exception);
9231           (void) SetImageChannelMask(image,channel_mask);
9232           break;
9233         }
9234         case 48:  /* Quantize */
9235         {
9236           QuantizeInfo
9237             *quantize_info;
9238
9239           quantize_info=AcquireQuantizeInfo(info->image_info);
9240           if (attribute_flag[0] != 0)
9241             quantize_info->number_colors=(size_t)
9242               argument_list[0].integer_reference;
9243           if (attribute_flag[1] != 0)
9244             quantize_info->tree_depth=(size_t)
9245               argument_list[1].integer_reference;
9246           if (attribute_flag[2] != 0)
9247             quantize_info->colorspace=(ColorspaceType)
9248               argument_list[2].integer_reference;
9249           if (attribute_flag[3] != 0)
9250             quantize_info->dither_method=(DitherMethod)
9251               argument_list[3].integer_reference;
9252           if (attribute_flag[4] != 0)
9253             quantize_info->measure_error=
9254               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
9255           if (attribute_flag[6] != 0)
9256             (void) QueryColorCompliance(argument_list[6].string_reference,
9257               AllCompliance,&image->transparent_color,exception);
9258           if (attribute_flag[7] != 0)
9259             quantize_info->dither_method=(DitherMethod)
9260               argument_list[7].integer_reference;
9261           if (attribute_flag[5] && argument_list[5].integer_reference)
9262             (void) QuantizeImages(quantize_info,image,exception);
9263           else
9264             if ((image->storage_class == DirectClass) ||
9265                (image->colors > quantize_info->number_colors) ||
9266                (quantize_info->colorspace == GRAYColorspace))
9267              (void) QuantizeImage(quantize_info,image,exception);
9268            else
9269              CompressImageColormap(image,exception);
9270           quantize_info=DestroyQuantizeInfo(quantize_info);
9271           break;
9272         }
9273         case 49:  /* Raise */
9274         {
9275           if (attribute_flag[0] != 0)
9276             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9277               &geometry,exception);
9278           if (attribute_flag[1] != 0)
9279             geometry.width=argument_list[1].integer_reference;
9280           if (attribute_flag[2] != 0)
9281             geometry.height=argument_list[2].integer_reference;
9282           if (attribute_flag[3] == 0)
9283             argument_list[3].integer_reference=1;
9284           (void) RaiseImage(image,&geometry,
9285             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
9286             exception);
9287           break;
9288         }
9289         case 50:  /* Segment */
9290         {
9291           ColorspaceType
9292             colorspace;
9293
9294           double
9295             cluster_threshold,
9296             smoothing_threshold;
9297
9298           MagickBooleanType
9299             verbose;
9300
9301           cluster_threshold=1.0;
9302           smoothing_threshold=1.5;
9303           colorspace=sRGBColorspace;
9304           verbose=MagickFalse;
9305           if (attribute_flag[0] != 0)
9306             {
9307               flags=ParseGeometry(argument_list[0].string_reference,
9308                 &geometry_info);
9309               cluster_threshold=geometry_info.rho;
9310               if (flags & SigmaValue)
9311                 smoothing_threshold=geometry_info.sigma;
9312             }
9313           if (attribute_flag[1] != 0)
9314             cluster_threshold=argument_list[1].real_reference;
9315           if (attribute_flag[2] != 0)
9316             smoothing_threshold=argument_list[2].real_reference;
9317           if (attribute_flag[3] != 0)
9318             colorspace=(ColorspaceType) argument_list[3].integer_reference;
9319           if (attribute_flag[4] != 0)
9320             verbose=argument_list[4].integer_reference != 0 ?
9321               MagickTrue : MagickFalse;
9322           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
9323             smoothing_threshold,exception);
9324           break;
9325         }
9326         case 51:  /* Signature */
9327         {
9328           (void) SignatureImage(image,exception);
9329           break;
9330         }
9331         case 52:  /* Solarize */
9332         {
9333           geometry_info.rho=QuantumRange/2.0;
9334           if (attribute_flag[0] != 0)
9335             flags=ParseGeometry(argument_list[0].string_reference,
9336               &geometry_info);
9337           if (attribute_flag[1] != 0)
9338             geometry_info.rho=StringToDoubleInterval(
9339               argument_list[1].string_reference,(double) QuantumRange+1.0);
9340           (void) SolarizeImage(image,geometry_info.rho,exception);
9341           break;
9342         }
9343         case 53:  /* Sync */
9344         {
9345           (void) SyncImage(image,exception);
9346           break;
9347         }
9348         case 54:  /* Texture */
9349         {
9350           if (attribute_flag[0] == 0)
9351             break;
9352           TextureImage(image,argument_list[0].image_reference,exception);
9353           break;
9354         }
9355         case 55:  /* Evalute */
9356         {
9357           MagickEvaluateOperator
9358             op;
9359
9360           op=SetEvaluateOperator;
9361           if (attribute_flag[0] == MagickFalse)
9362             argument_list[0].real_reference=0.0;
9363           if (attribute_flag[1] != MagickFalse)
9364             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
9365           if (attribute_flag[2] != MagickFalse)
9366             channel=(ChannelType) argument_list[2].integer_reference;
9367           channel_mask=SetImageChannelMask(image,channel);
9368           (void) EvaluateImage(image,op,argument_list[0].real_reference,
9369             exception);
9370           (void) SetImageChannelMask(image,channel_mask);
9371           break;
9372         }
9373         case 56:  /* Transparent */
9374         {
9375           double
9376             opacity;
9377
9378           MagickBooleanType
9379             invert;
9380
9381           PixelInfo
9382             target;
9383
9384           (void) QueryColorCompliance("none",AllCompliance,&target,
9385             exception);
9386           if (attribute_flag[0] != 0)
9387             (void) QueryColorCompliance(argument_list[0].string_reference,
9388               AllCompliance,&target,exception);
9389           opacity=TransparentAlpha;
9390           if (attribute_flag[1] != 0)
9391             opacity=StringToDoubleInterval(argument_list[1].string_reference,
9392               (double) QuantumRange+1.0);
9393           if (attribute_flag[2] != 0)
9394             image->fuzz=StringToDoubleInterval(
9395               argument_list[2].string_reference,(double) QuantumRange+1.0);
9396           if (attribute_flag[3] == 0)
9397             argument_list[3].integer_reference=0;
9398           invert=MagickFalse;
9399           if (attribute_flag[3] != 0)
9400             invert=(MagickBooleanType) argument_list[3].integer_reference;
9401           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
9402             invert,exception);
9403           break;
9404         }
9405         case 57:  /* Threshold */
9406         {
9407           double
9408             threshold;
9409
9410           if (attribute_flag[0] == 0)
9411             argument_list[0].string_reference="50%";
9412           if (attribute_flag[1] != 0)
9413             channel=(ChannelType) argument_list[1].integer_reference;
9414           threshold=StringToDoubleInterval(argument_list[0].string_reference,
9415             (double) QuantumRange+1.0);
9416           channel_mask=SetImageChannelMask(image,channel);
9417           (void) BilevelImage(image,threshold,exception);
9418           (void) SetImageChannelMask(image,channel_mask);
9419           break;
9420         }
9421         case 58:  /* Charcoal */
9422         {
9423           if (attribute_flag[0] != 0)
9424             {
9425               flags=ParseGeometry(argument_list[0].string_reference,
9426                 &geometry_info);
9427               if ((flags & SigmaValue) == 0)
9428                 geometry_info.sigma=1.0;
9429             }
9430           if (attribute_flag[1] != 0)
9431             geometry_info.rho=argument_list[1].real_reference;
9432           if (attribute_flag[2] != 0)
9433             geometry_info.sigma=argument_list[2].real_reference;
9434           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9435             exception);
9436           break;
9437         }
9438         case 59:  /* Trim */
9439         {
9440           if (attribute_flag[0] != 0)
9441             image->fuzz=StringToDoubleInterval(
9442               argument_list[0].string_reference,(double) QuantumRange+1.0);
9443           image=TrimImage(image,exception);
9444           break;
9445         }
9446         case 60:  /* Wave */
9447         {
9448           PixelInterpolateMethod
9449             method;
9450
9451           if (attribute_flag[0] != 0)
9452             {
9453               flags=ParseGeometry(argument_list[0].string_reference,
9454                 &geometry_info);
9455               if ((flags & SigmaValue) == 0)
9456                 geometry_info.sigma=1.0;
9457             }
9458           if (attribute_flag[1] != 0)
9459             geometry_info.rho=argument_list[1].real_reference;
9460           if (attribute_flag[2] != 0)
9461             geometry_info.sigma=argument_list[2].real_reference;
9462           method=UndefinedInterpolatePixel;
9463           if (attribute_flag[3] != 0)
9464             method=(PixelInterpolateMethod) argument_list[3].integer_reference;
9465           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9466             method,exception);
9467           break;
9468         }
9469         case 61:  /* Separate */
9470         {
9471           if (attribute_flag[0] != 0)
9472             channel=(ChannelType) argument_list[0].integer_reference;
9473           image=SeparateImage(image,channel,exception);
9474           break;
9475         }
9476         case 63:  /* Stereo */
9477         {
9478           if (attribute_flag[0] == 0)
9479             {
9480               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9481                 PackageName);
9482               goto PerlException;
9483             }
9484           if (attribute_flag[1] != 0)
9485             geometry.x=argument_list[1].integer_reference;
9486           if (attribute_flag[2] != 0)
9487             geometry.y=argument_list[2].integer_reference;
9488           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9489             geometry.x,geometry.y,exception);
9490           break;
9491         }
9492         case 64:  /* Stegano */
9493         {
9494           if (attribute_flag[0] == 0)
9495             {
9496               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9497                 PackageName);
9498               goto PerlException;
9499             }
9500           if (attribute_flag[1] == 0)
9501             argument_list[1].integer_reference=0;
9502           image->offset=argument_list[1].integer_reference;
9503           image=SteganoImage(image,argument_list[0].image_reference,exception);
9504           break;
9505         }
9506         case 65:  /* Deconstruct */
9507         {
9508           image=CompareImagesLayers(image,CompareAnyLayer,exception);
9509           break;
9510         }
9511         case 66:  /* GaussianBlur */
9512         {
9513           if (attribute_flag[0] != 0)
9514             {
9515               flags=ParseGeometry(argument_list[0].string_reference,
9516                 &geometry_info);
9517               if ((flags & SigmaValue) == 0)
9518                 geometry_info.sigma=1.0;
9519             }
9520           if (attribute_flag[1] != 0)
9521             geometry_info.rho=argument_list[1].real_reference;
9522           if (attribute_flag[2] != 0)
9523             geometry_info.sigma=argument_list[2].real_reference;
9524           if (attribute_flag[3] != 0)
9525             channel=(ChannelType) argument_list[3].integer_reference;
9526           channel_mask=SetImageChannelMask(image,channel);
9527           image=GaussianBlurImage(image,geometry_info.rho,geometry_info.sigma,
9528             exception);
9529           if (image != (Image *) NULL)
9530             (void) SetImageChannelMask(image,channel_mask);
9531           break;
9532         }
9533         case 67:  /* Convolve */
9534         {
9535           KernelInfo
9536             *kernel;
9537
9538           kernel=(KernelInfo *) NULL;
9539           if ((attribute_flag[0] == 0) && (attribute_flag[3] == 0))
9540             break;
9541           if (attribute_flag[0] != 0)
9542             {
9543               AV
9544                 *av;
9545
9546               size_t
9547                 order;
9548
9549               kernel=AcquireKernelInfo((const char *) NULL,exception);
9550               if (kernel == (KernelInfo *) NULL)
9551                 break;
9552               av=(AV *) argument_list[0].array_reference;
9553               order=(size_t) sqrt(av_len(av)+1);
9554               kernel->width=order;
9555               kernel->height=order;
9556               kernel->values=(MagickRealType *) AcquireAlignedMemory(order,
9557                 order*sizeof(*kernel->values));
9558               if (kernel->values == (MagickRealType *) NULL)
9559                 {
9560                   kernel=DestroyKernelInfo(kernel);
9561                   ThrowPerlException(exception,ResourceLimitFatalError,
9562                     "MemoryAllocationFailed",PackageName);
9563                   goto PerlException;
9564                 }
9565               for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9566                 kernel->values[j]=(MagickRealType) SvNV(*(av_fetch(av,j,0)));
9567               for ( ; j < (ssize_t) (order*order); j++)
9568                 kernel->values[j]=0.0;
9569             }
9570           if (attribute_flag[1] != 0)
9571             channel=(ChannelType) argument_list[1].integer_reference;
9572           if (attribute_flag[2] != 0)
9573             SetImageArtifact(image,"filter:blur",
9574               argument_list[2].string_reference);
9575           if (attribute_flag[3] != 0)
9576             {
9577               kernel=AcquireKernelInfo(argument_list[3].string_reference,
9578                 exception);
9579               if (kernel == (KernelInfo *) NULL)
9580                 break;
9581             }
9582           channel_mask=SetImageChannelMask(image,channel);
9583           image=ConvolveImage(image,kernel,exception);
9584           if (image != (Image *) NULL)
9585             (void) SetImageChannelMask(image,channel_mask);
9586           kernel=DestroyKernelInfo(kernel);
9587           break;
9588         }
9589         case 68:  /* Profile */
9590         {
9591           const char
9592             *name;
9593
9594           Image
9595             *profile_image;
9596
9597           ImageInfo
9598             *profile_info;
9599
9600           StringInfo
9601             *profile;
9602
9603           name="*";
9604           if (attribute_flag[0] != 0)
9605             name=argument_list[0].string_reference;
9606           if (attribute_flag[2] != 0)
9607             image->rendering_intent=(RenderingIntent)
9608               argument_list[2].integer_reference;
9609           if (attribute_flag[3] != 0)
9610             image->black_point_compensation=
9611               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9612           if (attribute_flag[1] != 0)
9613             {
9614               if (argument_list[1].length == 0)
9615                 {
9616                   /*
9617                     Remove a profile from the image.
9618                   */
9619                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9620                     exception);
9621                   break;
9622                 }
9623               /*
9624                 Associate user supplied profile with the image.
9625               */
9626               profile=AcquireStringInfo(argument_list[1].length);
9627               SetStringInfoDatum(profile,(const unsigned char *)
9628                 argument_list[1].string_reference);
9629               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9630                 (size_t) GetStringInfoLength(profile),exception);
9631               profile=DestroyStringInfo(profile);
9632               break;
9633             }
9634           /*
9635             Associate a profile with the image.
9636           */
9637           profile_info=CloneImageInfo(info ? info->image_info :
9638             (ImageInfo *) NULL);
9639           profile_image=ReadImages(profile_info,name,exception);
9640           if (profile_image == (Image *) NULL)
9641             break;
9642           ResetImageProfileIterator(profile_image);
9643           name=GetNextImageProfile(profile_image);
9644           while (name != (const char *) NULL)
9645           {
9646             const StringInfo
9647               *profile;
9648
9649             profile=GetImageProfile(profile_image,name);
9650             if (profile != (const StringInfo *) NULL)
9651               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9652                 (size_t) GetStringInfoLength(profile),exception);
9653             name=GetNextImageProfile(profile_image);
9654           }
9655           profile_image=DestroyImage(profile_image);
9656           profile_info=DestroyImageInfo(profile_info);
9657           break;
9658         }
9659         case 69:  /* UnsharpMask */
9660         {
9661           if (attribute_flag[0] != 0)
9662             {
9663               flags=ParseGeometry(argument_list[0].string_reference,
9664                 &geometry_info);
9665               if ((flags & SigmaValue) == 0)
9666                 geometry_info.sigma=1.0;
9667               if ((flags & XiValue) == 0)
9668                 geometry_info.xi=1.0;
9669               if ((flags & PsiValue) == 0)
9670                 geometry_info.psi=0.5;
9671             }
9672           if (attribute_flag[1] != 0)
9673             geometry_info.rho=argument_list[1].real_reference;
9674           if (attribute_flag[2] != 0)
9675             geometry_info.sigma=argument_list[2].real_reference;
9676           if (attribute_flag[3] != 0)
9677             geometry_info.xi=argument_list[3].real_reference;
9678           if (attribute_flag[4] != 0)
9679             geometry_info.psi=argument_list[4].real_reference;
9680           if (attribute_flag[5] != 0)
9681             channel=(ChannelType) argument_list[5].integer_reference;
9682           channel_mask=SetImageChannelMask(image,channel);
9683           image=UnsharpMaskImage(image,geometry_info.rho,geometry_info.sigma,
9684             geometry_info.xi,geometry_info.psi,exception);
9685           if (image != (Image *) NULL)
9686             (void) SetImageChannelMask(image,channel_mask);
9687           break;
9688         }
9689         case 70:  /* MotionBlur */
9690         {
9691           if (attribute_flag[0] != 0)
9692             {
9693               flags=ParseGeometry(argument_list[0].string_reference,
9694                 &geometry_info);
9695               if ((flags & SigmaValue) == 0)
9696                 geometry_info.sigma=1.0;
9697               if ((flags & XiValue) == 0)
9698                 geometry_info.xi=1.0;
9699             }
9700           if (attribute_flag[1] != 0)
9701             geometry_info.rho=argument_list[1].real_reference;
9702           if (attribute_flag[2] != 0)
9703             geometry_info.sigma=argument_list[2].real_reference;
9704           if (attribute_flag[3] != 0)
9705             geometry_info.xi=argument_list[3].real_reference;
9706           if (attribute_flag[4] != 0)
9707             channel=(ChannelType) argument_list[4].integer_reference;
9708           channel_mask=SetImageChannelMask(image,channel);
9709           image=MotionBlurImage(image,geometry_info.rho,geometry_info.sigma,
9710             geometry_info.xi,exception);
9711           if (image != (Image *) NULL)
9712             (void) SetImageChannelMask(image,channel_mask);
9713           break;
9714         }
9715         case 71:  /* OrderedDither */
9716         {
9717           if (attribute_flag[0] == 0)
9718             argument_list[0].string_reference="o8x8";
9719           if (attribute_flag[1] != 0)
9720             channel=(ChannelType) argument_list[1].integer_reference;
9721           channel_mask=SetImageChannelMask(image,channel);
9722           (void) OrderedPosterizeImage(image,argument_list[0].string_reference,
9723             exception);
9724           (void) SetImageChannelMask(image,channel_mask);
9725           break;
9726         }
9727         case 72:  /* Shave */
9728         {
9729           if (attribute_flag[0] != 0)
9730             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9731               &geometry,exception);
9732           if (attribute_flag[1] != 0)
9733             geometry.width=argument_list[1].integer_reference;
9734           if (attribute_flag[2] != 0)
9735             geometry.height=argument_list[2].integer_reference;
9736           image=ShaveImage(image,&geometry,exception);
9737           break;
9738         }
9739         case 73:  /* Level */
9740         {
9741           double
9742             black_point,
9743             gamma,
9744             white_point;
9745
9746           black_point=0.0;
9747           white_point=(double) image->columns*image->rows;
9748           gamma=1.0;
9749           if (attribute_flag[0] != 0)
9750             {
9751               flags=ParseGeometry(argument_list[0].string_reference,
9752                 &geometry_info);
9753               black_point=geometry_info.rho;
9754               if ((flags & SigmaValue) != 0)
9755                 white_point=geometry_info.sigma;
9756               if ((flags & XiValue) != 0)
9757                 gamma=geometry_info.xi;
9758               if ((flags & PercentValue) != 0)
9759                 {
9760                   black_point*=(double) (QuantumRange/100.0);
9761                   white_point*=(double) (QuantumRange/100.0);
9762                 }
9763               if ((flags & SigmaValue) == 0)
9764                 white_point=(double) QuantumRange-black_point;
9765             }
9766           if (attribute_flag[1] != 0)
9767             black_point=argument_list[1].real_reference;
9768           if (attribute_flag[2] != 0)
9769             white_point=argument_list[2].real_reference;
9770           if (attribute_flag[3] != 0)
9771             gamma=argument_list[3].real_reference;
9772           if (attribute_flag[4] != 0)
9773             channel=(ChannelType) argument_list[4].integer_reference;
9774           if (attribute_flag[5] != 0)
9775             {
9776               argument_list[0].real_reference=argument_list[5].real_reference;
9777               attribute_flag[0]=attribute_flag[5];
9778             }
9779           channel_mask=SetImageChannelMask(image,channel);
9780           (void) LevelImage(image,black_point,white_point,gamma,exception);
9781           (void) SetImageChannelMask(image,channel_mask);
9782           break;
9783         }
9784         case 74:  /* Clip */
9785         {
9786           if (attribute_flag[0] == 0)
9787             argument_list[0].string_reference="#1";
9788           if (attribute_flag[1] == 0)
9789             argument_list[1].integer_reference=MagickTrue;
9790           (void) ClipImagePath(image,argument_list[0].string_reference,
9791             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse,
9792             exception);
9793           break;
9794         }
9795         case 75:  /* AffineTransform */
9796         {
9797           DrawInfo
9798             *draw_info;
9799
9800           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9801             (DrawInfo *) NULL);
9802           if (attribute_flag[0] != 0)
9803             {
9804               AV
9805                 *av;
9806
9807               av=(AV *) argument_list[0].array_reference;
9808               if ((av_len(av) != 3) && (av_len(av) != 5))
9809                 {
9810                   ThrowPerlException(exception,OptionError,
9811                     "affine matrix must have 4 or 6 elements",PackageName);
9812                   goto PerlException;
9813                 }
9814               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9815               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9816               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9817               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9818               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9819                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9820                 {
9821                   ThrowPerlException(exception,OptionError,
9822                     "affine matrix is singular",PackageName);
9823                    goto PerlException;
9824                 }
9825               if (av_len(av) == 5)
9826                 {
9827                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9828                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9829                 }
9830             }
9831           for (j=1; j < 6; j++)
9832           {
9833             if (attribute_flag[j] == 0)
9834               continue;
9835             value=argument_list[j].string_reference;
9836             angle=argument_list[j].real_reference;
9837             current=draw_info->affine;
9838             GetAffineMatrix(&affine);
9839             switch (j)
9840             {
9841               case 1:
9842               {
9843                 /*
9844                   Translate.
9845                 */
9846                 flags=ParseGeometry(value,&geometry_info);
9847                 affine.tx=geometry_info.xi;
9848                 affine.ty=geometry_info.psi;
9849                 if ((flags & PsiValue) == 0)
9850                   affine.ty=affine.tx;
9851                 break;
9852               }
9853               case 2:
9854               {
9855                 /*
9856                   Scale.
9857                 */
9858                 flags=ParseGeometry(value,&geometry_info);
9859                 affine.sx=geometry_info.rho;
9860                 affine.sy=geometry_info.sigma;
9861                 if ((flags & SigmaValue) == 0)
9862                   affine.sy=affine.sx;
9863                 break;
9864               }
9865               case 3:
9866               {
9867                 /*
9868                   Rotate.
9869                 */
9870                 if (angle == 0.0)
9871                   break;
9872                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9873                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9874                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9875                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9876                 break;
9877               }
9878               case 4:
9879               {
9880                 /*
9881                   SkewX.
9882                 */
9883                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9884                 break;
9885               }
9886               case 5:
9887               {
9888                 /*
9889                   SkewY.
9890                 */
9891                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9892                 break;
9893               }
9894             }
9895             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9896             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9897             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9898             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9899             draw_info->affine.tx=
9900               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9901             draw_info->affine.ty=
9902               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9903           }
9904           if (attribute_flag[6] != 0)
9905             image->interpolate=(PixelInterpolateMethod)
9906               argument_list[6].integer_reference;
9907           if (attribute_flag[7] != 0)
9908             QueryColorCompliance(argument_list[7].string_reference,
9909               AllCompliance,&image->background_color,exception);
9910           image=AffineTransformImage(image,&draw_info->affine,exception);
9911           draw_info=DestroyDrawInfo(draw_info);
9912           break;
9913         }
9914         case 76:  /* Difference */
9915         {
9916           if (attribute_flag[0] == 0)
9917             {
9918               ThrowPerlException(exception,OptionError,
9919                 "ReferenceImageRequired",PackageName);
9920               goto PerlException;
9921             }
9922           if (attribute_flag[1] != 0)
9923             image->fuzz=StringToDoubleInterval(
9924               argument_list[1].string_reference,(double) QuantumRange+1.0);
9925           (void) IsImagesEqual(image,argument_list[0].image_reference,
9926             exception);
9927           break;
9928         }
9929         case 77:  /* AdaptiveThreshold */
9930         {
9931           if (attribute_flag[0] != 0)
9932             {
9933               flags=ParseGeometry(argument_list[0].string_reference,
9934                 &geometry_info);
9935               if ((flags & PercentValue) != 0)
9936                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9937             }
9938           if (attribute_flag[1] != 0)
9939             geometry_info.rho=argument_list[1].integer_reference;
9940           if (attribute_flag[2] != 0)
9941             geometry_info.sigma=argument_list[2].integer_reference;
9942           if (attribute_flag[3] != 0)
9943             geometry_info.xi=argument_list[3].integer_reference;;
9944           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9945             (size_t) geometry_info.sigma,(double) geometry_info.xi,exception);
9946           break;
9947         }
9948         case 78:  /* Resample */
9949         {
9950           size_t
9951             height,
9952             width;
9953
9954           if (attribute_flag[0] != 0)
9955             {
9956               flags=ParseGeometry(argument_list[0].string_reference,
9957                 &geometry_info);
9958               if ((flags & SigmaValue) == 0)
9959                 geometry_info.sigma=geometry_info.rho;
9960             }
9961           if (attribute_flag[1] != 0)
9962             geometry_info.rho=argument_list[1].real_reference;
9963           if (attribute_flag[2] != 0)
9964             geometry_info.sigma=argument_list[2].real_reference;
9965           if (attribute_flag[3] == 0)
9966             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9967           if (attribute_flag[4] == 0)
9968             SetImageArtifact(image,"filter:support",
9969               argument_list[4].string_reference);
9970           width=(size_t) (geometry_info.rho*image->columns/
9971             (image->resolution.x == 0.0 ? 72.0 : image->resolution.x)+0.5);
9972           height=(size_t) (geometry_info.sigma*image->rows/
9973             (image->resolution.y == 0.0 ? 72.0 : image->resolution.y)+0.5);
9974           image=ResizeImage(image,width,height,(FilterTypes)
9975             argument_list[3].integer_reference,exception);
9976           if (image != (Image *) NULL)
9977             {
9978               image->resolution.x=geometry_info.rho;
9979               image->resolution.y=geometry_info.sigma;
9980             }
9981           break;
9982         }
9983         case 79:  /* Describe */
9984         {
9985           if (attribute_flag[0] == 0)
9986             argument_list[0].file_reference=(FILE *) NULL;
9987           if (attribute_flag[1] != 0)
9988             (void) SetImageArtifact(image,"identify:features",
9989               argument_list[1].string_reference);
9990           (void) IdentifyImage(image,argument_list[0].file_reference,
9991             MagickTrue,exception);
9992           break;
9993         }
9994         case 80:  /* BlackThreshold */
9995         {
9996           if (attribute_flag[0] == 0)
9997             argument_list[0].string_reference="50%";
9998           if (attribute_flag[2] != 0)
9999             channel=(ChannelType) argument_list[2].integer_reference;
10000           channel_mask=SetImageChannelMask(image,channel);
10001           BlackThresholdImage(image,argument_list[0].string_reference,
10002             exception);
10003           (void) SetImageChannelMask(image,channel_mask);
10004           break;
10005         }
10006         case 81:  /* WhiteThreshold */
10007         {
10008           if (attribute_flag[0] == 0)
10009             argument_list[0].string_reference="50%";
10010           if (attribute_flag[2] != 0)
10011             channel=(ChannelType) argument_list[2].integer_reference;
10012           channel_mask=SetImageChannelMask(image,channel);
10013           WhiteThresholdImage(image,argument_list[0].string_reference,
10014             exception);
10015           (void) SetImageChannelMask(image,channel_mask);
10016           break;
10017         }
10018         case 82:  /* RotationalBlur */
10019         {
10020           if (attribute_flag[0] != 0)
10021             {
10022               flags=ParseGeometry(argument_list[0].string_reference,
10023                 &geometry_info);
10024             }
10025           if (attribute_flag[1] != 0)
10026             geometry_info.rho=argument_list[1].real_reference;
10027           if (attribute_flag[2] != 0)
10028             channel=(ChannelType) argument_list[2].integer_reference;
10029           channel_mask=SetImageChannelMask(image,channel);
10030           image=RotationalBlurImage(image,geometry_info.rho,exception);
10031           if (image != (Image *) NULL)
10032             (void) SetImageChannelMask(image,channel_mask);
10033           break;
10034         }
10035         case 83:  /* Thumbnail */
10036         {
10037           if (attribute_flag[0] != 0)
10038             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10039               &geometry,exception);
10040           if (attribute_flag[1] != 0)
10041             geometry.width=argument_list[1].integer_reference;
10042           if (attribute_flag[2] != 0)
10043             geometry.height=argument_list[2].integer_reference;
10044           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
10045           break;
10046         }
10047         case 84:  /* Strip */
10048         {
10049           (void) StripImage(image,exception);
10050           break;
10051         }
10052         case 85:  /* Tint */
10053         {
10054           PixelInfo
10055             tint;
10056
10057           GetPixelInfo(image,&tint);
10058           if (attribute_flag[0] != 0)
10059             (void) QueryColorCompliance(argument_list[0].string_reference,
10060               AllCompliance,&tint,exception);
10061           if (attribute_flag[1] == 0)
10062             argument_list[1].string_reference="100";
10063           image=TintImage(image,argument_list[1].string_reference,&tint,
10064             exception);
10065           break;
10066         }
10067         case 86:  /* Channel */
10068         {
10069           if (attribute_flag[0] != 0)
10070             channel=(ChannelType) argument_list[0].integer_reference;
10071           image=SeparateImage(image,channel,exception);
10072           break;
10073         }
10074         case 87:  /* Splice */
10075         {
10076           if (attribute_flag[7] != 0)
10077             image->gravity=(GravityType) argument_list[7].integer_reference;
10078           if (attribute_flag[0] != 0)
10079             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
10080               &geometry,exception);
10081           if (attribute_flag[1] != 0)
10082             geometry.width=argument_list[1].integer_reference;
10083           if (attribute_flag[2] != 0)
10084             geometry.height=argument_list[2].integer_reference;
10085           if (attribute_flag[3] != 0)
10086             geometry.x=argument_list[3].integer_reference;
10087           if (attribute_flag[4] != 0)
10088             geometry.y=argument_list[4].integer_reference;
10089           if (attribute_flag[5] != 0)
10090             image->fuzz=StringToDoubleInterval(
10091               argument_list[5].string_reference,(double) QuantumRange+1.0);
10092           if (attribute_flag[6] != 0)
10093             (void) QueryColorCompliance(argument_list[6].string_reference,
10094               AllCompliance,&image->background_color,exception);
10095           image=SpliceImage(image,&geometry,exception);
10096           break;
10097         }
10098         case 88:  /* Posterize */
10099         {
10100           if (attribute_flag[0] == 0)
10101             argument_list[0].integer_reference=3;
10102           if (attribute_flag[1] == 0)
10103             argument_list[1].integer_reference=0;
10104           (void) PosterizeImage(image,argument_list[0].integer_reference,
10105             argument_list[1].integer_reference ? RiemersmaDitherMethod :
10106             NoDitherMethod,exception);
10107           break;
10108         }
10109         case 89:  /* Shadow */
10110         {
10111           if (attribute_flag[0] != 0)
10112             {
10113               flags=ParseGeometry(argument_list[0].string_reference,
10114                 &geometry_info);
10115               if ((flags & SigmaValue) == 0)
10116                 geometry_info.sigma=1.0;
10117               if ((flags & XiValue) == 0)
10118                 geometry_info.xi=4.0;
10119               if ((flags & PsiValue) == 0)
10120                 geometry_info.psi=4.0;
10121             }
10122           if (attribute_flag[1] != 0)
10123             geometry_info.rho=argument_list[1].real_reference;
10124           if (attribute_flag[2] != 0)
10125             geometry_info.sigma=argument_list[2].real_reference;
10126           if (attribute_flag[3] != 0)
10127             geometry_info.xi=argument_list[3].integer_reference;
10128           if (attribute_flag[4] != 0)
10129             geometry_info.psi=argument_list[4].integer_reference;
10130           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
10131             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10132             ceil(geometry_info.psi-0.5),exception);
10133           break;
10134         }
10135         case 90:  /* Identify */
10136         {
10137           if (attribute_flag[0] == 0)
10138             argument_list[0].file_reference=(FILE *) NULL;
10139           if (attribute_flag[1] != 0)
10140             (void) SetImageArtifact(image,"identify:features",
10141               argument_list[1].string_reference);
10142           if ((attribute_flag[2] != 0) &&
10143               (argument_list[2].integer_reference != 0))
10144             (void) SetImageArtifact(image,"identify:unique","true");
10145           (void) IdentifyImage(image,argument_list[0].file_reference,
10146             MagickTrue,exception);
10147           break;
10148         }
10149         case 91:  /* SepiaTone */
10150         {
10151           if (attribute_flag[0] == 0)
10152             argument_list[0].real_reference=80.0*QuantumRange/100.0;
10153           image=SepiaToneImage(image,argument_list[0].real_reference,
10154             exception);
10155           break;
10156         }
10157         case 92:  /* SigmoidalContrast */
10158         {
10159           MagickBooleanType
10160             sharpen;
10161
10162           if (attribute_flag[0] != 0)
10163             {
10164               flags=ParseGeometry(argument_list[0].string_reference,
10165                 &geometry_info);
10166               if ((flags & SigmaValue) == 0)
10167                 geometry_info.sigma=QuantumRange/2.0;
10168               if ((flags & PercentValue) != 0)
10169                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
10170             }
10171           if (attribute_flag[1] != 0)
10172             geometry_info.rho=argument_list[1].real_reference;
10173           if (attribute_flag[2] != 0)
10174             geometry_info.sigma=argument_list[2].real_reference;
10175           if (attribute_flag[3] != 0)
10176             channel=(ChannelType) argument_list[3].integer_reference;
10177           sharpen=MagickTrue;
10178           if (attribute_flag[4] != 0)
10179             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
10180               MagickFalse;
10181           channel_mask=SetImageChannelMask(image,channel);
10182           (void) SigmoidalContrastImage(image,sharpen,geometry_info.rho,
10183             geometry_info.sigma,exception);
10184           (void) SetImageChannelMask(image,channel_mask);
10185           break;
10186         }
10187         case 93:  /* Extent */
10188         {
10189           if (attribute_flag[7] != 0)
10190             image->gravity=(GravityType) argument_list[7].integer_reference;
10191           if (attribute_flag[0] != 0)
10192             {
10193               int
10194                 flags;
10195
10196               flags=ParseGravityGeometry(image,
10197                 argument_list[0].string_reference,&geometry,exception);
10198               (void) flags;
10199               if (geometry.width == 0)
10200                 geometry.width=image->columns;
10201               if (geometry.height == 0)
10202                 geometry.height=image->rows;
10203             }
10204           if (attribute_flag[1] != 0)
10205             geometry.width=argument_list[1].integer_reference;
10206           if (attribute_flag[2] != 0)
10207             geometry.height=argument_list[2].integer_reference;
10208           if (attribute_flag[3] != 0)
10209             geometry.x=argument_list[3].integer_reference;
10210           if (attribute_flag[4] != 0)
10211             geometry.y=argument_list[4].integer_reference;
10212           if (attribute_flag[5] != 0)
10213             image->fuzz=StringToDoubleInterval(
10214               argument_list[5].string_reference,(double) QuantumRange+1.0);
10215           if (attribute_flag[6] != 0)
10216             (void) QueryColorCompliance(argument_list[6].string_reference,
10217               AllCompliance,&image->background_color,exception);
10218           image=ExtentImage(image,&geometry,exception);
10219           break;
10220         }
10221         case 94:  /* Vignette */
10222         {
10223           if (attribute_flag[0] != 0)
10224             {
10225               flags=ParseGeometry(argument_list[0].string_reference,
10226                 &geometry_info);
10227               if ((flags & SigmaValue) == 0)
10228                 geometry_info.sigma=1.0;
10229               if ((flags & XiValue) == 0)
10230                 geometry_info.xi=0.1*image->columns;
10231               if ((flags & PsiValue) == 0)
10232                 geometry_info.psi=0.1*image->rows;
10233             }
10234           if (attribute_flag[1] != 0)
10235             geometry_info.rho=argument_list[1].real_reference;
10236           if (attribute_flag[2] != 0)
10237             geometry_info.sigma=argument_list[2].real_reference;
10238           if (attribute_flag[3] != 0)
10239             geometry_info.xi=argument_list[3].integer_reference;
10240           if (attribute_flag[4] != 0)
10241             geometry_info.psi=argument_list[4].integer_reference;
10242           if (attribute_flag[5] != 0)
10243             (void) QueryColorCompliance(argument_list[5].string_reference,
10244               AllCompliance,&image->background_color,exception);
10245           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
10246             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t)
10247             ceil(geometry_info.psi-0.5),exception);
10248           break;
10249         }
10250         case 95:  /* ContrastStretch */
10251         {
10252           double
10253             black_point,
10254             white_point;
10255
10256           black_point=0.0;
10257           white_point=(double) image->columns*image->rows;
10258           if (attribute_flag[0] != 0)
10259             {
10260               flags=ParseGeometry(argument_list[0].string_reference,
10261                 &geometry_info);
10262               black_point=geometry_info.rho;
10263               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
10264                 black_point;
10265               if ((flags & PercentValue) != 0)
10266                 {
10267                   black_point*=(double) image->columns*image->rows/100.0;
10268                   white_point*=(double) image->columns*image->rows/100.0;
10269                 }
10270               white_point=(double) image->columns*image->rows-
10271                 white_point;
10272             }
10273           if (attribute_flag[1] != 0)
10274             black_point=argument_list[1].real_reference;
10275           if (attribute_flag[2] != 0)
10276             white_point=argument_list[2].real_reference;
10277           if (attribute_flag[4] != 0)
10278             channel=(ChannelType) argument_list[4].integer_reference;
10279           channel_mask=SetImageChannelMask(image,channel);
10280           (void) ContrastStretchImage(image,black_point,white_point,exception);
10281           (void) SetImageChannelMask(image,channel_mask);
10282           break;
10283         }
10284         case 96:  /* Sans0 */
10285         {
10286           break;
10287         }
10288         case 97:  /* Sans1 */
10289         {
10290           break;
10291         }
10292         case 98:  /* AdaptiveSharpen */
10293         {
10294           if (attribute_flag[0] != 0)
10295             {
10296               flags=ParseGeometry(argument_list[0].string_reference,
10297                 &geometry_info);
10298               if ((flags & SigmaValue) == 0)
10299                 geometry_info.sigma=1.0;
10300               if ((flags & XiValue) == 0)
10301                 geometry_info.xi=0.0;
10302             }
10303           if (attribute_flag[1] != 0)
10304             geometry_info.rho=argument_list[1].real_reference;
10305           if (attribute_flag[2] != 0)
10306             geometry_info.sigma=argument_list[2].real_reference;
10307           if (attribute_flag[3] != 0)
10308             geometry_info.xi=argument_list[3].real_reference;
10309           if (attribute_flag[4] != 0)
10310             channel=(ChannelType) argument_list[4].integer_reference;
10311           channel_mask=SetImageChannelMask(image,channel);
10312           image=AdaptiveSharpenImage(image,geometry_info.rho,
10313             geometry_info.sigma,exception);
10314           if (image != (Image *) NULL)
10315             (void) SetImageChannelMask(image,channel_mask);
10316           break;
10317         }
10318         case 99:  /* Transpose */
10319         {
10320           image=TransposeImage(image,exception);
10321           break;
10322         }
10323         case 100:  /* Tranverse */
10324         {
10325           image=TransverseImage(image,exception);
10326           break;
10327         }
10328         case 101:  /* AutoOrient */
10329         {
10330           image=AutoOrientImage(image,image->orientation,exception);
10331           break;
10332         }
10333         case 102:  /* AdaptiveBlur */
10334         {
10335           if (attribute_flag[0] != 0)
10336             {
10337               flags=ParseGeometry(argument_list[0].string_reference,
10338                 &geometry_info);
10339               if ((flags & SigmaValue) == 0)
10340                 geometry_info.sigma=1.0;
10341               if ((flags & XiValue) == 0)
10342                 geometry_info.xi=0.0;
10343             }
10344           if (attribute_flag[1] != 0)
10345             geometry_info.rho=argument_list[1].real_reference;
10346           if (attribute_flag[2] != 0)
10347             geometry_info.sigma=argument_list[2].real_reference;
10348           if (attribute_flag[3] != 0)
10349             channel=(ChannelType) argument_list[3].integer_reference;
10350           channel_mask=SetImageChannelMask(image,channel);
10351           image=AdaptiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10352             exception);
10353           if (image != (Image *) NULL)
10354             (void) SetImageChannelMask(image,channel_mask);
10355           break;
10356         }
10357         case 103:  /* Sketch */
10358         {
10359           if (attribute_flag[0] != 0)
10360             {
10361               flags=ParseGeometry(argument_list[0].string_reference,
10362                 &geometry_info);
10363               if ((flags & SigmaValue) == 0)
10364                 geometry_info.sigma=1.0;
10365               if ((flags & XiValue) == 0)
10366                 geometry_info.xi=1.0;
10367             }
10368           if (attribute_flag[1] != 0)
10369             geometry_info.rho=argument_list[1].real_reference;
10370           if (attribute_flag[2] != 0)
10371             geometry_info.sigma=argument_list[2].real_reference;
10372           if (attribute_flag[3] != 0)
10373             geometry_info.xi=argument_list[3].real_reference;
10374           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
10375             geometry_info.xi,exception);
10376           break;
10377         }
10378         case 104:  /* UniqueColors */
10379         {
10380           image=UniqueImageColors(image,exception);
10381           break;
10382         }
10383         case 105:  /* AdaptiveResize */
10384         {
10385           if (attribute_flag[0] != 0)
10386             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10387               &geometry,exception);
10388           if (attribute_flag[1] != 0)
10389             geometry.width=argument_list[1].integer_reference;
10390           if (attribute_flag[2] != 0)
10391             geometry.height=argument_list[2].integer_reference;
10392           if (attribute_flag[3] != 0)
10393             image->filter=(FilterTypes) argument_list[4].integer_reference;
10394           if (attribute_flag[4] != 0)
10395             SetImageArtifact(image,"filter:support",
10396               argument_list[4].string_reference);
10397           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
10398             exception);
10399           break;
10400         }
10401         case 106:  /* ClipMask */
10402         {
10403           Image
10404             *mask_image;
10405
10406           if (attribute_flag[0] == 0)
10407             {
10408               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10409                 PackageName);
10410               goto PerlException;
10411             }
10412           mask_image=CloneImage(argument_list[0].image_reference,0,0,MagickTrue,
10413             exception);
10414           (void) SetImageMask(image,mask_image,exception);
10415           mask_image=DestroyImage(mask_image);
10416           break;
10417         }
10418         case 107:  /* LinearStretch */
10419         {
10420            double
10421              black_point,
10422              white_point;
10423
10424            black_point=0.0;
10425            white_point=(double) image->columns*image->rows;
10426            if (attribute_flag[0] != 0)
10427              {
10428                flags=ParseGeometry(argument_list[0].string_reference,
10429                  &geometry_info);
10430                if ((flags & SigmaValue) != 0)
10431                   white_point=geometry_info.sigma;
10432                if ((flags & PercentValue) != 0)
10433                  {
10434                    black_point*=(double) image->columns*image->rows/100.0;
10435                    white_point*=(double) image->columns*image->rows/100.0;
10436                  }
10437                if ((flags & SigmaValue) == 0)
10438                  white_point=(double) image->columns*image->rows-black_point;
10439              }
10440           if (attribute_flag[1] != 0)
10441             black_point=argument_list[1].real_reference;
10442           if (attribute_flag[2] != 0)
10443             white_point=argument_list[2].real_reference;
10444           (void) LinearStretchImage(image,black_point,white_point,exception);
10445           break;
10446         }
10447         case 108:  /* ColorMatrix */
10448         {
10449           AV
10450             *av;
10451
10452           double
10453             *color_matrix;
10454
10455           KernelInfo
10456             *kernel_info;
10457
10458           size_t
10459             order;
10460
10461           if (attribute_flag[0] == 0)
10462             break;
10463           av=(AV *) argument_list[0].array_reference;
10464           order=(size_t) sqrt(av_len(av)+1);
10465           color_matrix=(double *) AcquireQuantumMemory(order,order*
10466             sizeof(*color_matrix));
10467           if (color_matrix == (double *) NULL)
10468             {
10469               ThrowPerlException(exception,ResourceLimitFatalError,
10470                 "MemoryAllocationFailed",PackageName);
10471               goto PerlException;
10472            }
10473           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10474             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10475           for ( ; j < (ssize_t) (order*order); j++)
10476             color_matrix[j]=0.0;
10477           kernel_info=AcquireKernelInfo((const char *) NULL,exception);
10478           if (kernel_info == (KernelInfo *) NULL)
10479             break;
10480           kernel_info->width=order;
10481           kernel_info->height=order;
10482           kernel_info->values=(MagickRealType *) AcquireAlignedMemory(order,
10483             order*sizeof(*kernel_info->values));
10484           if (kernel_info->values != (MagickRealType *) NULL)
10485             {
10486               for (i=0; i < (ssize_t) (order*order); i++)
10487                 kernel_info->values[i]=(MagickRealType) color_matrix[i];
10488               image=ColorMatrixImage(image,kernel_info,exception);
10489             }
10490           kernel_info=DestroyKernelInfo(kernel_info);
10491           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10492           break;
10493         }
10494         case 109:  /* Mask */
10495         {
10496           Image
10497             *mask_image;
10498
10499           if (attribute_flag[0] == 0)
10500             {
10501               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10502                 PackageName);
10503               goto PerlException;
10504             }
10505           mask_image=CloneImage(argument_list[0].image_reference,0,0,
10506             MagickTrue,exception);
10507           (void) SetImageMask(image,mask_image,exception);
10508           mask_image=DestroyImage(mask_image);
10509           break;
10510         }
10511         case 110:  /* Polaroid */
10512         {
10513           char
10514             *caption;
10515
10516           DrawInfo
10517             *draw_info;
10518
10519           double
10520             angle;
10521
10522           PixelInterpolateMethod
10523             method;
10524
10525           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10526             (DrawInfo *) NULL);
10527           caption=(char *) NULL;
10528           if (attribute_flag[0] != 0)
10529             caption=InterpretImageProperties(info ? info->image_info :
10530               (ImageInfo *) NULL,image,argument_list[0].string_reference,
10531               exception);
10532           angle=0.0;
10533           if (attribute_flag[1] != 0)
10534             angle=argument_list[1].real_reference;
10535           if (attribute_flag[2] != 0)
10536             (void) CloneString(&draw_info->font,
10537               argument_list[2].string_reference);
10538           if (attribute_flag[3] != 0)
10539             (void) QueryColorCompliance(argument_list[3].string_reference,
10540               AllCompliance,&draw_info->stroke,exception);
10541           if (attribute_flag[4] != 0)
10542             (void) QueryColorCompliance(argument_list[4].string_reference,
10543               AllCompliance,&draw_info->fill,exception);
10544           if (attribute_flag[5] != 0)
10545             draw_info->stroke_width=argument_list[5].real_reference;
10546           if (attribute_flag[6] != 0)
10547             draw_info->pointsize=argument_list[6].real_reference;
10548           if (attribute_flag[7] != 0)
10549             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10550           if (attribute_flag[8] != 0)
10551             (void) QueryColorCompliance(argument_list[8].string_reference,
10552               AllCompliance,&image->background_color,exception);
10553           method=UndefinedInterpolatePixel;
10554           if (attribute_flag[9] != 0)
10555             method=(PixelInterpolateMethod) argument_list[9].integer_reference;
10556           image=PolaroidImage(image,draw_info,caption,angle,method,exception);
10557           draw_info=DestroyDrawInfo(draw_info);
10558           if (caption != (char *) NULL)
10559             caption=DestroyString(caption);
10560           break;
10561         }
10562         case 111:  /* FloodfillPaint */
10563         {
10564           DrawInfo
10565             *draw_info;
10566
10567           MagickBooleanType
10568             invert;
10569
10570           PixelInfo
10571             target;
10572
10573           draw_info=CloneDrawInfo(info ? info->image_info :
10574             (ImageInfo *) NULL,(DrawInfo *) NULL);
10575           if (attribute_flag[0] != 0)
10576             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10577               &geometry,exception);
10578           if (attribute_flag[1] != 0)
10579             geometry.x=argument_list[1].integer_reference;
10580           if (attribute_flag[2] != 0)
10581             geometry.y=argument_list[2].integer_reference;
10582           if (attribute_flag[3] != 0)
10583             (void) QueryColorCompliance(argument_list[3].string_reference,
10584               AllCompliance,&draw_info->fill,exception);
10585           (void) GetOneVirtualPixelInfo(image,UndefinedVirtualPixelMethod,
10586             geometry.x,geometry.y,&target,exception);
10587           if (attribute_flag[4] != 0)
10588             QueryColorCompliance(argument_list[4].string_reference,
10589               AllCompliance,&target,exception);
10590           if (attribute_flag[5] != 0)
10591             image->fuzz=StringToDoubleInterval(
10592               argument_list[5].string_reference,(double) QuantumRange+1.0);
10593           if (attribute_flag[6] != 0)
10594             channel=(ChannelType) argument_list[6].integer_reference;
10595           invert=MagickFalse;
10596           if (attribute_flag[7] != 0)
10597             invert=(MagickBooleanType) argument_list[7].integer_reference;
10598           channel_mask=SetImageChannelMask(image,channel);
10599           (void) FloodfillPaintImage(image,draw_info,&target,geometry.x,
10600             geometry.y,invert,exception);
10601           (void) SetImageChannelMask(image,channel_mask);
10602           draw_info=DestroyDrawInfo(draw_info);
10603           break;
10604         }
10605         case 112:  /* Distort */
10606         {
10607           AV
10608             *av;
10609
10610           double
10611             *coordinates;
10612
10613           DistortImageMethod
10614             method;
10615
10616           size_t
10617             number_coordinates;
10618
10619           VirtualPixelMethod
10620             virtual_pixel;
10621
10622           if (attribute_flag[0] == 0)
10623             break;
10624           method=UndefinedDistortion;
10625           if (attribute_flag[1] != 0)
10626             method=(DistortImageMethod) argument_list[1].integer_reference;
10627           av=(AV *) argument_list[0].array_reference;
10628           number_coordinates=(size_t) av_len(av)+1;
10629           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10630             sizeof(*coordinates));
10631           if (coordinates == (double *) NULL)
10632             {
10633               ThrowPerlException(exception,ResourceLimitFatalError,
10634                 "MemoryAllocationFailed",PackageName);
10635               goto PerlException;
10636             }
10637           for (j=0; j < (ssize_t) number_coordinates; j++)
10638             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10639           virtual_pixel=UndefinedVirtualPixelMethod;
10640           if (attribute_flag[2] != 0)
10641             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10642               argument_list[2].integer_reference,exception);
10643           image=DistortImage(image,method,number_coordinates,coordinates,
10644             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10645             exception);
10646           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10647             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10648               exception);
10649           coordinates=(double *) RelinquishMagickMemory(coordinates);
10650           break;
10651         }
10652         case 113:  /* Clut */
10653         {
10654           PixelInterpolateMethod
10655             method;
10656
10657           if (attribute_flag[0] == 0)
10658             {
10659               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10660                 PackageName);
10661               goto PerlException;
10662             }
10663           method=UndefinedInterpolatePixel;
10664           if (attribute_flag[1] != 0)
10665             method=(PixelInterpolateMethod) argument_list[1].integer_reference;
10666           if (attribute_flag[2] != 0)
10667             channel=(ChannelType) argument_list[2].integer_reference;
10668           channel_mask=SetImageChannelMask(image,channel);
10669           (void) ClutImage(image,argument_list[0].image_reference,method,
10670             exception);
10671           (void) SetImageChannelMask(image,channel_mask);
10672           break;
10673         }
10674         case 114:  /* LiquidRescale */
10675         {
10676           if (attribute_flag[0] != 0)
10677             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10678               &geometry,exception);
10679           if (attribute_flag[1] != 0)
10680             geometry.width=argument_list[1].integer_reference;
10681           if (attribute_flag[2] != 0)
10682             geometry.height=argument_list[2].integer_reference;
10683           if (attribute_flag[3] == 0)
10684             argument_list[3].real_reference=1.0;
10685           if (attribute_flag[4] == 0)
10686             argument_list[4].real_reference=0.0;
10687           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10688             argument_list[3].real_reference,argument_list[4].real_reference,
10689             exception);
10690           break;
10691         }
10692         case 115:  /* EncipherImage */
10693         {
10694           (void) EncipherImage(image,argument_list[0].string_reference,
10695             exception);
10696           break;
10697         }
10698         case 116:  /* DecipherImage */
10699         {
10700           (void) DecipherImage(image,argument_list[0].string_reference,
10701             exception);
10702           break;
10703         }
10704         case 117:  /* Deskew */
10705         {
10706           geometry_info.rho=QuantumRange/2.0;
10707           if (attribute_flag[0] != 0)
10708             flags=ParseGeometry(argument_list[0].string_reference,
10709               &geometry_info);
10710           if (attribute_flag[1] != 0)
10711             geometry_info.rho=StringToDoubleInterval(
10712               argument_list[1].string_reference,(double) QuantumRange+1.0);
10713           image=DeskewImage(image,geometry_info.rho,exception);
10714           break;
10715         }
10716         case 118:  /* Remap */
10717         {
10718           QuantizeInfo
10719             *quantize_info;
10720
10721           if (attribute_flag[0] == 0)
10722             {
10723               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10724                 PackageName);
10725               goto PerlException;
10726             }
10727           quantize_info=AcquireQuantizeInfo(info->image_info);
10728           if (attribute_flag[1] != 0)
10729             quantize_info->dither_method=(DitherMethod)
10730               argument_list[1].integer_reference;
10731           (void) RemapImages(quantize_info,image,
10732             argument_list[0].image_reference,exception);
10733           quantize_info=DestroyQuantizeInfo(quantize_info);
10734           break;
10735         }
10736         case 119:  /* SparseColor */
10737         {
10738           AV
10739             *av;
10740
10741           double
10742             *coordinates;
10743
10744           SparseColorMethod
10745             method;
10746
10747           size_t
10748             number_coordinates;
10749
10750           VirtualPixelMethod
10751             virtual_pixel;
10752
10753           if (attribute_flag[0] == 0)
10754             break;
10755           method=UndefinedColorInterpolate;
10756           if (attribute_flag[1] != 0)
10757             method=(SparseColorMethod) argument_list[1].integer_reference;
10758           av=(AV *) argument_list[0].array_reference;
10759           number_coordinates=(size_t) av_len(av)+1;
10760           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10761             sizeof(*coordinates));
10762           if (coordinates == (double *) NULL)
10763             {
10764               ThrowPerlException(exception,ResourceLimitFatalError,
10765                 "MemoryAllocationFailed",PackageName);
10766               goto PerlException;
10767             }
10768           for (j=0; j < (ssize_t) number_coordinates; j++)
10769             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10770           virtual_pixel=UndefinedVirtualPixelMethod;
10771           if (attribute_flag[2] != 0)
10772             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10773               argument_list[2].integer_reference,exception);
10774           if (attribute_flag[3] != 0)
10775             channel=(ChannelType) argument_list[3].integer_reference;
10776           channel_mask=SetImageChannelMask(image,channel);
10777           image=SparseColorImage(image,method,number_coordinates,coordinates,
10778             exception);
10779           if (image != (Image *) NULL)
10780             (void) SetImageChannelMask(image,channel_mask);
10781           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10782             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10783               exception);
10784           coordinates=(double *) RelinquishMagickMemory(coordinates);
10785           break;
10786         }
10787         case 120:  /* Function */
10788         {
10789           AV
10790             *av;
10791
10792           double
10793             *parameters;
10794
10795           MagickFunction
10796             function;
10797
10798           size_t
10799             number_parameters;
10800
10801           VirtualPixelMethod
10802             virtual_pixel;
10803
10804           if (attribute_flag[0] == 0)
10805             break;
10806           function=UndefinedFunction;
10807           if (attribute_flag[1] != 0)
10808             function=(MagickFunction) argument_list[1].integer_reference;
10809           av=(AV *) argument_list[0].array_reference;
10810           number_parameters=(size_t) av_len(av)+1;
10811           parameters=(double *) AcquireQuantumMemory(number_parameters,
10812             sizeof(*parameters));
10813           if (parameters == (double *) NULL)
10814             {
10815               ThrowPerlException(exception,ResourceLimitFatalError,
10816                 "MemoryAllocationFailed",PackageName);
10817               goto PerlException;
10818             }
10819           for (j=0; j < (ssize_t) number_parameters; j++)
10820             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10821           virtual_pixel=UndefinedVirtualPixelMethod;
10822           if (attribute_flag[2] != 0)
10823             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10824               argument_list[2].integer_reference,exception);
10825           (void) FunctionImage(image,function,number_parameters,parameters,
10826             exception);
10827           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10828             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel,
10829               exception);
10830           parameters=(double *) RelinquishMagickMemory(parameters);
10831           break;
10832         }
10833         case 121:  /* SelectiveBlur */
10834         {
10835           if (attribute_flag[0] != 0)
10836             {
10837               flags=ParseGeometry(argument_list[0].string_reference,
10838                 &geometry_info);
10839               if ((flags & SigmaValue) == 0)
10840                 geometry_info.sigma=1.0;
10841               if ((flags & PercentValue) != 0)
10842                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10843             }
10844           if (attribute_flag[1] != 0)
10845             geometry_info.rho=argument_list[1].real_reference;
10846           if (attribute_flag[2] != 0)
10847             geometry_info.sigma=argument_list[2].real_reference;
10848           if (attribute_flag[3] != 0)
10849             geometry_info.xi=argument_list[3].integer_reference;;
10850           if (attribute_flag[5] != 0)
10851             channel=(ChannelType) argument_list[5].integer_reference;
10852           channel_mask=SetImageChannelMask(image,channel);
10853           image=SelectiveBlurImage(image,geometry_info.rho,geometry_info.sigma,
10854             geometry_info.xi,exception);
10855           if (image != (Image *) NULL)
10856             (void) SetImageChannelMask(image,channel_mask);
10857           break;
10858         }
10859         case 122:  /* HaldClut */
10860         {
10861           if (attribute_flag[0] == 0)
10862             {
10863               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10864                 PackageName);
10865               goto PerlException;
10866             }
10867           if (attribute_flag[1] != 0)
10868             channel=(ChannelType) argument_list[1].integer_reference;
10869           channel_mask=SetImageChannelMask(image,channel);
10870           (void) HaldClutImage(image,argument_list[0].image_reference,
10871             exception);
10872           (void) SetImageChannelMask(image,channel_mask);
10873           break;
10874         }
10875         case 123:  /* BlueShift */
10876         {
10877           if (attribute_flag[0] != 0)
10878             (void) ParseGeometry(argument_list[0].string_reference,
10879               &geometry_info);
10880           image=BlueShiftImage(image,geometry_info.rho,exception);
10881           break;
10882         }
10883         case 124:  /* ForwardFourierTransformImage */
10884         {
10885           image=ForwardFourierTransformImage(image,
10886             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10887             exception);
10888           break;
10889         }
10890         case 125:  /* InverseFourierTransformImage */
10891         {
10892           image=InverseFourierTransformImage(image,image->next,
10893             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10894             exception);
10895           break;
10896         }
10897         case 126:  /* ColorDecisionList */
10898         {
10899           if (attribute_flag[0] == 0)
10900             argument_list[0].string_reference=(char *) NULL;
10901           (void) ColorDecisionListImage(image,
10902             argument_list[0].string_reference,exception);
10903           break;
10904         }
10905         case 127:  /* AutoGamma */
10906         {
10907           if (attribute_flag[0] != 0)
10908             channel=(ChannelType) argument_list[0].integer_reference;
10909           channel_mask=SetImageChannelMask(image,channel);
10910           (void) AutoGammaImage(image,exception);
10911           (void) SetImageChannelMask(image,channel_mask);
10912           break;
10913         }
10914         case 128:  /* AutoLevel */
10915         {
10916           if (attribute_flag[0] != 0)
10917             channel=(ChannelType) argument_list[0].integer_reference;
10918           channel_mask=SetImageChannelMask(image,channel);
10919           (void) AutoLevelImage(image,exception);
10920           (void) SetImageChannelMask(image,channel_mask);
10921           break;
10922         }
10923         case 129:  /* LevelColors */
10924         {
10925           PixelInfo
10926             black_point,
10927             white_point;
10928
10929           (void) QueryColorCompliance("#000000",AllCompliance,&black_point,
10930             exception);
10931           (void) QueryColorCompliance("#ffffff",AllCompliance,&white_point,
10932             exception);
10933           if (attribute_flag[1] != 0)
10934              (void) QueryColorCompliance(
10935                argument_list[1].string_reference,AllCompliance,&black_point,
10936                exception);
10937           if (attribute_flag[2] != 0)
10938              (void) QueryColorCompliance(
10939                argument_list[2].string_reference,AllCompliance,&white_point,
10940                exception);
10941           if (attribute_flag[3] != 0)
10942             channel=(ChannelType) argument_list[3].integer_reference;
10943           channel_mask=SetImageChannelMask(image,channel);
10944           (void) LevelImageColors(image,&black_point,&white_point,
10945             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10946             exception);
10947           (void) SetImageChannelMask(image,channel_mask);
10948           break;
10949         }
10950         case 130:  /* Clamp */
10951         {
10952           if (attribute_flag[0] != 0)
10953             channel=(ChannelType) argument_list[0].integer_reference;
10954           channel_mask=SetImageChannelMask(image,channel);
10955           (void) ClampImage(image,exception);
10956           (void) SetImageChannelMask(image,channel_mask);
10957           break;
10958         }
10959         case 131:  /* BrightnessContrast */
10960         {
10961           double
10962             brightness,
10963             contrast;
10964
10965           brightness=0.0;
10966           contrast=0.0;
10967           if (attribute_flag[0] != 0)
10968             {
10969               flags=ParseGeometry(argument_list[0].string_reference,
10970                 &geometry_info);
10971               brightness=geometry_info.rho;
10972               if ((flags & SigmaValue) == 0)
10973                 contrast=geometry_info.sigma;
10974             }
10975           if (attribute_flag[1] != 0)
10976             brightness=argument_list[1].real_reference;
10977           if (attribute_flag[2] != 0)
10978             contrast=argument_list[2].real_reference;
10979           if (attribute_flag[4] != 0)
10980             channel=(ChannelType) argument_list[4].integer_reference;
10981           channel_mask=SetImageChannelMask(image,channel);
10982           (void) BrightnessContrastImage(image,brightness,contrast,exception);
10983           (void) SetImageChannelMask(image,channel_mask);
10984           break;
10985         }
10986         case 132:  /* Morphology */
10987         {
10988           KernelInfo
10989             *kernel;
10990
10991           MorphologyMethod
10992             method;
10993
10994           ssize_t
10995             iterations;
10996
10997           if (attribute_flag[0] == 0)
10998             break;
10999           kernel=AcquireKernelInfo(argument_list[0].string_reference,exception);
11000           if (kernel == (KernelInfo *) NULL)
11001             break;
11002           if (attribute_flag[1] != 0)
11003             channel=(ChannelType) argument_list[1].integer_reference;
11004           method=UndefinedMorphology;
11005           if (attribute_flag[2] != 0)
11006             method=argument_list[2].integer_reference;
11007           iterations=1;
11008           if (attribute_flag[3] != 0)
11009             iterations=argument_list[3].integer_reference;
11010           channel_mask=SetImageChannelMask(image,channel);
11011           image=MorphologyImage(image,method,iterations,kernel,exception);
11012           if (image != (Image *) NULL)
11013             (void) SetImageChannelMask(image,channel_mask);
11014           kernel=DestroyKernelInfo(kernel);
11015           break;
11016         }
11017         case 133:  /* Mode */
11018         {
11019           if (attribute_flag[0] != 0)
11020             {
11021               flags=ParseGeometry(argument_list[0].string_reference,
11022                 &geometry_info);
11023               if ((flags & SigmaValue) == 0)
11024                 geometry_info.sigma=1.0;
11025             }
11026           if (attribute_flag[1] != 0)
11027             geometry_info.rho=argument_list[1].real_reference;
11028           if (attribute_flag[2] != 0)
11029             geometry_info.sigma=argument_list[2].real_reference;
11030           if (attribute_flag[3] != 0)
11031             channel=(ChannelType) argument_list[3].integer_reference;
11032           channel_mask=SetImageChannelMask(image,channel);
11033           image=StatisticImage(image,ModeStatistic,(size_t) geometry_info.rho,
11034             (size_t) geometry_info.sigma,exception);
11035           if (image != (Image *) NULL)
11036             (void) SetImageChannelMask(image,channel_mask);
11037           break;
11038         }
11039         case 134:  /* Statistic */
11040         {
11041           StatisticType
11042             statistic;
11043
11044           statistic=UndefinedStatistic;
11045           if (attribute_flag[0] != 0)
11046             {
11047               flags=ParseGeometry(argument_list[0].string_reference,
11048                 &geometry_info);
11049               if ((flags & SigmaValue) == 0)
11050                 geometry_info.sigma=1.0;
11051             }
11052           if (attribute_flag[1] != 0)
11053             geometry_info.rho=argument_list[1].real_reference;
11054           if (attribute_flag[2] != 0)
11055             geometry_info.sigma=argument_list[2].real_reference;
11056           if (attribute_flag[3] != 0)
11057             channel=(ChannelType) argument_list[3].integer_reference;
11058           if (attribute_flag[4] != 0)
11059             statistic=(StatisticType) argument_list[4].integer_reference;
11060           channel_mask=SetImageChannelMask(image,channel);
11061           image=StatisticImage(image,statistic,(size_t) geometry_info.rho,
11062             (size_t) geometry_info.sigma,exception);
11063           if (image != (Image *) NULL)
11064             (void) SetImageChannelMask(image,channel_mask);
11065           break;
11066         }
11067         case 135:  /* Perceptible */
11068         {
11069           double
11070             epsilon;
11071
11072           epsilon=MagickEpsilon;
11073           if (attribute_flag[0] != 0)
11074             epsilon=argument_list[0].real_reference;
11075           if (attribute_flag[1] != 0)
11076             channel=(ChannelType) argument_list[1].integer_reference;
11077           channel_mask=SetImageChannelMask(image,channel);
11078           (void) PerceptibleImage(image,epsilon,exception);
11079           (void) SetImageChannelMask(image,channel_mask);
11080           break;
11081         }
11082         case 136:  /* Poly */
11083         {
11084           AV
11085             *av;
11086
11087           double
11088             *terms;
11089
11090           size_t
11091             number_terms;
11092
11093           if (attribute_flag[0] == 0)
11094             break;
11095           if (attribute_flag[1] != 0)
11096             channel=(ChannelType) argument_list[1].integer_reference;
11097           av=(AV *) argument_list[0].array_reference;
11098           number_terms=(size_t) av_len(av);
11099           terms=(double *) AcquireQuantumMemory(number_terms,sizeof(*terms));
11100           if (terms == (double *) NULL)
11101             {
11102               ThrowPerlException(exception,ResourceLimitFatalError,
11103                 "MemoryAllocationFailed",PackageName);
11104               goto PerlException;
11105             }
11106           for (j=0; j < av_len(av); j++)
11107             terms[j]=(double) SvNV(*(av_fetch(av,j,0)));
11108           image=PolynomialImage(image,number_terms >> 1,terms,exception);
11109           terms=(double *) RelinquishMagickMemory(terms);
11110           break;
11111         }
11112         case 137:  /* Grayscale */
11113         {
11114           PixelIntensityMethod
11115             method;
11116
11117           method=UndefinedPixelIntensityMethod;
11118           if (attribute_flag[0] != 0)
11119             method=(PixelIntensityMethod) argument_list[0].integer_reference;
11120           (void) GrayscaleImage(image,method,exception);
11121           break;
11122         }
11123         case 138:  /* Canny */
11124         {
11125           if (attribute_flag[0] != 0)
11126             {
11127               flags=ParseGeometry(argument_list[0].string_reference,
11128                 &geometry_info);
11129               if ((flags & SigmaValue) == 0)
11130                 geometry_info.sigma=1.0;
11131               if ((flags & XiValue) == 0)
11132                 geometry_info.xi=0.10;
11133               if ((flags & PsiValue) == 0)
11134                 geometry_info.psi=0.30;
11135               if ((flags & PercentValue) != 0)
11136                 {
11137                   geometry_info.xi/=100.0;
11138                   geometry_info.psi/=100.0;
11139                 }
11140             }
11141           if (attribute_flag[1] != 0)
11142             geometry_info.rho=argument_list[1].real_reference;
11143           if (attribute_flag[2] != 0)
11144             geometry_info.sigma=argument_list[2].real_reference;
11145           if (attribute_flag[3] != 0)
11146             geometry_info.xi=argument_list[3].real_reference;
11147           if (attribute_flag[4] != 0)
11148             geometry_info.psi=argument_list[4].real_reference;
11149           if (attribute_flag[5] != 0)
11150             channel=(ChannelType) argument_list[5].integer_reference;
11151           channel_mask=SetImageChannelMask(image,channel);
11152           image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
11153             geometry_info.xi,geometry_info.psi,exception);
11154           if (image != (Image *) NULL)
11155             (void) SetImageChannelMask(image,channel_mask);
11156           break;
11157         }
11158         case 139:  /* HoughLine */
11159         {
11160           if (attribute_flag[0] != 0)
11161             {
11162               flags=ParseGeometry(argument_list[0].string_reference,
11163                 &geometry_info);
11164               if ((flags & SigmaValue) == 0)
11165                 geometry_info.sigma=geometry_info.rho;
11166               if ((flags & XiValue) == 0)
11167                 geometry_info.xi=40;
11168             }
11169           if (attribute_flag[1] != 0)
11170             geometry_info.rho=(double) argument_list[1].integer_reference;
11171           if (attribute_flag[2] != 0)
11172             geometry_info.sigma=(double) argument_list[2].integer_reference;
11173           if (attribute_flag[3] != 0)
11174             geometry_info.xi=(double) argument_list[3].integer_reference;
11175           image=HoughLineImage(image,(size_t) geometry_info.rho,(size_t)
11176             geometry_info.sigma,(size_t) geometry_info.xi,exception);
11177           break;
11178         }
11179         case 140:  /* MeanShift */
11180         {
11181           if (attribute_flag[0] != 0)
11182             {
11183               flags=ParseGeometry(argument_list[0].string_reference,
11184                 &geometry_info);
11185               if ((flags & SigmaValue) == 0)
11186                 geometry_info.sigma=geometry_info.rho;
11187               if ((flags & XiValue) == 0)
11188                 geometry_info.xi=0.10*QuantumRange;
11189               if ((flags & PercentValue) != 0)
11190                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
11191             }
11192           if (attribute_flag[1] != 0)
11193             geometry_info.rho=(double) argument_list[1].integer_reference;
11194           if (attribute_flag[2] != 0)
11195             geometry_info.sigma=(double) argument_list[2].integer_reference;
11196           if (attribute_flag[3] != 0)
11197             geometry_info.xi=(double) argument_list[3].integer_reference;
11198           image=MeanShiftImage(image,(size_t) geometry_info.rho,(size_t)
11199             geometry_info.sigma,geometry_info.xi,exception);
11200           break;
11201         }
11202         case 141:  /* Kuwahara */
11203         {
11204           if (attribute_flag[0] != 0)
11205             {
11206               flags=ParseGeometry(argument_list[0].string_reference,
11207                 &geometry_info);
11208               if ((flags & SigmaValue) == 0)
11209                 geometry_info.sigma=geometry_info.rho-0.5;
11210             }
11211           if (attribute_flag[1] != 0)
11212             geometry_info.rho=argument_list[1].real_reference;
11213           if (attribute_flag[2] != 0)
11214             geometry_info.sigma=argument_list[2].real_reference;
11215           if (attribute_flag[3] != 0)
11216             channel=(ChannelType) argument_list[3].integer_reference;
11217           channel_mask=SetImageChannelMask(image,channel);
11218           image=KuwaharaImage(image,geometry_info.rho,geometry_info.sigma,
11219             exception);
11220           if (image != (Image *) NULL)
11221             (void) SetImageChannelMask(image,channel_mask);
11222           break;
11223         }
11224         case 142:  /* ConnectedComponent */
11225         {
11226           size_t
11227             connectivity;
11228
11229           connectivity=4;
11230           if (attribute_flag[0] != 0)
11231             connectivity=argument_list[0].integer_reference;
11232           image=ConnectedComponentsImage(image,connectivity,exception);
11233           break;
11234         }
11235       }
11236       if (next != (Image *) NULL)
11237         (void) CatchImageException(next);
11238       if (region_image != (Image *) NULL)
11239         {
11240           /*
11241             Composite region.
11242           */
11243           status=CompositeImage(region_image,image,CopyCompositeOp,MagickTrue,
11244             region_info.x,region_info.y,exception);
11245           (void) status;
11246           (void) CatchImageException(region_image);
11247           image=DestroyImage(image);
11248           image=region_image;
11249         }
11250       if (image != (Image *) NULL)
11251         {
11252           number_images++;
11253           if (next && (next != image))
11254             {
11255               image->next=next->next;
11256               if (image->next != (Image *) NULL)
11257                 image->next->previous=image;
11258               DeleteImageFromRegistry(*pv,next);
11259             }
11260           sv_setiv(*pv,PTR2IV(image));
11261           next=image;
11262         }
11263       if (*pv)
11264         pv++;
11265     }
11266
11267   PerlException:
11268     if (reference_vector)
11269       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
11270     InheritPerlException(exception,perl_exception);
11271     exception=DestroyExceptionInfo(exception);
11272     sv_setiv(perl_exception,(IV) number_images);
11273     SvPOK_on(perl_exception);
11274     ST(0)=sv_2mortal(perl_exception);
11275     XSRETURN(1);
11276   }
11277 \f
11278 #
11279 ###############################################################################
11280 #                                                                             #
11281 #                                                                             #
11282 #                                                                             #
11283 #   M o n t a g e                                                             #
11284 #                                                                             #
11285 #                                                                             #
11286 #                                                                             #
11287 ###############################################################################
11288 #
11289 #
11290 void
11291 Montage(ref,...)
11292   Image::Magick ref=NO_INIT
11293   ALIAS:
11294     MontageImage  = 1
11295     montage       = 2
11296     montageimage  = 3
11297   PPCODE:
11298   {
11299     AV
11300       *av;
11301
11302     char
11303       *attribute;
11304
11305     ExceptionInfo
11306       *exception;
11307
11308     HV
11309       *hv;
11310
11311     Image
11312       *image,
11313       *next;
11314
11315     PixelInfo
11316       transparent_color;
11317
11318     MontageInfo
11319       *montage_info;
11320
11321     register ssize_t
11322       i;
11323
11324     ssize_t
11325       sp;
11326
11327     struct PackageInfo
11328       *info;
11329
11330     SV
11331       *av_reference,
11332       *perl_exception,
11333       *reference,
11334       *rv,
11335       *sv;
11336
11337     PERL_UNUSED_VAR(ref);
11338     PERL_UNUSED_VAR(ix);
11339     exception=AcquireExceptionInfo();
11340     perl_exception=newSVpv("",0);
11341     sv=NULL;
11342     attribute=NULL;
11343     if (sv_isobject(ST(0)) == 0)
11344       {
11345         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11346           PackageName);
11347         goto PerlException;
11348       }
11349     reference=SvRV(ST(0));
11350     hv=SvSTASH(reference);
11351     av=newAV();
11352     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11353     SvREFCNT_dec(av);
11354     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11355     if (image == (Image *) NULL)
11356       {
11357         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11358           PackageName);
11359         goto PerlException;
11360       }
11361     /*
11362       Get options.
11363     */
11364     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11365     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
11366     (void) QueryColorCompliance("none",AllCompliance,&transparent_color,
11367       exception);
11368     for (i=2; i < items; i+=2)
11369     {
11370       attribute=(char *) SvPV(ST(i-1),na);
11371       switch (*attribute)
11372       {
11373         case 'B':
11374         case 'b':
11375         {
11376           if (LocaleCompare(attribute,"background") == 0)
11377             {
11378               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11379                 &montage_info->background_color,exception);
11380               for (next=image; next; next=next->next)
11381                 next->background_color=montage_info->background_color;
11382               break;
11383             }
11384           if (LocaleCompare(attribute,"border") == 0)
11385             {
11386               montage_info->border_width=SvIV(ST(i));
11387               break;
11388             }
11389           if (LocaleCompare(attribute,"bordercolor") == 0)
11390             {
11391               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11392                 &montage_info->border_color,exception);
11393               for (next=image; next; next=next->next)
11394                 next->border_color=montage_info->border_color;
11395               break;
11396             }
11397           if (LocaleCompare(attribute,"borderwidth") == 0)
11398             {
11399               montage_info->border_width=SvIV(ST(i));
11400               break;
11401             }
11402           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11403             attribute);
11404           break;
11405         }
11406         case 'C':
11407         case 'c':
11408         {
11409           if (LocaleCompare(attribute,"compose") == 0)
11410             {
11411               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11412                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
11413               if (sp < 0)
11414                 {
11415                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11416                     SvPV(ST(i),na));
11417                   break;
11418                 }
11419               for (next=image; next; next=next->next)
11420                 next->compose=(CompositeOperator) sp;
11421               break;
11422             }
11423           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11424             attribute);
11425           break;
11426         }
11427         case 'F':
11428         case 'f':
11429         {
11430           if (LocaleCompare(attribute,"fill") == 0)
11431             {
11432               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11433                 &montage_info->fill,exception);
11434               break;
11435             }
11436           if (LocaleCompare(attribute,"font") == 0)
11437             {
11438               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
11439               break;
11440             }
11441           if (LocaleCompare(attribute,"frame") == 0)
11442             {
11443               char
11444                 *p;
11445
11446               p=SvPV(ST(i),na);
11447               if (IsGeometry(p) == MagickFalse)
11448                 {
11449                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11450                     p);
11451                   break;
11452                 }
11453               (void) CloneString(&montage_info->frame,p);
11454               if (*p == '\0')
11455                 montage_info->frame=(char *) NULL;
11456               break;
11457             }
11458           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11459             attribute);
11460           break;
11461         }
11462         case 'G':
11463         case 'g':
11464         {
11465           if (LocaleCompare(attribute,"geometry") == 0)
11466             {
11467               char
11468                 *p;
11469
11470               p=SvPV(ST(i),na);
11471               if (IsGeometry(p) == MagickFalse)
11472                 {
11473                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11474                     p);
11475                   break;
11476                 }
11477              (void) CloneString(&montage_info->geometry,p);
11478              if (*p == '\0')
11479                montage_info->geometry=(char *) NULL;
11480              break;
11481            }
11482          if (LocaleCompare(attribute,"gravity") == 0)
11483            {
11484              ssize_t
11485                in;
11486
11487              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11488                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
11489              if (in < 0)
11490                {
11491                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
11492                    SvPV(ST(i),na));
11493                  return;
11494                }
11495              montage_info->gravity=(GravityType) in;
11496              for (next=image; next; next=next->next)
11497                next->gravity=(GravityType) in;
11498              break;
11499            }
11500           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11501             attribute);
11502           break;
11503         }
11504         case 'L':
11505         case 'l':
11506         {
11507           if (LocaleCompare(attribute,"label") == 0)
11508             {
11509               for (next=image; next; next=next->next)
11510                 (void) SetImageProperty(next,"label",InterpretImageProperties(
11511                   info ? info->image_info : (ImageInfo *) NULL,next,
11512                   SvPV(ST(i),na),exception),exception);
11513               break;
11514             }
11515           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11516             attribute);
11517           break;
11518         }
11519         case 'M':
11520         case 'm':
11521         {
11522           if (LocaleCompare(attribute,"mattecolor") == 0)
11523             {
11524               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11525                 &montage_info->matte_color,exception);
11526               for (next=image; next; next=next->next)
11527                 next->matte_color=montage_info->matte_color;
11528               break;
11529             }
11530           if (LocaleCompare(attribute,"mode") == 0)
11531             {
11532               ssize_t
11533                 in;
11534
11535               in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11536                 MagickModeOptions,MagickFalse,SvPV(ST(i),na));
11537               switch (in)
11538               {
11539                 default:
11540                 {
11541                   ThrowPerlException(exception,OptionError,
11542                     "UnrecognizedModeType",SvPV(ST(i),na));
11543                   break;
11544                 }
11545                 case FrameMode:
11546                 {
11547                   (void) CloneString(&montage_info->frame,"15x15+3+3");
11548                   montage_info->shadow=MagickTrue;
11549                   break;
11550                 }
11551                 case UnframeMode:
11552                 {
11553                   montage_info->frame=(char *) NULL;
11554                   montage_info->shadow=MagickFalse;
11555                   montage_info->border_width=0;
11556                   break;
11557                 }
11558                 case ConcatenateMode:
11559                 {
11560                   montage_info->frame=(char *) NULL;
11561                   montage_info->shadow=MagickFalse;
11562                   (void) CloneString(&montage_info->geometry,"+0+0");
11563                   montage_info->border_width=0;
11564                 }
11565               }
11566               break;
11567             }
11568           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11569             attribute);
11570           break;
11571         }
11572         case 'P':
11573         case 'p':
11574         {
11575           if (LocaleCompare(attribute,"pointsize") == 0)
11576             {
11577               montage_info->pointsize=SvIV(ST(i));
11578               break;
11579             }
11580           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11581             attribute);
11582           break;
11583         }
11584         case 'S':
11585         case 's':
11586         {
11587           if (LocaleCompare(attribute,"shadow") == 0)
11588             {
11589               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
11590                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
11591               if (sp < 0)
11592                 {
11593                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11594                     SvPV(ST(i),na));
11595                   break;
11596                 }
11597              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
11598              break;
11599             }
11600           if (LocaleCompare(attribute,"stroke") == 0)
11601             {
11602               (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11603                 &montage_info->stroke,exception);
11604               break;
11605             }
11606           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11607             attribute);
11608           break;
11609         }
11610         case 'T':
11611         case 't':
11612         {
11613           if (LocaleCompare(attribute,"texture") == 0)
11614             {
11615               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
11616               break;
11617             }
11618           if (LocaleCompare(attribute,"tile") == 0)
11619             {
11620               char *p=SvPV(ST(i),na);
11621               if (IsGeometry(p) == MagickFalse)
11622                 {
11623                   ThrowPerlException(exception,OptionError,"MissingGeometry",
11624                     p);
11625                   break;
11626                 }
11627               (void) CloneString(&montage_info->tile,p);
11628               if (*p == '\0')
11629                 montage_info->tile=(char *) NULL;
11630               break;
11631             }
11632           if (LocaleCompare(attribute,"title") == 0)
11633             {
11634               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
11635               break;
11636             }
11637           if (LocaleCompare(attribute,"transparent") == 0)
11638             {
11639               PixelInfo
11640                 transparent_color;
11641
11642               QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
11643                 &transparent_color,exception);
11644               for (next=image; next; next=next->next)
11645                 (void) TransparentPaintImage(next,&transparent_color,
11646                   TransparentAlpha,MagickFalse,exception);
11647               break;
11648             }
11649           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11650             attribute);
11651           break;
11652         }
11653         default:
11654         {
11655           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11656             attribute);
11657           break;
11658         }
11659       }
11660     }
11661     image=MontageImageList(info->image_info,montage_info,image,exception);
11662     montage_info=DestroyMontageInfo(montage_info);
11663     if (image == (Image *) NULL)
11664       goto PerlException;
11665     if (transparent_color.alpha != TransparentAlpha)
11666       for (next=image; next; next=next->next)
11667         (void) TransparentPaintImage(next,&transparent_color,
11668           TransparentAlpha,MagickFalse,exception);
11669     for (  ; image; image=image->next)
11670     {
11671       AddImageToRegistry(sv,image);
11672       rv=newRV(sv);
11673       av_push(av,sv_bless(rv,hv));
11674       SvREFCNT_dec(sv);
11675     }
11676     exception=DestroyExceptionInfo(exception);
11677     ST(0)=av_reference;
11678     SvREFCNT_dec(perl_exception);
11679     XSRETURN(1);
11680
11681   PerlException:
11682     InheritPerlException(exception,perl_exception);
11683     exception=DestroyExceptionInfo(exception);
11684     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11685     SvPOK_on(perl_exception);
11686     ST(0)=sv_2mortal(perl_exception);
11687     XSRETURN(1);
11688   }
11689 \f
11690 #
11691 ###############################################################################
11692 #                                                                             #
11693 #                                                                             #
11694 #                                                                             #
11695 #   M o r p h                                                                 #
11696 #                                                                             #
11697 #                                                                             #
11698 #                                                                             #
11699 ###############################################################################
11700 #
11701 #
11702 void
11703 Morph(ref,...)
11704   Image::Magick ref=NO_INIT
11705   ALIAS:
11706     MorphImage  = 1
11707     morph       = 2
11708     morphimage  = 3
11709   PPCODE:
11710   {
11711     AV
11712       *av;
11713
11714     char
11715       *attribute;
11716
11717     ExceptionInfo
11718       *exception;
11719
11720     HV
11721       *hv;
11722
11723     Image
11724       *image;
11725
11726     register ssize_t
11727       i;
11728
11729     ssize_t
11730       number_frames;
11731
11732     struct PackageInfo
11733       *info;
11734
11735     SV
11736       *av_reference,
11737       *perl_exception,
11738       *reference,
11739       *rv,
11740       *sv;
11741
11742     PERL_UNUSED_VAR(ref);
11743     PERL_UNUSED_VAR(ix);
11744     exception=AcquireExceptionInfo();
11745     perl_exception=newSVpv("",0);
11746     sv=NULL;
11747     av=NULL;
11748     attribute=NULL;
11749     if (sv_isobject(ST(0)) == 0)
11750       {
11751         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11752           PackageName);
11753         goto PerlException;
11754       }
11755     reference=SvRV(ST(0));
11756     hv=SvSTASH(reference);
11757     av=newAV();
11758     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11759     SvREFCNT_dec(av);
11760     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11761     if (image == (Image *) NULL)
11762       {
11763         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11764           PackageName);
11765         goto PerlException;
11766       }
11767     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11768     /*
11769       Get attribute.
11770     */
11771     number_frames=30;
11772     for (i=2; i < items; i+=2)
11773     {
11774       attribute=(char *) SvPV(ST(i-1),na);
11775       switch (*attribute)
11776       {
11777         case 'F':
11778         case 'f':
11779         {
11780           if (LocaleCompare(attribute,"frames") == 0)
11781             {
11782               number_frames=SvIV(ST(i));
11783               break;
11784             }
11785           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11786             attribute);
11787           break;
11788         }
11789         default:
11790         {
11791           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11792             attribute);
11793           break;
11794         }
11795       }
11796     }
11797     image=MorphImages(image,number_frames,exception);
11798     if (image == (Image *) NULL)
11799       goto PerlException;
11800     for ( ; image; image=image->next)
11801     {
11802       AddImageToRegistry(sv,image);
11803       rv=newRV(sv);
11804       av_push(av,sv_bless(rv,hv));
11805       SvREFCNT_dec(sv);
11806     }
11807     exception=DestroyExceptionInfo(exception);
11808     ST(0)=av_reference;
11809     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11810     XSRETURN(1);
11811
11812   PerlException:
11813     InheritPerlException(exception,perl_exception);
11814     exception=DestroyExceptionInfo(exception);
11815     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11816     SvPOK_on(perl_exception);
11817     ST(0)=sv_2mortal(perl_exception);
11818     XSRETURN(1);
11819   }
11820 \f
11821 #
11822 ###############################################################################
11823 #                                                                             #
11824 #                                                                             #
11825 #                                                                             #
11826 #   M o s a i c                                                               #
11827 #                                                                             #
11828 #                                                                             #
11829 #                                                                             #
11830 ###############################################################################
11831 #
11832 #
11833 void
11834 Mosaic(ref)
11835   Image::Magick ref=NO_INIT
11836   ALIAS:
11837     MosaicImage   = 1
11838     mosaic        = 2
11839     mosaicimage   = 3
11840   PPCODE:
11841   {
11842     AV
11843       *av;
11844
11845     ExceptionInfo
11846       *exception;
11847
11848     HV
11849       *hv;
11850
11851     Image
11852       *image;
11853
11854     struct PackageInfo
11855       *info;
11856
11857     SV
11858       *perl_exception,
11859       *reference,
11860       *rv,
11861       *sv;
11862
11863     PERL_UNUSED_VAR(ref);
11864     PERL_UNUSED_VAR(ix);
11865     exception=AcquireExceptionInfo();
11866     perl_exception=newSVpv("",0);
11867     sv=NULL;
11868     if (sv_isobject(ST(0)) == 0)
11869       {
11870         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11871           PackageName);
11872         goto PerlException;
11873       }
11874     reference=SvRV(ST(0));
11875     hv=SvSTASH(reference);
11876     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11877     if (image == (Image *) NULL)
11878       {
11879         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11880           PackageName);
11881         goto PerlException;
11882       }
11883     image=MergeImageLayers(image,MosaicLayer,exception);
11884     /*
11885       Create blessed Perl array for the returned image.
11886     */
11887     av=newAV();
11888     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11889     SvREFCNT_dec(av);
11890     AddImageToRegistry(sv,image);
11891     rv=newRV(sv);
11892     av_push(av,sv_bless(rv,hv));
11893     SvREFCNT_dec(sv);
11894     (void) CopyMagickString(info->image_info->filename,image->filename,
11895       MagickPathExtent);
11896     SetImageInfo(info->image_info,0,exception);
11897     exception=DestroyExceptionInfo(exception);
11898     SvREFCNT_dec(perl_exception);
11899     XSRETURN(1);
11900
11901   PerlException:
11902     InheritPerlException(exception,perl_exception);
11903     exception=DestroyExceptionInfo(exception);
11904     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11905     SvPOK_on(perl_exception);  /* return messages in string context */
11906     ST(0)=sv_2mortal(perl_exception);
11907     XSRETURN(1);
11908   }
11909 \f
11910 #
11911 ###############################################################################
11912 #                                                                             #
11913 #                                                                             #
11914 #                                                                             #
11915 #   P i n g                                                                   #
11916 #                                                                             #
11917 #                                                                             #
11918 #                                                                             #
11919 ###############################################################################
11920 #
11921 #
11922 void
11923 Ping(ref,...)
11924   Image::Magick ref=NO_INIT
11925   ALIAS:
11926     PingImage  = 1
11927     ping       = 2
11928     pingimage  = 3
11929   PPCODE:
11930   {
11931     AV
11932       *av;
11933
11934     char
11935       **keep,
11936       **list;
11937
11938     ExceptionInfo
11939       *exception;
11940
11941     Image
11942       *image,
11943       *next;
11944
11945     int
11946       n;
11947
11948     MagickBooleanType
11949       status;
11950
11951     register char
11952       **p;
11953
11954     register ssize_t
11955       i;
11956
11957     ssize_t
11958       ac;
11959
11960     STRLEN
11961       *length;
11962
11963     struct PackageInfo
11964       *info,
11965       *package_info;
11966
11967     SV
11968       *perl_exception,
11969       *reference;
11970
11971     size_t
11972       count;
11973
11974     PERL_UNUSED_VAR(ref);
11975     PERL_UNUSED_VAR(ix);
11976     exception=AcquireExceptionInfo();
11977     perl_exception=newSVpv("",0);
11978     package_info=(struct PackageInfo *) NULL;
11979     ac=(items < 2) ? 1 : items-1;
11980     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11981     keep=list;
11982     length=(STRLEN *) NULL;
11983     if (list == (char **) NULL)
11984       {
11985         ThrowPerlException(exception,ResourceLimitError,
11986           "MemoryAllocationFailed",PackageName);
11987         goto PerlException;
11988       }
11989     keep=list;
11990     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11991     if (length == (STRLEN *) NULL)
11992       {
11993         ThrowPerlException(exception,ResourceLimitError,
11994           "MemoryAllocationFailed",PackageName);
11995         goto PerlException;
11996       }
11997     if (sv_isobject(ST(0)) == 0)
11998       {
11999         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12000           PackageName);
12001         goto PerlException;
12002       }
12003     reference=SvRV(ST(0));
12004     if (SvTYPE(reference) != SVt_PVAV)
12005       {
12006         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12007           PackageName);
12008         goto PerlException;
12009       }
12010     av=(AV *) reference;
12011     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12012       exception);
12013     package_info=ClonePackageInfo(info,exception);
12014     n=1;
12015     if (items <= 1)
12016       *list=(char *) (*package_info->image_info->filename ?
12017         package_info->image_info->filename : "XC:black");
12018     else
12019       for (n=0, i=0; i < ac; i++)
12020       {
12021         list[n]=(char *) SvPV(ST(i+1),length[n]);
12022         if ((items >= 3) && strEQcase(list[n],"blob"))
12023           {
12024             void
12025               *blob;
12026
12027             i++;
12028             blob=(void *) (SvPV(ST(i+1),length[n]));
12029             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12030           }
12031         if ((items >= 3) && strEQcase(list[n],"filename"))
12032           continue;
12033         if ((items >= 3) && strEQcase(list[n],"file"))
12034           {
12035             FILE
12036               *file;
12037
12038             PerlIO
12039               *io_info;
12040
12041             i++;
12042             io_info=IoIFP(sv_2io(ST(i+1)));
12043             if (io_info == (PerlIO *) NULL)
12044               {
12045                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12046                   PackageName);
12047                 continue;
12048               }
12049             file=PerlIO_findFILE(io_info);
12050             if (file == (FILE *) NULL)
12051               {
12052                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12053                   PackageName);
12054                 continue;
12055               }
12056             SetImageInfoFile(package_info->image_info,file);
12057           }
12058         if ((items >= 3) && strEQcase(list[n],"magick"))
12059           continue;
12060         n++;
12061       }
12062     list[n]=(char *) NULL;
12063     keep=list;
12064     status=ExpandFilenames(&n,&list);
12065     if (status == MagickFalse)
12066       {
12067         ThrowPerlException(exception,ResourceLimitError,
12068           "MemoryAllocationFailed",PackageName);
12069         goto PerlException;
12070       }
12071     count=0;
12072     for (i=0; i < n; i++)
12073     {
12074       (void) CopyMagickString(package_info->image_info->filename,list[i],
12075         MagickPathExtent);
12076       image=PingImage(package_info->image_info,exception);
12077       if (image == (Image *) NULL)
12078         break;
12079       if ((package_info->image_info->file != (FILE *) NULL) ||
12080           (package_info->image_info->blob != (void *) NULL))
12081         DisassociateImageStream(image);
12082       count+=GetImageListLength(image);
12083       EXTEND(sp,4*count);
12084       for (next=image; next; next=next->next)
12085       {
12086         PUSHs(sv_2mortal(newSViv(next->columns)));
12087         PUSHs(sv_2mortal(newSViv(next->rows)));
12088         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
12089         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
12090       }
12091       image=DestroyImageList(image);
12092     }
12093     /*
12094       Free resources.
12095     */
12096     for (i=0; i < n; i++)
12097       if (list[i] != (char *) NULL)
12098         for (p=keep; list[i] != *p++; )
12099           if (*p == NULL)
12100             {
12101               list[i]=(char *) RelinquishMagickMemory(list[i]);
12102               break;
12103             }
12104
12105   PerlException:
12106     if (package_info != (struct PackageInfo *) NULL)
12107       DestroyPackageInfo(package_info);
12108     if (list && (list != keep))
12109       list=(char **) RelinquishMagickMemory(list);
12110     if (keep)
12111       keep=(char **) RelinquishMagickMemory(keep);
12112     if (length)
12113       length=(STRLEN *) RelinquishMagickMemory(length);
12114     InheritPerlException(exception,perl_exception);
12115     exception=DestroyExceptionInfo(exception);
12116     SvREFCNT_dec(perl_exception);  /* throw away all errors */
12117   }
12118 \f
12119 #
12120 ###############################################################################
12121 #                                                                             #
12122 #                                                                             #
12123 #                                                                             #
12124 #   P r e v i e w                                                             #
12125 #                                                                             #
12126 #                                                                             #
12127 #                                                                             #
12128 ###############################################################################
12129 #
12130 #
12131 void
12132 Preview(ref,...)
12133   Image::Magick ref=NO_INIT
12134   ALIAS:
12135     PreviewImage = 1
12136     preview      = 2
12137     previewimage = 3
12138   PPCODE:
12139   {
12140     AV
12141       *av;
12142
12143     ExceptionInfo
12144       *exception;
12145
12146     HV
12147       *hv;
12148
12149     Image
12150       *image,
12151       *preview_image;
12152
12153     PreviewType
12154       preview_type;
12155
12156     struct PackageInfo
12157       *info;
12158
12159     SV
12160       *av_reference,
12161       *perl_exception,
12162       *reference,
12163       *rv,
12164       *sv;
12165
12166     PERL_UNUSED_VAR(ref);
12167     PERL_UNUSED_VAR(ix);
12168     exception=AcquireExceptionInfo();
12169     perl_exception=newSVpv("",0);
12170     sv=NULL;
12171     av=NULL;
12172     if (sv_isobject(ST(0)) == 0)
12173       {
12174         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12175           PackageName);
12176         goto PerlException;
12177       }
12178     reference=SvRV(ST(0));
12179     hv=SvSTASH(reference);
12180     av=newAV();
12181     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
12182     SvREFCNT_dec(av);
12183     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12184     if (image == (Image *) NULL)
12185       {
12186         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12187           PackageName);
12188         goto PerlException;
12189       }
12190     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
12191     preview_type=GammaPreview;
12192     if (items > 1)
12193       preview_type=(PreviewType)
12194         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
12195     for ( ; image; image=image->next)
12196     {
12197       preview_image=PreviewImage(image,preview_type,exception);
12198       if (preview_image == (Image *) NULL)
12199         goto PerlException;
12200       AddImageToRegistry(sv,preview_image);
12201       rv=newRV(sv);
12202       av_push(av,sv_bless(rv,hv));
12203       SvREFCNT_dec(sv);
12204     }
12205     exception=DestroyExceptionInfo(exception);
12206     ST(0)=av_reference;
12207     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12208     XSRETURN(1);
12209
12210   PerlException:
12211     InheritPerlException(exception,perl_exception);
12212     exception=DestroyExceptionInfo(exception);
12213     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
12214     SvPOK_on(perl_exception);
12215     ST(0)=sv_2mortal(perl_exception);
12216     XSRETURN(1);
12217   }
12218 \f
12219 #
12220 ###############################################################################
12221 #                                                                             #
12222 #                                                                             #
12223 #                                                                             #
12224 #   Q u e r y C o l o r                                                       #
12225 #                                                                             #
12226 #                                                                             #
12227 #                                                                             #
12228 ###############################################################################
12229 #
12230 #
12231 void
12232 QueryColor(ref,...)
12233   Image::Magick ref=NO_INIT
12234   ALIAS:
12235     querycolor = 1
12236   PPCODE:
12237   {
12238     char
12239       *name;
12240
12241     ExceptionInfo
12242       *exception;
12243
12244     PixelInfo
12245       color;
12246
12247     register ssize_t
12248       i;
12249
12250     SV
12251       *perl_exception;
12252
12253     PERL_UNUSED_VAR(ref);
12254     PERL_UNUSED_VAR(ix);
12255     exception=AcquireExceptionInfo();
12256     perl_exception=newSVpv("",0);
12257     if (items == 1)
12258       {
12259         const ColorInfo
12260           **colorlist;
12261
12262         size_t
12263           colors;
12264
12265         colorlist=GetColorInfoList("*",&colors,exception);
12266         EXTEND(sp,colors);
12267         for (i=0; i < (ssize_t) colors; i++)
12268         {
12269           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
12270         }
12271         colorlist=(const ColorInfo **)
12272           RelinquishMagickMemory((ColorInfo **) colorlist);
12273         goto PerlException;
12274       }
12275     EXTEND(sp,5*items);
12276     for (i=1; i < items; i++)
12277     {
12278       name=(char *) SvPV(ST(i),na);
12279       if (QueryColorCompliance(name,AllCompliance,&color,exception) == MagickFalse)
12280         {
12281           PUSHs(&sv_undef);
12282           continue;
12283         }
12284       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
12285       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
12286       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
12287       if (color.colorspace == CMYKColorspace)
12288         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
12289       if (color.alpha_trait != UndefinedPixelTrait)
12290         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
12291     }
12292
12293   PerlException:
12294     InheritPerlException(exception,perl_exception);
12295     exception=DestroyExceptionInfo(exception);
12296     SvREFCNT_dec(perl_exception);
12297   }
12298 \f
12299 #
12300 ###############################################################################
12301 #                                                                             #
12302 #                                                                             #
12303 #                                                                             #
12304 #   Q u e r y C o l o r N a m e                                               #
12305 #                                                                             #
12306 #                                                                             #
12307 #                                                                             #
12308 ###############################################################################
12309 #
12310 #
12311 void
12312 QueryColorname(ref,...)
12313   Image::Magick ref=NO_INIT
12314   ALIAS:
12315     querycolorname = 1
12316   PPCODE:
12317   {
12318     AV
12319       *av;
12320
12321     char
12322       message[MagickPathExtent];
12323
12324     ExceptionInfo
12325       *exception;
12326
12327     Image
12328       *image;
12329
12330     PixelInfo
12331       target_color;
12332
12333     register ssize_t
12334       i;
12335
12336     struct PackageInfo
12337       *info;
12338
12339     SV
12340       *perl_exception,
12341       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12342
12343     PERL_UNUSED_VAR(ref);
12344     PERL_UNUSED_VAR(ix);
12345     exception=AcquireExceptionInfo();
12346     perl_exception=newSVpv("",0);
12347     reference=SvRV(ST(0));
12348     av=(AV *) reference;
12349     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12350       exception);
12351     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12352     if (image == (Image *) NULL)
12353       {
12354         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12355           PackageName);
12356         goto PerlException;
12357       }
12358     EXTEND(sp,items);
12359     for (i=1; i < items; i++)
12360     {
12361       (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,&target_color,
12362         exception);
12363       (void) QueryColorname(image,&target_color,SVGCompliance,message,
12364         exception);
12365       PUSHs(sv_2mortal(newSVpv(message,0)));
12366     }
12367
12368   PerlException:
12369     InheritPerlException(exception,perl_exception);
12370     exception=DestroyExceptionInfo(exception);
12371     SvREFCNT_dec(perl_exception);
12372   }
12373 \f
12374 #
12375 ###############################################################################
12376 #                                                                             #
12377 #                                                                             #
12378 #                                                                             #
12379 #   Q u e r y F o n t                                                         #
12380 #                                                                             #
12381 #                                                                             #
12382 #                                                                             #
12383 ###############################################################################
12384 #
12385 #
12386 void
12387 QueryFont(ref,...)
12388   Image::Magick ref=NO_INIT
12389   ALIAS:
12390     queryfont = 1
12391   PPCODE:
12392   {
12393     char
12394       *name,
12395       message[MagickPathExtent];
12396
12397     ExceptionInfo
12398       *exception;
12399
12400     register ssize_t
12401       i;
12402
12403     SV
12404       *perl_exception;
12405
12406     volatile const TypeInfo
12407       *type_info;
12408
12409     PERL_UNUSED_VAR(ref);
12410     PERL_UNUSED_VAR(ix);
12411     exception=AcquireExceptionInfo();
12412     perl_exception=newSVpv("",0);
12413     if (items == 1)
12414       {
12415         const TypeInfo
12416           **typelist;
12417
12418         size_t
12419           types;
12420
12421         typelist=GetTypeInfoList("*",&types,exception);
12422         EXTEND(sp,types);
12423         for (i=0; i < (ssize_t) types; i++)
12424         {
12425           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
12426         }
12427         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
12428           typelist);
12429         goto PerlException;
12430       }
12431     EXTEND(sp,10*items);
12432     for (i=1; i < items; i++)
12433     {
12434       name=(char *) SvPV(ST(i),na);
12435       type_info=GetTypeInfo(name,exception);
12436       if (type_info == (TypeInfo *) NULL)
12437         {
12438           PUSHs(&sv_undef);
12439           continue;
12440         }
12441       if (type_info->name == (char *) NULL)
12442         PUSHs(&sv_undef);
12443       else
12444         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
12445       if (type_info->description == (char *) NULL)
12446         PUSHs(&sv_undef);
12447       else
12448         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
12449       if (type_info->family == (char *) NULL)
12450         PUSHs(&sv_undef);
12451       else
12452         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
12453       if (type_info->style == UndefinedStyle)
12454         PUSHs(&sv_undef);
12455       else
12456         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
12457           type_info->style),0)));
12458       if (type_info->stretch == UndefinedStretch)
12459         PUSHs(&sv_undef);
12460       else
12461         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
12462           type_info->stretch),0)));
12463       (void) FormatLocaleString(message,MagickPathExtent,"%.20g",(double)
12464         type_info->weight);
12465       PUSHs(sv_2mortal(newSVpv(message,0)));
12466       if (type_info->encoding == (char *) NULL)
12467         PUSHs(&sv_undef);
12468       else
12469         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
12470       if (type_info->foundry == (char *) NULL)
12471         PUSHs(&sv_undef);
12472       else
12473         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
12474       if (type_info->format == (char *) NULL)
12475         PUSHs(&sv_undef);
12476       else
12477         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
12478       if (type_info->metrics == (char *) NULL)
12479         PUSHs(&sv_undef);
12480       else
12481         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
12482       if (type_info->glyphs == (char *) NULL)
12483         PUSHs(&sv_undef);
12484       else
12485         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
12486     }
12487
12488   PerlException:
12489     InheritPerlException(exception,perl_exception);
12490     exception=DestroyExceptionInfo(exception);
12491     SvREFCNT_dec(perl_exception);
12492   }
12493 \f
12494 #
12495 ###############################################################################
12496 #                                                                             #
12497 #                                                                             #
12498 #                                                                             #
12499 #   Q u e r y F o n t M e t r i c s                                           #
12500 #                                                                             #
12501 #                                                                             #
12502 #                                                                             #
12503 ###############################################################################
12504 #
12505 #
12506 void
12507 QueryFontMetrics(ref,...)
12508   Image::Magick ref=NO_INIT
12509   ALIAS:
12510     queryfontmetrics = 1
12511   PPCODE:
12512   {
12513     AffineMatrix
12514       affine,
12515       current;
12516
12517     AV
12518       *av;
12519
12520     char
12521       *attribute;
12522
12523     double
12524       x,
12525       y;
12526
12527     DrawInfo
12528       *draw_info;
12529
12530     ExceptionInfo
12531       *exception;
12532
12533     GeometryInfo
12534       geometry_info;
12535
12536     Image
12537       *image;
12538
12539     MagickBooleanType
12540       status;
12541
12542     MagickStatusType
12543       flags;
12544
12545     register ssize_t
12546       i;
12547
12548     ssize_t
12549       type;
12550
12551     struct PackageInfo
12552       *info,
12553       *package_info;
12554
12555     SV
12556       *perl_exception,
12557       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12558
12559     TypeMetric
12560       metrics;
12561
12562     PERL_UNUSED_VAR(ref);
12563     PERL_UNUSED_VAR(ix);
12564     exception=AcquireExceptionInfo();
12565     package_info=(struct PackageInfo *) NULL;
12566     perl_exception=newSVpv("",0);
12567     reference=SvRV(ST(0));
12568     av=(AV *) reference;
12569     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12570       exception);
12571     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12572     if (image == (Image *) NULL)
12573       {
12574         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12575           PackageName);
12576         goto PerlException;
12577       }
12578     package_info=ClonePackageInfo(info,exception);
12579     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12580     CloneString(&draw_info->text,"");
12581     current=draw_info->affine;
12582     GetAffineMatrix(&affine);
12583     x=0.0;
12584     y=0.0;
12585     EXTEND(sp,7*items);
12586     for (i=2; i < items; i+=2)
12587     {
12588       attribute=(char *) SvPV(ST(i-1),na);
12589       switch (*attribute)
12590       {
12591         case 'A':
12592         case 'a':
12593         {
12594           if (LocaleCompare(attribute,"antialias") == 0)
12595             {
12596               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12597                 SvPV(ST(i),na));
12598               if (type < 0)
12599                 {
12600                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12601                     SvPV(ST(i),na));
12602                   break;
12603                 }
12604               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12605               break;
12606             }
12607           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12608             attribute);
12609           break;
12610         }
12611         case 'd':
12612         case 'D':
12613         {
12614           if (LocaleCompare(attribute,"density") == 0)
12615             {
12616               CloneString(&draw_info->density,SvPV(ST(i),na));
12617               break;
12618             }
12619           if (LocaleCompare(attribute,"direction") == 0)
12620             {
12621               draw_info->direction=(DirectionType) ParseCommandOption(
12622                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
12623               break;
12624             }
12625           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12626             attribute);
12627           break;
12628         }
12629         case 'e':
12630         case 'E':
12631         {
12632           if (LocaleCompare(attribute,"encoding") == 0)
12633             {
12634               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12635               break;
12636             }
12637           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12638             attribute);
12639           break;
12640         }
12641         case 'f':
12642         case 'F':
12643         {
12644           if (LocaleCompare(attribute,"family") == 0)
12645             {
12646               CloneString(&draw_info->family,SvPV(ST(i),na));
12647               break;
12648             }
12649           if (LocaleCompare(attribute,"fill") == 0)
12650             {
12651               if (info)
12652                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12653                   &draw_info->fill,exception);
12654               break;
12655             }
12656           if (LocaleCompare(attribute,"font") == 0)
12657             {
12658               CloneString(&draw_info->font,SvPV(ST(i),na));
12659               break;
12660             }
12661           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12662             attribute);
12663           break;
12664         }
12665         case 'g':
12666         case 'G':
12667         {
12668           if (LocaleCompare(attribute,"geometry") == 0)
12669             {
12670               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12671               break;
12672             }
12673           if (LocaleCompare(attribute,"gravity") == 0)
12674             {
12675               draw_info->gravity=(GravityType) ParseCommandOption(
12676                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12677               break;
12678             }
12679           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12680             attribute);
12681           break;
12682         }
12683         case 'i':
12684         case 'I':
12685         {
12686           if (LocaleCompare(attribute,"interline-spacing") == 0)
12687             {
12688               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12689               draw_info->interline_spacing=geometry_info.rho;
12690               break;
12691             }
12692           if (LocaleCompare(attribute,"interword-spacing") == 0)
12693             {
12694               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12695               draw_info->interword_spacing=geometry_info.rho;
12696               break;
12697             }
12698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12699             attribute);
12700           break;
12701         }
12702         case 'k':
12703         case 'K':
12704         {
12705           if (LocaleCompare(attribute,"kerning") == 0)
12706             {
12707               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12708               draw_info->kerning=geometry_info.rho;
12709               break;
12710             }
12711           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12712             attribute);
12713           break;
12714         }
12715         case 'p':
12716         case 'P':
12717         {
12718           if (LocaleCompare(attribute,"pointsize") == 0)
12719             {
12720               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12721               draw_info->pointsize=geometry_info.rho;
12722               break;
12723             }
12724           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12725             attribute);
12726           break;
12727         }
12728         case 'r':
12729         case 'R':
12730         {
12731           if (LocaleCompare(attribute,"rotate") == 0)
12732             {
12733               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12734               affine.rx=geometry_info.rho;
12735               affine.ry=geometry_info.sigma;
12736               if ((flags & SigmaValue) == 0)
12737                 affine.ry=affine.rx;
12738               break;
12739             }
12740           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12741             attribute);
12742           break;
12743         }
12744         case 's':
12745         case 'S':
12746         {
12747           if (LocaleCompare(attribute,"scale") == 0)
12748             {
12749               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12750               affine.sx=geometry_info.rho;
12751               affine.sy=geometry_info.sigma;
12752               if ((flags & SigmaValue) == 0)
12753                 affine.sy=affine.sx;
12754               break;
12755             }
12756           if (LocaleCompare(attribute,"skew") == 0)
12757             {
12758               double
12759                 x_angle,
12760                 y_angle;
12761
12762               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12763               x_angle=geometry_info.rho;
12764               y_angle=geometry_info.sigma;
12765               if ((flags & SigmaValue) == 0)
12766                 y_angle=x_angle;
12767               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12768               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12769               break;
12770             }
12771           if (LocaleCompare(attribute,"stroke") == 0)
12772             {
12773               if (info)
12774                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
12775                   &draw_info->stroke,exception);
12776               break;
12777             }
12778           if (LocaleCompare(attribute,"style") == 0)
12779             {
12780               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12781                 SvPV(ST(i),na));
12782               if (type < 0)
12783                 {
12784                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12785                     SvPV(ST(i),na));
12786                   break;
12787                 }
12788               draw_info->style=(StyleType) type;
12789               break;
12790             }
12791           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12792             attribute);
12793           break;
12794         }
12795         case 't':
12796         case 'T':
12797         {
12798           if (LocaleCompare(attribute,"text") == 0)
12799             {
12800               CloneString(&draw_info->text,SvPV(ST(i),na));
12801               break;
12802             }
12803           if (LocaleCompare(attribute,"translate") == 0)
12804             {
12805               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12806               affine.tx=geometry_info.rho;
12807               affine.ty=geometry_info.sigma;
12808               if ((flags & SigmaValue) == 0)
12809                 affine.ty=affine.tx;
12810               break;
12811             }
12812           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12813             attribute);
12814           break;
12815         }
12816         case 'w':
12817         case 'W':
12818         {
12819           if (LocaleCompare(attribute,"weight") == 0)
12820             {
12821               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12822               draw_info->weight=(size_t) geometry_info.rho;
12823               break;
12824             }
12825           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12826             attribute);
12827           break;
12828         }
12829         case 'x':
12830         case 'X':
12831         {
12832           if (LocaleCompare(attribute,"x") == 0)
12833             {
12834               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12835               x=geometry_info.rho;
12836               break;
12837             }
12838           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12839             attribute);
12840           break;
12841         }
12842         case 'y':
12843         case 'Y':
12844         {
12845           if (LocaleCompare(attribute,"y") == 0)
12846             {
12847               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12848               y=geometry_info.rho;
12849               break;
12850             }
12851           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12852             attribute);
12853           break;
12854         }
12855         default:
12856         {
12857           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12858             attribute);
12859           break;
12860         }
12861       }
12862     }
12863     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12864     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12865     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12866     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12867     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12868     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12869     if (draw_info->geometry == (char *) NULL)
12870       {
12871         draw_info->geometry=AcquireString((char *) NULL);
12872         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
12873           "%.15g,%.15g",x,y);
12874       }
12875     status=GetTypeMetrics(image,draw_info,&metrics,exception);
12876     (void) CatchImageException(image);
12877     if (status == MagickFalse)
12878       PUSHs(&sv_undef);
12879     else
12880       {
12881         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12882         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12883         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12884         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12885         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12886         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12887         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12888         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12889         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12890         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12891         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12892         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12893         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12894       }
12895     draw_info=DestroyDrawInfo(draw_info);
12896
12897   PerlException:
12898     if (package_info != (struct PackageInfo *) NULL)
12899       DestroyPackageInfo(package_info);
12900     InheritPerlException(exception,perl_exception);
12901     exception=DestroyExceptionInfo(exception);
12902     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12903   }
12904 \f
12905 #
12906 ###############################################################################
12907 #                                                                             #
12908 #                                                                             #
12909 #                                                                             #
12910 #   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                         #
12911 #                                                                             #
12912 #                                                                             #
12913 #                                                                             #
12914 ###############################################################################
12915 #
12916 #
12917 void
12918 QueryMultilineFontMetrics(ref,...)
12919   Image::Magick ref=NO_INIT
12920   ALIAS:
12921     querymultilinefontmetrics = 1
12922   PPCODE:
12923   {
12924     AffineMatrix
12925       affine,
12926       current;
12927
12928     AV
12929       *av;
12930
12931     char
12932       *attribute;
12933
12934     double
12935       x,
12936       y;
12937
12938     DrawInfo
12939       *draw_info;
12940
12941     ExceptionInfo
12942       *exception;
12943
12944     GeometryInfo
12945       geometry_info;
12946
12947     Image
12948       *image;
12949
12950     MagickBooleanType
12951       status;
12952
12953     MagickStatusType
12954       flags;
12955
12956     register ssize_t
12957       i;
12958
12959     ssize_t
12960       type;
12961
12962     struct PackageInfo
12963       *info,
12964       *package_info;
12965
12966     SV
12967       *perl_exception,
12968       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12969
12970     TypeMetric
12971       metrics;
12972
12973     PERL_UNUSED_VAR(ref);
12974     PERL_UNUSED_VAR(ix);
12975     exception=AcquireExceptionInfo();
12976     package_info=(struct PackageInfo *) NULL;
12977     perl_exception=newSVpv("",0);
12978     reference=SvRV(ST(0));
12979     av=(AV *) reference;
12980     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12981       exception);
12982     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12983     if (image == (Image *) NULL)
12984       {
12985         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12986           PackageName);
12987         goto PerlException;
12988       }
12989     package_info=ClonePackageInfo(info,exception);
12990     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12991     CloneString(&draw_info->text,"");
12992     current=draw_info->affine;
12993     GetAffineMatrix(&affine);
12994     x=0.0;
12995     y=0.0;
12996     EXTEND(sp,7*items);
12997     for (i=2; i < items; i+=2)
12998     {
12999       attribute=(char *) SvPV(ST(i-1),na);
13000       switch (*attribute)
13001       {
13002         case 'A':
13003         case 'a':
13004         {
13005           if (LocaleCompare(attribute,"antialias") == 0)
13006             {
13007               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13008                 SvPV(ST(i),na));
13009               if (type < 0)
13010                 {
13011                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13012                     SvPV(ST(i),na));
13013                   break;
13014                 }
13015               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
13016               break;
13017             }
13018           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13019             attribute);
13020           break;
13021         }
13022         case 'd':
13023         case 'D':
13024         {
13025           if (LocaleCompare(attribute,"density") == 0)
13026             {
13027               CloneString(&draw_info->density,SvPV(ST(i),na));
13028               break;
13029             }
13030           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13031             attribute);
13032           break;
13033         }
13034         case 'e':
13035         case 'E':
13036         {
13037           if (LocaleCompare(attribute,"encoding") == 0)
13038             {
13039               CloneString(&draw_info->encoding,SvPV(ST(i),na));
13040               break;
13041             }
13042           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13043             attribute);
13044           break;
13045         }
13046         case 'f':
13047         case 'F':
13048         {
13049           if (LocaleCompare(attribute,"family") == 0)
13050             {
13051               CloneString(&draw_info->family,SvPV(ST(i),na));
13052               break;
13053             }
13054           if (LocaleCompare(attribute,"fill") == 0)
13055             {
13056               if (info)
13057                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13058                   &draw_info->fill,exception);
13059               break;
13060             }
13061           if (LocaleCompare(attribute,"font") == 0)
13062             {
13063               CloneString(&draw_info->font,SvPV(ST(i),na));
13064               break;
13065             }
13066           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13067             attribute);
13068           break;
13069         }
13070         case 'g':
13071         case 'G':
13072         {
13073           if (LocaleCompare(attribute,"geometry") == 0)
13074             {
13075               CloneString(&draw_info->geometry,SvPV(ST(i),na));
13076               break;
13077             }
13078           if (LocaleCompare(attribute,"gravity") == 0)
13079             {
13080               draw_info->gravity=(GravityType) ParseCommandOption(
13081                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13082               break;
13083             }
13084           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13085             attribute);
13086           break;
13087         }
13088         case 'p':
13089         case 'P':
13090         {
13091           if (LocaleCompare(attribute,"pointsize") == 0)
13092             {
13093               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13094               draw_info->pointsize=geometry_info.rho;
13095               break;
13096             }
13097           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13098             attribute);
13099           break;
13100         }
13101         case 'r':
13102         case 'R':
13103         {
13104           if (LocaleCompare(attribute,"rotate") == 0)
13105             {
13106               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13107               affine.rx=geometry_info.rho;
13108               affine.ry=geometry_info.sigma;
13109               if ((flags & SigmaValue) == 0)
13110                 affine.ry=affine.rx;
13111               break;
13112             }
13113           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13114             attribute);
13115           break;
13116         }
13117         case 's':
13118         case 'S':
13119         {
13120           if (LocaleCompare(attribute,"scale") == 0)
13121             {
13122               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13123               affine.sx=geometry_info.rho;
13124               affine.sy=geometry_info.sigma;
13125               if ((flags & SigmaValue) == 0)
13126                 affine.sy=affine.sx;
13127               break;
13128             }
13129           if (LocaleCompare(attribute,"skew") == 0)
13130             {
13131               double
13132                 x_angle,
13133                 y_angle;
13134
13135               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13136               x_angle=geometry_info.rho;
13137               y_angle=geometry_info.sigma;
13138               if ((flags & SigmaValue) == 0)
13139                 y_angle=x_angle;
13140               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
13141               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
13142               break;
13143             }
13144           if (LocaleCompare(attribute,"stroke") == 0)
13145             {
13146               if (info)
13147                 (void) QueryColorCompliance(SvPV(ST(i),na),AllCompliance,
13148                   &draw_info->stroke,exception);
13149               break;
13150             }
13151           if (LocaleCompare(attribute,"style") == 0)
13152             {
13153               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
13154                 SvPV(ST(i),na));
13155               if (type < 0)
13156                 {
13157                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13158                     SvPV(ST(i),na));
13159                   break;
13160                 }
13161               draw_info->style=(StyleType) type;
13162               break;
13163             }
13164           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13165             attribute);
13166           break;
13167         }
13168         case 't':
13169         case 'T':
13170         {
13171           if (LocaleCompare(attribute,"text") == 0)
13172             {
13173               CloneString(&draw_info->text,SvPV(ST(i),na));
13174               break;
13175             }
13176           if (LocaleCompare(attribute,"translate") == 0)
13177             {
13178               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13179               affine.tx=geometry_info.rho;
13180               affine.ty=geometry_info.sigma;
13181               if ((flags & SigmaValue) == 0)
13182                 affine.ty=affine.tx;
13183               break;
13184             }
13185           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13186             attribute);
13187           break;
13188         }
13189         case 'w':
13190         case 'W':
13191         {
13192           if (LocaleCompare(attribute,"weight") == 0)
13193             {
13194               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13195               draw_info->weight=(size_t) geometry_info.rho;
13196               break;
13197             }
13198           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13199             attribute);
13200           break;
13201         }
13202         case 'x':
13203         case 'X':
13204         {
13205           if (LocaleCompare(attribute,"x") == 0)
13206             {
13207               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13208               x=geometry_info.rho;
13209               break;
13210             }
13211           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13212             attribute);
13213           break;
13214         }
13215         case 'y':
13216         case 'Y':
13217         {
13218           if (LocaleCompare(attribute,"y") == 0)
13219             {
13220               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
13221               y=geometry_info.rho;
13222               break;
13223             }
13224           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13225             attribute);
13226           break;
13227         }
13228         default:
13229         {
13230           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13231             attribute);
13232           break;
13233         }
13234       }
13235     }
13236     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
13237     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
13238     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
13239     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
13240     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
13241     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
13242     if (draw_info->geometry == (char *) NULL)
13243       {
13244         draw_info->geometry=AcquireString((char *) NULL);
13245         (void) FormatLocaleString(draw_info->geometry,MagickPathExtent,
13246           "%.15g,%.15g",x,y);
13247       }
13248     status=GetMultilineTypeMetrics(image,draw_info,&metrics,exception);
13249     (void) CatchException(exception);
13250     if (status == MagickFalse)
13251       PUSHs(&sv_undef);
13252     else
13253       {
13254         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
13255         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
13256         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
13257         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
13258         PUSHs(sv_2mortal(newSVnv(metrics.width)));
13259         PUSHs(sv_2mortal(newSVnv(metrics.height)));
13260         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
13261         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
13262         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
13263         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
13264         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
13265         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
13266         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
13267       }
13268     draw_info=DestroyDrawInfo(draw_info);
13269
13270   PerlException:
13271     if (package_info != (struct PackageInfo *) NULL)
13272       DestroyPackageInfo(package_info);
13273     InheritPerlException(exception,perl_exception);
13274     exception=DestroyExceptionInfo(exception);
13275     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13276   }
13277 \f
13278 #
13279 ###############################################################################
13280 #                                                                             #
13281 #                                                                             #
13282 #                                                                             #
13283 #   Q u e r y F o r m a t                                                     #
13284 #                                                                             #
13285 #                                                                             #
13286 #                                                                             #
13287 ###############################################################################
13288 #
13289 #
13290 void
13291 QueryFormat(ref,...)
13292   Image::Magick ref=NO_INIT
13293   ALIAS:
13294     queryformat = 1
13295   PPCODE:
13296   {
13297     char
13298       *name;
13299
13300     ExceptionInfo
13301       *exception;
13302
13303     register ssize_t
13304       i;
13305
13306     SV
13307       *perl_exception;
13308
13309     volatile const MagickInfo
13310       *magick_info;
13311
13312     PERL_UNUSED_VAR(ref);
13313     PERL_UNUSED_VAR(ix);
13314     exception=AcquireExceptionInfo();
13315     perl_exception=newSVpv("",0);
13316     if (items == 1)
13317       {
13318         char
13319           format[MagickPathExtent];
13320
13321         const MagickInfo
13322           **format_list;
13323
13324         size_t
13325           types;
13326
13327         format_list=GetMagickInfoList("*",&types,exception);
13328         EXTEND(sp,types);
13329         for (i=0; i < (ssize_t) types; i++)
13330         {
13331           (void) CopyMagickString(format,format_list[i]->name,MagickPathExtent);
13332           LocaleLower(format);
13333           PUSHs(sv_2mortal(newSVpv(format,0)));
13334         }
13335         format_list=(const MagickInfo **)
13336           RelinquishMagickMemory((MagickInfo *) format_list);
13337         goto PerlException;
13338       }
13339     EXTEND(sp,8*items);
13340     for (i=1; i < items; i++)
13341     {
13342       name=(char *) SvPV(ST(i),na);
13343       magick_info=GetMagickInfo(name,exception);
13344       if (magick_info == (const MagickInfo *) NULL)
13345         {
13346           PUSHs(&sv_undef);
13347           continue;
13348         }
13349       if (magick_info->description == (char *) NULL)
13350         PUSHs(&sv_undef);
13351       else
13352         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
13353       if (magick_info->module == (char *) NULL)
13354         PUSHs(&sv_undef);
13355       else
13356         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
13357     }
13358
13359   PerlException:
13360     InheritPerlException(exception,perl_exception);
13361     exception=DestroyExceptionInfo(exception);
13362     SvREFCNT_dec(perl_exception);
13363   }
13364 \f
13365 #
13366 ###############################################################################
13367 #                                                                             #
13368 #                                                                             #
13369 #                                                                             #
13370 #   Q u e r y O p t i o n                                                     #
13371 #                                                                             #
13372 #                                                                             #
13373 #                                                                             #
13374 ###############################################################################
13375 #
13376 #
13377 void
13378 QueryOption(ref,...)
13379   Image::Magick ref=NO_INIT
13380   ALIAS:
13381     queryoption = 1
13382   PPCODE:
13383   {
13384     char
13385       **options;
13386
13387     ExceptionInfo
13388       *exception;
13389
13390     register ssize_t
13391       i;
13392
13393     ssize_t
13394       j,
13395       option;
13396
13397     SV
13398       *perl_exception;
13399
13400     PERL_UNUSED_VAR(ref);
13401     PERL_UNUSED_VAR(ix);
13402     exception=AcquireExceptionInfo();
13403     perl_exception=newSVpv("",0);
13404     EXTEND(sp,8*items);
13405     for (i=1; i < items; i++)
13406     {
13407       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
13408         SvPV(ST(i),na));
13409       options=GetCommandOptions((CommandOption) option);
13410       if (options == (char **) NULL)
13411         PUSHs(&sv_undef);
13412       else
13413         {
13414           for (j=0; options[j] != (char *) NULL; j++)
13415             PUSHs(sv_2mortal(newSVpv(options[j],0)));
13416           options=DestroyStringList(options);
13417         }
13418     }
13419
13420     InheritPerlException(exception,perl_exception);
13421     exception=DestroyExceptionInfo(exception);
13422     SvREFCNT_dec(perl_exception);
13423   }
13424 \f
13425 #
13426 ###############################################################################
13427 #                                                                             #
13428 #                                                                             #
13429 #                                                                             #
13430 #   R e a d                                                                   #
13431 #                                                                             #
13432 #                                                                             #
13433 #                                                                             #
13434 ###############################################################################
13435 #
13436 #
13437 void
13438 Read(ref,...)
13439   Image::Magick ref=NO_INIT
13440   ALIAS:
13441     ReadImage  = 1
13442     read       = 2
13443     readimage  = 3
13444   PPCODE:
13445   {
13446     AV
13447       *av;
13448
13449     char
13450       **keep,
13451       **list;
13452
13453     ExceptionInfo
13454       *exception;
13455
13456     HV
13457       *hv;
13458
13459     Image
13460       *image;
13461
13462     int
13463       n;
13464
13465     MagickBooleanType
13466       status;
13467
13468     register char
13469       **p;
13470
13471     register ssize_t
13472       i;
13473
13474     ssize_t
13475       ac,
13476       number_images;
13477
13478     STRLEN
13479       *length;
13480
13481     struct PackageInfo
13482       *info,
13483       *package_info;
13484
13485     SV
13486       *perl_exception,  /* Perl variable for storing messages */
13487       *reference,
13488       *rv,
13489       *sv;
13490
13491     PERL_UNUSED_VAR(ref);
13492     PERL_UNUSED_VAR(ix);
13493     exception=AcquireExceptionInfo();
13494     perl_exception=newSVpv("",0);
13495     sv=NULL;
13496     package_info=(struct PackageInfo *) NULL;
13497     number_images=0;
13498     ac=(items < 2) ? 1 : items-1;
13499     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
13500     keep=list;
13501     length=(STRLEN *) NULL;
13502     if (list == (char **) NULL)
13503       {
13504         ThrowPerlException(exception,ResourceLimitError,
13505           "MemoryAllocationFailed",PackageName);
13506         goto PerlException;
13507       }
13508     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
13509     if (length == (STRLEN *) NULL)
13510       {
13511         ThrowPerlException(exception,ResourceLimitError,
13512           "MemoryAllocationFailed",PackageName);
13513         goto PerlException;
13514       }
13515     if (sv_isobject(ST(0)) == 0)
13516       {
13517         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13518           PackageName);
13519         goto PerlException;
13520       }
13521     reference=SvRV(ST(0));
13522     hv=SvSTASH(reference);
13523     if (SvTYPE(reference) != SVt_PVAV)
13524       {
13525         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13526           PackageName);
13527         goto PerlException;
13528       }
13529     av=(AV *) reference;
13530     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13531       exception);
13532     package_info=ClonePackageInfo(info,exception);
13533     n=1;
13534     if (items <= 1)
13535       *list=(char *) (*package_info->image_info->filename ?
13536         package_info->image_info->filename : "XC:black");
13537     else
13538       for (n=0, i=0; i < ac; i++)
13539       {
13540         list[n]=(char *) SvPV(ST(i+1),length[n]);
13541         if ((items >= 3) && strEQcase(list[n],"blob"))
13542           {
13543             void
13544               *blob;
13545
13546             i++;
13547             blob=(void *) (SvPV(ST(i+1),length[n]));
13548             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
13549           }
13550         if ((items >= 3) && strEQcase(list[n],"filename"))
13551           continue;
13552         if ((items >= 3) && strEQcase(list[n],"file"))
13553           {
13554             FILE
13555               *file;
13556
13557             PerlIO
13558               *io_info;
13559
13560             i++;
13561             io_info=IoIFP(sv_2io(ST(i+1)));
13562             if (io_info == (PerlIO *) NULL)
13563               {
13564                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13565                   PackageName);
13566                 continue;
13567               }
13568             file=PerlIO_findFILE(io_info);
13569             if (file == (FILE *) NULL)
13570               {
13571                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
13572                   PackageName);
13573                 continue;
13574               }
13575             SetImageInfoFile(package_info->image_info,file);
13576           }
13577         if ((items >= 3) && strEQcase(list[n],"magick"))
13578           continue;
13579         n++;
13580       }
13581     list[n]=(char *) NULL;
13582     keep=list;
13583     status=ExpandFilenames(&n,&list);
13584     if (status == MagickFalse)
13585       {
13586         ThrowPerlException(exception,ResourceLimitError,
13587           "MemoryAllocationFailed",PackageName);
13588         goto PerlException;
13589       }
13590     number_images=0;
13591     for (i=0; i < n; i++)
13592     {
13593       if ((package_info->image_info->file == (FILE *) NULL) &&
13594           (package_info->image_info->blob == (void *) NULL))
13595         image=ReadImages(package_info->image_info,list[i],exception);
13596       else
13597         {
13598           image=ReadImages(package_info->image_info,
13599             package_info->image_info->filename,exception);
13600           if (image != (Image *) NULL)
13601             DisassociateImageStream(image);
13602         }
13603       if (image == (Image *) NULL)
13604         break;
13605       for ( ; image; image=image->next)
13606       {
13607         AddImageToRegistry(sv,image);
13608         rv=newRV(sv);
13609         av_push(av,sv_bless(rv,hv));
13610         SvREFCNT_dec(sv);
13611         number_images++;
13612       }
13613     }
13614     /*
13615       Free resources.
13616     */
13617     for (i=0; i < n; i++)
13618       if (list[i] != (char *) NULL)
13619         for (p=keep; list[i] != *p++; )
13620           if (*p == (char *) NULL)
13621             {
13622               list[i]=(char *) RelinquishMagickMemory(list[i]);
13623               break;
13624             }
13625
13626   PerlException:
13627     if (package_info != (struct PackageInfo *) NULL)
13628       DestroyPackageInfo(package_info);
13629     if (list && (list != keep))
13630       list=(char **) RelinquishMagickMemory(list);
13631     if (keep)
13632       keep=(char **) RelinquishMagickMemory(keep);
13633     if (length)
13634       length=(STRLEN *) RelinquishMagickMemory(length);
13635     InheritPerlException(exception,perl_exception);
13636     exception=DestroyExceptionInfo(exception);
13637     sv_setiv(perl_exception,(IV) number_images);
13638     SvPOK_on(perl_exception);
13639     ST(0)=sv_2mortal(perl_exception);
13640     XSRETURN(1);
13641   }
13642 \f
13643 #
13644 ###############################################################################
13645 #                                                                             #
13646 #                                                                             #
13647 #                                                                             #
13648 #   R e m o t e                                                               #
13649 #                                                                             #
13650 #                                                                             #
13651 #                                                                             #
13652 ###############################################################################
13653 #
13654 #
13655 void
13656 Remote(ref,...)
13657   Image::Magick ref=NO_INIT
13658   ALIAS:
13659     RemoteCommand  = 1
13660     remote         = 2
13661     remoteCommand  = 3
13662   PPCODE:
13663   {
13664     AV
13665       *av;
13666
13667     ExceptionInfo
13668       *exception;
13669
13670     register ssize_t
13671       i;
13672
13673     SV
13674       *perl_exception,
13675       *reference;
13676
13677     struct PackageInfo
13678       *info;
13679
13680     PERL_UNUSED_VAR(ref);
13681     PERL_UNUSED_VAR(ix);
13682     exception=AcquireExceptionInfo();
13683     perl_exception=newSVpv("",0);
13684     reference=SvRV(ST(0));
13685     av=(AV *) reference;
13686     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13687       exception);
13688     for (i=1; i < items; i++)
13689       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13690         SvPV(ST(i),na),exception);
13691     InheritPerlException(exception,perl_exception);
13692     exception=DestroyExceptionInfo(exception);
13693     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13694   }
13695 \f
13696 #
13697 ###############################################################################
13698 #                                                                             #
13699 #                                                                             #
13700 #                                                                             #
13701 #   S e t                                                                     #
13702 #                                                                             #
13703 #                                                                             #
13704 #                                                                             #
13705 ###############################################################################
13706 #
13707 #
13708 void
13709 Set(ref,...)
13710   Image::Magick ref=NO_INIT
13711   ALIAS:
13712     SetAttributes  = 1
13713     SetAttribute   = 2
13714     set            = 3
13715     setattributes  = 4
13716     setattribute   = 5
13717   PPCODE:
13718   {
13719     ExceptionInfo
13720       *exception;
13721
13722     Image
13723       *image;
13724
13725     register ssize_t
13726       i;
13727
13728     struct PackageInfo
13729       *info;
13730
13731     SV
13732       *perl_exception,
13733       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13734
13735     PERL_UNUSED_VAR(ref);
13736     PERL_UNUSED_VAR(ix);
13737     exception=AcquireExceptionInfo();
13738     perl_exception=newSVpv("",0);
13739     if (sv_isobject(ST(0)) == 0)
13740       {
13741         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13742           PackageName);
13743         goto PerlException;
13744       }
13745     reference=SvRV(ST(0));
13746     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13747     if (items == 2)
13748       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13749     else
13750       for (i=2; i < items; i+=2)
13751         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13752
13753   PerlException:
13754     InheritPerlException(exception,perl_exception);
13755     exception=DestroyExceptionInfo(exception);
13756     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13757     SvPOK_on(perl_exception);
13758     ST(0)=sv_2mortal(perl_exception);
13759     XSRETURN(1);
13760   }
13761 \f
13762 #
13763 ###############################################################################
13764 #                                                                             #
13765 #                                                                             #
13766 #                                                                             #
13767 #   S e t P i x e l                                                           #
13768 #                                                                             #
13769 #                                                                             #
13770 #                                                                             #
13771 ###############################################################################
13772 #
13773 #
13774 void
13775 SetPixel(ref,...)
13776   Image::Magick ref=NO_INIT
13777   ALIAS:
13778     setpixel = 1
13779     setPixel = 2
13780   PPCODE:
13781   {
13782     AV
13783       *av;
13784
13785     char
13786       *attribute;
13787
13788     ChannelType
13789       channel,
13790       channel_mask;
13791
13792     ExceptionInfo
13793       *exception;
13794
13795     Image
13796       *image;
13797
13798     MagickBooleanType
13799       normalize;
13800
13801     RectangleInfo
13802       region;
13803
13804     register ssize_t
13805       i;
13806
13807     register Quantum
13808       *q;
13809
13810     ssize_t
13811       option;
13812
13813     struct PackageInfo
13814       *info;
13815
13816     SV
13817       *perl_exception,
13818       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13819
13820     PERL_UNUSED_VAR(ref);
13821     PERL_UNUSED_VAR(ix);
13822     exception=AcquireExceptionInfo();
13823     perl_exception=newSVpv("",0);
13824     reference=SvRV(ST(0));
13825     av=(AV *) reference;
13826     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13827       exception);
13828     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13829     if (image == (Image *) NULL)
13830       {
13831         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13832           PackageName);
13833         goto PerlException;
13834       }
13835     av=(AV *) NULL;
13836     normalize=MagickTrue;
13837     region.x=0;
13838     region.y=0;
13839     region.width=image->columns;
13840     region.height=1;
13841     if (items == 1)
13842       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13843     channel=DefaultChannels;
13844     for (i=2; i < items; i+=2)
13845     {
13846       attribute=(char *) SvPV(ST(i-1),na);
13847       switch (*attribute)
13848       {
13849         case 'C':
13850         case 'c':
13851         {
13852           if (LocaleCompare(attribute,"channel") == 0)
13853             {
13854               ssize_t
13855                 option;
13856
13857               option=ParseChannelOption(SvPV(ST(i),na));
13858               if (option < 0)
13859                 {
13860                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13861                     SvPV(ST(i),na));
13862                   return;
13863                 }
13864               channel=(ChannelType) option;
13865               break;
13866             }
13867           if (LocaleCompare(attribute,"color") == 0)
13868             {
13869               if (SvTYPE(ST(i)) != SVt_RV)
13870                 {
13871                   char
13872                     message[MagickPathExtent];
13873
13874                   (void) FormatLocaleString(message,MagickPathExtent,
13875                     "invalid %.60s value",attribute);
13876                   ThrowPerlException(exception,OptionError,message,
13877                     SvPV(ST(i),na));
13878                 }
13879               av=(AV *) SvRV(ST(i));
13880               break;
13881             }
13882           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13883             attribute);
13884           break;
13885         }
13886         case 'g':
13887         case 'G':
13888         {
13889           if (LocaleCompare(attribute,"geometry") == 0)
13890             {
13891               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13892               break;
13893             }
13894           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13895             attribute);
13896           break;
13897         }
13898         case 'N':
13899         case 'n':
13900         {
13901           if (LocaleCompare(attribute,"normalize") == 0)
13902             {
13903               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13904                 SvPV(ST(i),na));
13905               if (option < 0)
13906                 {
13907                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13908                     SvPV(ST(i),na));
13909                   break;
13910                 }
13911              normalize=option != 0 ? MagickTrue : MagickFalse;
13912              break;
13913             }
13914           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13915             attribute);
13916           break;
13917         }
13918         case 'x':
13919         case 'X':
13920         {
13921           if (LocaleCompare(attribute,"x") == 0)
13922             {
13923               region.x=SvIV(ST(i));
13924               break;
13925             }
13926           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13927             attribute);
13928           break;
13929         }
13930         case 'y':
13931         case 'Y':
13932         {
13933           if (LocaleCompare(attribute,"y") == 0)
13934             {
13935               region.y=SvIV(ST(i));
13936               break;
13937             }
13938           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13939             attribute);
13940           break;
13941         }
13942         default:
13943         {
13944           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13945             attribute);
13946           break;
13947         }
13948       }
13949     }
13950     (void) SetImageStorageClass(image,DirectClass,exception);
13951     channel_mask=SetImageChannelMask(image,channel);
13952     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13953     if ((q == (Quantum *) NULL) || (av == (AV *) NULL) ||
13954         (SvTYPE(av) != SVt_PVAV))
13955       PUSHs(&sv_undef);
13956     else
13957       {
13958         double
13959           scale;
13960
13961         register ssize_t
13962           i;
13963
13964         i=0;
13965         scale=1.0;
13966         if (normalize != MagickFalse)
13967           scale=QuantumRange;
13968         if (((GetPixelRedTraits(image) & UpdatePixelTrait) != 0) &&
13969             (i <= av_len(av)))
13970           {
13971             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13972               av_fetch(av,i,0)))),q);
13973             i++;
13974           }
13975         if (((GetPixelGreenTraits(image) & UpdatePixelTrait) != 0) &&
13976             (i <= av_len(av)))
13977           {
13978             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13979               av_fetch(av,i,0)))),q);
13980             i++;
13981           }
13982         if (((GetPixelBlueTraits(image) & UpdatePixelTrait) != 0) &&
13983             (i <= av_len(av)))
13984           {
13985             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13986               av_fetch(av,i,0)))),q);
13987             i++;
13988           }
13989         if ((((GetPixelBlackTraits(image) & UpdatePixelTrait) != 0) &&
13990             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13991           {
13992             SetPixelBlack(image,ClampToQuantum(scale*
13993               SvNV(*(av_fetch(av,i,0)))),q);
13994             i++;
13995           }
13996         if (((GetPixelAlphaTraits(image) & UpdatePixelTrait) != 0) &&
13997             (i <= av_len(av)))
13998           {
13999             SetPixelAlpha(image,ClampToQuantum(scale*
14000               SvNV(*(av_fetch(av,i,0)))),q);
14001             i++;
14002           }
14003         (void) SyncAuthenticPixels(image,exception);
14004       }
14005     (void) SetImageChannelMask(image,channel_mask);
14006
14007   PerlException:
14008     InheritPerlException(exception,perl_exception);
14009     exception=DestroyExceptionInfo(exception);
14010     SvREFCNT_dec(perl_exception);
14011   }
14012 \f
14013 #
14014 ###############################################################################
14015 #                                                                             #
14016 #                                                                             #
14017 #                                                                             #
14018 #   S m u s h                                                                 #
14019 #                                                                             #
14020 #                                                                             #
14021 #                                                                             #
14022 ###############################################################################
14023 #
14024 #
14025 void
14026 Smush(ref,...)
14027   Image::Magick ref=NO_INIT
14028   ALIAS:
14029     SmushImage  = 1
14030     smush       = 2
14031     smushimage  = 3
14032   PPCODE:
14033   {
14034     AV
14035       *av;
14036
14037     char
14038       *attribute;
14039
14040     ExceptionInfo
14041       *exception;
14042
14043     HV
14044       *hv;
14045
14046     Image
14047       *image;
14048
14049     register ssize_t
14050       i;
14051
14052     ssize_t
14053       offset,
14054       stack;
14055
14056     struct PackageInfo
14057       *info;
14058
14059     SV
14060       *av_reference,
14061       *perl_exception,
14062       *reference,
14063       *rv,
14064       *sv;
14065
14066     PERL_UNUSED_VAR(ref);
14067     PERL_UNUSED_VAR(ix);
14068     exception=AcquireExceptionInfo();
14069     perl_exception=newSVpv("",0);
14070     sv=NULL;
14071     attribute=NULL;
14072     av=NULL;
14073     if (sv_isobject(ST(0)) == 0)
14074       {
14075         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14076           PackageName);
14077         goto PerlException;
14078       }
14079     reference=SvRV(ST(0));
14080     hv=SvSTASH(reference);
14081     av=newAV();
14082     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14083     SvREFCNT_dec(av);
14084     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14085     if (image == (Image *) NULL)
14086       {
14087         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14088           PackageName);
14089         goto PerlException;
14090       }
14091     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14092     /*
14093       Get options.
14094     */
14095     offset=0;
14096     stack=MagickTrue;
14097     for (i=2; i < items; i+=2)
14098     {
14099       attribute=(char *) SvPV(ST(i-1),na);
14100       switch (*attribute)
14101       {
14102         case 'O':
14103         case 'o':
14104         {
14105           if (LocaleCompare(attribute,"offset") == 0)
14106             {
14107               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
14108               break;
14109             }
14110           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14111             attribute);
14112           break;
14113         }
14114         case 'S':
14115         case 's':
14116         {
14117           if (LocaleCompare(attribute,"stack") == 0)
14118             {
14119               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
14120                 SvPV(ST(i),na));
14121               if (stack < 0)
14122                 {
14123                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
14124                     SvPV(ST(i),na));
14125                   return;
14126                 }
14127               break;
14128             }
14129           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14130             attribute);
14131           break;
14132         }
14133         default:
14134         {
14135           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14136             attribute);
14137           break;
14138         }
14139       }
14140     }
14141     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
14142       exception);
14143     if (image == (Image *) NULL)
14144       goto PerlException;
14145     for ( ; image; image=image->next)
14146     {
14147       AddImageToRegistry(sv,image);
14148       rv=newRV(sv);
14149       av_push(av,sv_bless(rv,hv));
14150       SvREFCNT_dec(sv);
14151     }
14152     exception=DestroyExceptionInfo(exception);
14153     ST(0)=av_reference;
14154     SvREFCNT_dec(perl_exception);
14155     XSRETURN(1);
14156
14157   PerlException:
14158     InheritPerlException(exception,perl_exception);
14159     exception=DestroyExceptionInfo(exception);
14160     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14161     SvPOK_on(perl_exception);
14162     ST(0)=sv_2mortal(perl_exception);
14163     XSRETURN(1);
14164   }
14165 \f
14166 #
14167 ###############################################################################
14168 #                                                                             #
14169 #                                                                             #
14170 #                                                                             #
14171 #   S t a t i s t i c s                                                       #
14172 #                                                                             #
14173 #                                                                             #
14174 #                                                                             #
14175 ###############################################################################
14176 #
14177 #
14178 void
14179 Statistics(ref,...)
14180   Image::Magick ref=NO_INIT
14181   ALIAS:
14182     StatisticsImage = 1
14183     statistics      = 2
14184     statisticsimage = 3
14185   PPCODE:
14186   {
14187 #define ChannelStatistics(channel) \
14188 { \
14189   (void) FormatLocaleString(message,MagickPathExtent,"%.20g", \
14190     (double) channel_statistics[channel].depth); \
14191   PUSHs(sv_2mortal(newSVpv(message,0))); \
14192   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14193     channel_statistics[channel].minima/scale); \
14194   PUSHs(sv_2mortal(newSVpv(message,0))); \
14195   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14196     channel_statistics[channel].maxima/scale); \
14197   PUSHs(sv_2mortal(newSVpv(message,0))); \
14198   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14199     channel_statistics[channel].mean/scale); \
14200   PUSHs(sv_2mortal(newSVpv(message,0))); \
14201   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14202     channel_statistics[channel].standard_deviation/scale); \
14203   PUSHs(sv_2mortal(newSVpv(message,0))); \
14204   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14205     channel_statistics[channel].kurtosis); \
14206   PUSHs(sv_2mortal(newSVpv(message,0))); \
14207   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14208     channel_statistics[channel].skewness); \
14209   PUSHs(sv_2mortal(newSVpv(message,0))); \
14210   (void) FormatLocaleString(message,MagickPathExtent,"%.15g", \
14211     channel_statistics[channel].entropy); \
14212   PUSHs(sv_2mortal(newSVpv(message,0))); \
14213 }
14214
14215     AV
14216       *av;
14217
14218     char
14219       message[MagickPathExtent];
14220
14221     ChannelStatistics
14222       *channel_statistics;
14223
14224     double
14225       scale;
14226
14227     ExceptionInfo
14228       *exception;
14229
14230     Image
14231       *image;
14232
14233     ssize_t
14234       count;
14235
14236     struct PackageInfo
14237       *info;
14238
14239     SV
14240       *perl_exception,
14241       *reference;
14242
14243     PERL_UNUSED_VAR(ref);
14244     PERL_UNUSED_VAR(ix);
14245     exception=AcquireExceptionInfo();
14246     perl_exception=newSVpv("",0);
14247     av=NULL;
14248     if (sv_isobject(ST(0)) == 0)
14249       {
14250         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14251           PackageName);
14252         goto PerlException;
14253       }
14254     reference=SvRV(ST(0));
14255     av=newAV();
14256     SvREFCNT_dec(av);
14257     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14258     if (image == (Image *) NULL)
14259       {
14260         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14261           PackageName);
14262         goto PerlException;
14263       }
14264     count=0;
14265     for ( ; image; image=image->next)
14266     {
14267       channel_statistics=GetImageStatistics(image,exception);
14268       if (channel_statistics == (ChannelStatistics *) NULL)
14269         continue;
14270       count++;
14271       EXTEND(sp,35*count);
14272       scale=(double) QuantumRange;
14273       ChannelStatistics(RedChannel);
14274       ChannelStatistics(GreenChannel);
14275       ChannelStatistics(BlueChannel);
14276       if (image->colorspace == CMYKColorspace)
14277         ChannelStatistics(BlackChannel);
14278       if (image->alpha_trait != UndefinedPixelTrait)
14279         ChannelStatistics(AlphaChannel);
14280       channel_statistics=(ChannelStatistics *)
14281         RelinquishMagickMemory(channel_statistics);
14282     }
14283
14284   PerlException:
14285     InheritPerlException(exception,perl_exception);
14286     exception=DestroyExceptionInfo(exception);
14287     SvREFCNT_dec(perl_exception);
14288   }
14289 \f
14290 #
14291 ###############################################################################
14292 #                                                                             #
14293 #                                                                             #
14294 #                                                                             #
14295 #   S y n c A u t h e n t i c P i x e l s                                     #
14296 #                                                                             #
14297 #                                                                             #
14298 #                                                                             #
14299 ###############################################################################
14300 #
14301 #
14302 void
14303 SyncAuthenticPixels(ref,...)
14304   Image::Magick ref = NO_INIT
14305   ALIAS:
14306     Syncauthenticpixels = 1
14307     SyncImagePixels = 2
14308     syncimagepixels = 3
14309   CODE:
14310   {
14311     ExceptionInfo
14312       *exception;
14313
14314     Image
14315       *image;
14316
14317     MagickBooleanType
14318       status;
14319
14320     struct PackageInfo
14321       *info;
14322
14323     SV
14324       *perl_exception,
14325       *reference;
14326
14327     PERL_UNUSED_VAR(ref);
14328     PERL_UNUSED_VAR(ix);
14329     exception=AcquireExceptionInfo();
14330     perl_exception=newSVpv("",0);
14331     if (sv_isobject(ST(0)) == 0)
14332       {
14333         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14334           PackageName);
14335         goto PerlException;
14336       }
14337
14338     reference=SvRV(ST(0));
14339     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14340     if (image == (Image *) NULL)
14341       {
14342         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14343           PackageName);
14344         goto PerlException;
14345       }
14346
14347     status=SyncAuthenticPixels(image,exception);
14348     if (status != MagickFalse)
14349       return;
14350
14351   PerlException:
14352     InheritPerlException(exception,perl_exception);
14353     exception=DestroyExceptionInfo(exception);
14354     SvREFCNT_dec(perl_exception);  /* throw away all errors */
14355   }
14356 \f
14357 #
14358 ###############################################################################
14359 #                                                                             #
14360 #                                                                             #
14361 #                                                                             #
14362 #   T r a n s f o r m                                                         #
14363 #                                                                             #
14364 #                                                                             #
14365 #                                                                             #
14366 ###############################################################################
14367 #
14368 #
14369 void
14370 Transform(ref,...)
14371   Image::Magick ref=NO_INIT
14372   ALIAS:
14373     TransformImage = 1
14374     transform      = 2
14375     transformimage = 3
14376   PPCODE:
14377   {
14378     AV
14379       *av;
14380
14381     char
14382       *attribute,
14383       *crop_geometry,
14384       *geometry;
14385
14386     ExceptionInfo
14387       *exception;
14388
14389     HV
14390       *hv;
14391
14392     Image
14393       *clone,
14394       *image;
14395
14396     register ssize_t
14397       i;
14398
14399     struct PackageInfo
14400       *info;
14401
14402     SV
14403       *av_reference,
14404       *perl_exception,
14405       *reference,
14406       *rv,
14407       *sv;
14408
14409     PERL_UNUSED_VAR(ref);
14410     PERL_UNUSED_VAR(ix);
14411     exception=AcquireExceptionInfo();
14412     perl_exception=newSVpv("",0);
14413     sv=NULL;
14414     av=NULL;
14415     attribute=NULL;
14416     if (sv_isobject(ST(0)) == 0)
14417       {
14418         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14419           PackageName);
14420         goto PerlException;
14421       }
14422     reference=SvRV(ST(0));
14423     hv=SvSTASH(reference);
14424     av=newAV();
14425     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
14426     SvREFCNT_dec(av);
14427     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14428     if (image == (Image *) NULL)
14429       {
14430         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14431           PackageName);
14432         goto PerlException;
14433       }
14434     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
14435     /*
14436       Get attribute.
14437     */
14438     crop_geometry=(char *) NULL;
14439     geometry=(char *) NULL;
14440     for (i=2; i < items; i+=2)
14441     {
14442       attribute=(char *) SvPV(ST(i-1),na);
14443       switch (*attribute)
14444       {
14445         case 'c':
14446         case 'C':
14447         {
14448           if (LocaleCompare(attribute,"crop") == 0)
14449             {
14450               crop_geometry=SvPV(ST(i),na);
14451               break;
14452             }
14453           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14454             attribute);
14455           break;
14456         }
14457         case 'g':
14458         case 'G':
14459         {
14460           if (LocaleCompare(attribute,"geometry") == 0)
14461             {
14462               geometry=SvPV(ST(i),na);
14463               break;
14464             }
14465           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14466             attribute);
14467           break;
14468         }
14469         default:
14470         {
14471           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
14472             attribute);
14473           break;
14474         }
14475       }
14476     }
14477     for ( ; image; image=image->next)
14478     {
14479       clone=CloneImage(image,0,0,MagickTrue,exception);
14480       if (clone == (Image *) NULL)
14481         goto PerlException;
14482       TransformImage(&clone,crop_geometry,geometry,exception);
14483       for ( ; clone; clone=clone->next)
14484       {
14485         AddImageToRegistry(sv,clone);
14486         rv=newRV(sv);
14487         av_push(av,sv_bless(rv,hv));
14488         SvREFCNT_dec(sv);
14489       }
14490     }
14491     exception=DestroyExceptionInfo(exception);
14492     ST(0)=av_reference;
14493     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
14494     XSRETURN(1);
14495
14496   PerlException:
14497     InheritPerlException(exception,perl_exception);
14498     exception=DestroyExceptionInfo(exception);
14499     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
14500     SvPOK_on(perl_exception);
14501     ST(0)=sv_2mortal(perl_exception);
14502     XSRETURN(1);
14503   }
14504 \f
14505 #
14506 ###############################################################################
14507 #                                                                             #
14508 #                                                                             #
14509 #                                                                             #
14510 #   W r i t e                                                                 #
14511 #                                                                             #
14512 #                                                                             #
14513 #                                                                             #
14514 ###############################################################################
14515 #
14516 #
14517 void
14518 Write(ref,...)
14519   Image::Magick ref=NO_INIT
14520   ALIAS:
14521     WriteImage    = 1
14522     write         = 2
14523     writeimage    = 3
14524   PPCODE:
14525   {
14526     char
14527       filename[MagickPathExtent];
14528
14529     ExceptionInfo
14530       *exception;
14531
14532     Image
14533       *image,
14534       *next;
14535
14536     register ssize_t
14537       i;
14538
14539     ssize_t
14540       number_images,
14541       scene;
14542
14543     struct PackageInfo
14544       *info,
14545       *package_info;
14546
14547     SV
14548       *perl_exception,
14549       *reference;
14550
14551     PERL_UNUSED_VAR(ref);
14552     PERL_UNUSED_VAR(ix);
14553     exception=AcquireExceptionInfo();
14554     perl_exception=newSVpv("",0);
14555     number_images=0;
14556     package_info=(struct PackageInfo *) NULL;
14557     if (sv_isobject(ST(0)) == 0)
14558       {
14559         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
14560           PackageName);
14561         goto PerlException;
14562       }
14563     reference=SvRV(ST(0));
14564     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
14565     if (image == (Image *) NULL)
14566       {
14567         ThrowPerlException(exception,OptionError,"NoImagesDefined",
14568           PackageName);
14569         goto PerlException;
14570       }
14571     package_info=ClonePackageInfo(info,exception);
14572     if (items == 2)
14573       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
14574     else
14575       if (items > 2)
14576         for (i=2; i < items; i+=2)
14577           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
14578             exception);
14579     (void) CopyMagickString(filename,package_info->image_info->filename,
14580       MagickPathExtent);
14581     scene=0;
14582     for (next=image; next; next=next->next)
14583     {
14584       (void) CopyMagickString(next->filename,filename,MagickPathExtent);
14585       next->scene=scene++;
14586     }
14587     *package_info->image_info->magick='\0';
14588     SetImageInfo(package_info->image_info,(unsigned int)
14589       GetImageListLength(image),exception);
14590     for (next=image; next; next=next->next)
14591     {
14592       (void) WriteImage(package_info->image_info,next,exception);
14593       number_images++;
14594       if (package_info->image_info->adjoin)
14595         break;
14596     }
14597
14598   PerlException:
14599     if (package_info != (struct PackageInfo *) NULL)
14600       DestroyPackageInfo(package_info);
14601     InheritPerlException(exception,perl_exception);
14602     exception=DestroyExceptionInfo(exception);
14603     sv_setiv(perl_exception,(IV) number_images);
14604     SvPOK_on(perl_exception);
14605     ST(0)=sv_2mortal(perl_exception);
14606     XSRETURN(1);
14607   }