]> granicus.if.org Git - imagemagick/blob - PerlMagick/Magick.xs
10c979a524517ca53dbbbf4e9fc445c6de608f4f
[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 %                              John Cristy                                    %
23 %                             February 1997                                   %
24 %                                                                             %
25 %                                                                             %
26 %  Copyright 1999-2011 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(WIN32)
52 #define MagickExport
53 #endif
54
55 #if defined(__cplusplus) || defined(c_plusplus)
56 extern "C" {
57 #endif
58
59 #define PERL_NO_GET_CONTEXT
60 #include "EXTERN.h"
61 #include "perl.h"
62 #include "XSUB.h"
63 #include <math.h>
64 #include <MagickCore/MagickCore.h>
65 #undef tainted
66
67 #if defined(__cplusplus) || defined(c_plusplus)
68 }
69 #endif
70 \f
71 /*
72   Define declarations.
73 */
74 #ifndef aTHX_
75 #define aTHX_
76 #define pTHX_
77 #define dTHX
78 #endif
79 #define DegreesToRadians(x)  (MagickPI*(x)/180.0)
80 #define EndOf(array)  (&array[NumberOf(array)])
81 #define MaxArguments  33
82 #ifndef na
83 #define na  PL_na
84 #endif
85 #define NumberOf(array)  (sizeof(array)/sizeof(*array))
86 #define PackageName   "Image::Magick"
87 #if PERL_VERSION <= 6
88 #define PerlIO  FILE
89 #define PerlIO_importFILE(f, fl)  (f)
90 #define PerlIO_findFILE(f)  NULL
91 #endif
92 #ifndef sv_undef
93 #define sv_undef  PL_sv_undef
94 #endif
95
96 #define AddImageToRegistry(sv,image) \
97 { \
98   if (magick_registry != (SplayTreeInfo *) NULL) \
99     { \
100       (void) AddValueToSplayTree(magick_registry,image,image); \
101       (sv)=newSViv((IV) image); \
102     } \
103 }
104
105 #define DeleteImageFromRegistry(reference,image) \
106 { \
107   if (magick_registry != (SplayTreeInfo *) NULL) \
108     { \
109       if (GetImageReferenceCount(image) == 1) \
110        (void) DeleteNodeByValueFromSplayTree(magick_registry,image); \
111       image=DestroyImage(image); \
112       sv_setiv(reference,0); \
113     } \
114 }
115
116 #define InheritPerlException(exception,perl_exception) \
117 { \
118   char \
119     message[MaxTextExtent]; \
120  \
121   if ((exception)->severity != UndefinedException) \
122     { \
123       (void) FormatLocaleString(message,MaxTextExtent,"Exception %d: %s%s%s%s",\
124         (exception)->severity, (exception)->reason ? \
125         GetLocaleExceptionMessage((exception)->severity,(exception)->reason) : \
126         "Unknown", (exception)->description ? " (" : "", \
127         (exception)->description ? GetLocaleExceptionMessage( \
128         (exception)->severity,(exception)->description) : "", \
129         (exception)->description ? ")" : ""); \
130       if ((perl_exception) != (SV *) NULL) \
131         { \
132           if (SvCUR(perl_exception)) \
133             sv_catpv(perl_exception,"\n"); \
134           sv_catpv(perl_exception,message); \
135         } \
136     } \
137 }
138
139 #define ThrowPerlException(exception,severity,tag,reason) \
140   (void) ThrowMagickException(exception,GetMagickModule(),severity, \
141     tag,"`%s'",reason); \
142 \f
143 /*
144   Typedef and structure declarations.
145 */
146 typedef enum
147 {
148   ArrayReference = (~0),
149   RealReference = (~0)-1,
150   FileReference = (~0)-2,
151   ImageReference = (~0)-3,
152   IntegerReference = (~0)-4,
153   StringReference = (~0)-5
154 } MagickReference;
155
156 typedef struct _Arguments
157 {
158   const char
159     *method;
160
161   ssize_t
162     type;
163 } Arguments;
164
165 struct ArgumentList
166 {
167   ssize_t
168     integer_reference;
169
170   MagickRealType
171     real_reference;
172
173   const char
174     *string_reference;
175
176   Image
177     *image_reference;
178
179   SV
180     *array_reference;
181
182   FILE
183     *file_reference;
184
185   size_t
186     length;
187 };
188
189 struct PackageInfo
190 {
191   ImageInfo
192     *image_info;
193 };
194
195 typedef void
196   *Image__Magick;  /* data type for the Image::Magick package */
197 \f
198 /*
199   Static declarations.
200 */
201 static struct
202   Methods
203   {
204     const char
205       *name;
206
207     Arguments
208       arguments[MaxArguments];
209   } Methods[] =
210   {
211     { "Comment", { {"comment", StringReference} } },
212     { "Label", { {"label", StringReference} } },
213     { "AddNoise", { {"noise", MagickNoiseOptions},
214       {"channel", MagickChannelOptions} } },
215     { "Colorize", { {"fill", StringReference}, {"opacity", StringReference} } },
216     { "Border", { {"geometry", StringReference}, {"width", IntegerReference},
217       {"height", IntegerReference}, {"fill", StringReference},
218       {"bordercolor", StringReference}, {"color", StringReference},
219       {"compose", MagickComposeOptions} } },
220     { "Blur", { {"geometry", StringReference}, {"radius", RealReference},
221       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
222     { "Chop", { {"geometry", StringReference}, {"width", IntegerReference},
223       {"height", IntegerReference}, {"x", IntegerReference},
224       {"y", IntegerReference} } },
225     { "Crop", { {"geometry", StringReference}, {"width", IntegerReference},
226       {"height", IntegerReference}, {"x", IntegerReference},
227       {"y", IntegerReference}, {"fuzz", StringReference},
228       {"gravity", MagickGravityOptions} } },
229     { "Despeckle", },
230     { "Edge", { {"radius", RealReference} } },
231     { "Emboss", { {"geometry", StringReference}, {"radius", RealReference},
232       {"sigma", RealReference} } },
233     { "Enhance", },
234     { "Flip", },
235     { "Flop", },
236     { "Frame", { {"geometry", StringReference}, {"width", IntegerReference},
237       {"height", IntegerReference}, {"inner", IntegerReference},
238       {"outer", IntegerReference}, {"fill", StringReference},
239       {"color", StringReference}, {"compose", MagickComposeOptions} } },
240     { "Implode", { {"amount", RealReference},
241       {"interpolate", MagickInterpolateOptions} } },
242     { "Magnify", },
243     { "MedianFilter", { {"geometry", StringReference},
244       {"width", IntegerReference},{"height", IntegerReference},
245       {"channel", MagickChannelOptions} } },
246     { "Minify", },
247     { "OilPaint", { {"radius", RealReference} } },
248     { "ReduceNoise", { {"geometry", StringReference},
249       {"width", IntegerReference},{"height", IntegerReference},
250       {"channel", MagickChannelOptions} } },
251     { "Roll", { {"geometry", StringReference}, {"x", IntegerReference},
252       {"y", IntegerReference} } },
253     { "Rotate", { {"degrees", RealReference}, {"fill", StringReference},
254       {"color", StringReference}, {"background", StringReference} } },
255     { "Sample", { {"geometry", StringReference}, {"width", IntegerReference},
256       {"height", IntegerReference} } },
257     { "Scale", { {"geometry", StringReference}, {"width", IntegerReference},
258       {"height", IntegerReference} } },
259     { "Shade", { {"geometry", StringReference}, {"azimuth", RealReference},
260       {"elevation", RealReference}, {"gray", MagickBooleanOptions} } },
261     { "Sharpen", { {"geometry", StringReference}, {"radius", RealReference},
262       {"sigma", RealReference}, {"channel", MagickChannelOptions} } },
263     { "Shear", { {"geometry", StringReference}, {"x", RealReference},
264       {"y", RealReference}, { "fill", StringReference},
265       {"color", StringReference} } },
266     { "Spread", { {"radius", RealReference} } },
267     { "Swirl", { {"degrees", RealReference},
268       {"interpolate", MagickInterpolateOptions} } },
269     { "Resize", { {"geometry", StringReference}, {"width", IntegerReference},
270       {"height", IntegerReference}, {"filter", MagickFilterOptions},
271       {"support", StringReference }, {"blur", RealReference } } },
272     { "Zoom", { {"geometry", StringReference}, {"width", IntegerReference},
273       {"height", IntegerReference}, {"filter", MagickFilterOptions},
274       {"support", RealReference }, {"blur", RealReference } } },
275     { "Annotate", { {"text", StringReference}, {"font", StringReference},
276       {"pointsize", RealReference}, {"density", StringReference},
277       {"undercolor", StringReference}, {"stroke", StringReference},
278       {"fill", StringReference}, {"geometry", StringReference},
279       {"pen", StringReference}, {"x", RealReference},
280       {"y", RealReference}, {"gravity", MagickGravityOptions},
281       {"translate", StringReference}, {"scale", StringReference},
282       {"rotate", RealReference}, {"skewX", RealReference},
283       {"skewY", RealReference}, {"strokewidth", RealReference},
284       {"antialias", MagickBooleanOptions}, {"family", StringReference},
285       {"style", MagickStyleOptions}, {"stretch", MagickStretchOptions},
286       {"weight", IntegerReference}, {"align", MagickAlignOptions},
287       {"encoding", StringReference}, {"affine", ArrayReference},
288       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
289       {"tile", ImageReference}, {"kerning", RealReference},
290       {"interline-spacing", RealReference},
291       {"interword-spacing", RealReference},
292       {"direction", MagickDirectionOptions} } },
293     { "ColorFloodfill", { {"geometry", StringReference},
294       {"x", IntegerReference}, {"y", IntegerReference},
295       {"fill", StringReference}, {"bordercolor", StringReference},
296       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
297     { "Composite", { {"image", ImageReference},
298       {"compose", MagickComposeOptions}, {"geometry", StringReference},
299       {"x", IntegerReference}, {"y", IntegerReference},
300       {"gravity", MagickGravityOptions}, {"opacity", StringReference},
301       {"tile", MagickBooleanOptions}, {"rotate", RealReference},
302       {"color", StringReference}, {"mask", ImageReference},
303       {"channel", MagickChannelOptions},
304       {"interpolate", MagickInterpolateOptions}, {"args", StringReference},
305       {"blend", StringReference} } },
306     { "Contrast", { {"sharpen", MagickBooleanOptions} } },
307     { "CycleColormap", { {"display", IntegerReference} } },
308     { "Draw", { {"primitive", MagickPrimitiveOptions},
309       {"points", StringReference}, {"method", MagickMethodOptions},
310       {"stroke", StringReference}, {"fill", StringReference},
311       {"strokewidth", RealReference}, {"font", StringReference},
312       {"bordercolor", StringReference}, {"x", RealReference},
313       {"y", RealReference}, {"translate", StringReference},
314       {"scale", StringReference}, {"rotate", RealReference},
315       {"skewX", RealReference}, {"skewY", RealReference},
316       {"tile", ImageReference}, {"pointsize", RealReference},
317       {"antialias", MagickBooleanOptions}, {"density", StringReference},
318       {"linewidth", RealReference}, {"affine", ArrayReference},
319       {"stroke-dashoffset", RealReference},
320       {"stroke-dasharray", ArrayReference},
321       {"interpolate", MagickInterpolateOptions},
322       {"origin", StringReference}, {"text", StringReference},
323       {"fill-pattern", ImageReference}, {"stroke-pattern", ImageReference},
324       {"vector-graphics", StringReference}, {"kerning", RealReference},
325       {"interline-spacing", RealReference},
326       {"interword-spacing", RealReference},
327       {"direction", MagickDirectionOptions} } },
328     { "Equalize", { {"channel", MagickChannelOptions} } },
329     { "Gamma", { {"gamma", StringReference}, {"channel", MagickChannelOptions},
330       {"red", RealReference}, {"green", RealReference},
331       {"blue", RealReference} } },
332     { "Map", { {"image", ImageReference}, {"dither", MagickBooleanOptions},
333       {"dither-method", MagickDitherOptions} } },
334     { "MatteFloodfill", { {"geometry", StringReference},
335       {"x", IntegerReference}, {"y", IntegerReference},
336       {"opacity", StringReference}, {"bordercolor", StringReference},
337       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
338     { "Modulate", { {"factor", StringReference}, {"hue", RealReference},
339       {"saturation", RealReference}, {"whiteness", RealReference},
340       {"brightness", RealReference}, {"lightness", RealReference},
341       {"blackness", RealReference} } },
342     { "Negate", { {"gray", MagickBooleanOptions},
343       {"channel", MagickChannelOptions} } },
344     { "Normalize", { {"channel", MagickChannelOptions} } },
345     { "NumberColors", },
346     { "Opaque", { {"color", StringReference}, {"fill", StringReference},
347       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
348       {"invert", MagickBooleanOptions} } },
349     { "Quantize", { {"colors", IntegerReference},
350       {"treedepth", IntegerReference}, {"colorspace", MagickColorspaceOptions},
351       {"dither", MagickBooleanOptions}, {"measure", MagickBooleanOptions},
352       {"global", MagickBooleanOptions}, {"transparent-color", StringReference},
353       {"dither-method", MagickDitherOptions} } },
354     { "Raise", { {"geometry", StringReference}, {"width", IntegerReference},
355       {"height", IntegerReference}, {"raise", MagickBooleanOptions} } },
356     { "Segment", { {"geometry", StringReference},
357       {"cluster-threshold", RealReference},
358       {"smoothing-threshold", RealReference},
359       {"colorspace", MagickColorspaceOptions},
360       {"verbose", MagickBooleanOptions} } },
361     { "Signature", },
362     { "Solarize", { {"geometry", StringReference},
363       {"threshold", StringReference} } },
364     { "Sync", },
365     { "Texture", { {"texture", ImageReference} } },
366     { "Evaluate", { {"value", RealReference},
367       {"operator", MagickEvaluateOptions},
368       {"channel", MagickChannelOptions} } },
369     { "Transparent", { {"color", StringReference}, {"opacity", StringReference},
370       {"fuzz", StringReference}, {"invert", MagickBooleanOptions} } },
371     { "Threshold", { {"threshold", StringReference},
372       {"channel", MagickChannelOptions} } },
373     { "Charcoal", { {"geometry", StringReference}, {"radius", RealReference},
374       {"sigma", RealReference} } },
375     { "Trim", { {"fuzz", StringReference} } },
376     { "Wave", { {"geometry", StringReference}, {"amplitude", RealReference},
377       {"wavelength", RealReference},
378       {"interpolate", MagickInterpolateOptions} } },
379     { "Separate", { {"channel", MagickChannelOptions} } },
380     { "Condense", },
381     { "Stereo", { {"image", ImageReference}, {"x", IntegerReference},
382       {"y", IntegerReference} } },
383     { "Stegano", { {"image", ImageReference}, {"offset", IntegerReference} } },
384     { "Deconstruct", },
385     { "GaussianBlur", { {"geometry", StringReference},
386       {"radius", RealReference}, {"sigma", RealReference},
387       {"channel", MagickChannelOptions} } },
388     { "Convolve", { {"coefficients", ArrayReference},
389       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
390     { "Profile", { {"name", StringReference}, {"profile", StringReference},
391       { "rendering-intent", MagickIntentOptions},
392       { "black-point-compensation", MagickBooleanOptions} } },
393     { "UnsharpMask", { {"geometry", StringReference},
394       {"radius", RealReference}, {"sigma", RealReference},
395       {"amount", RealReference}, {"threshold", RealReference},
396       {"channel", MagickChannelOptions} } },
397     { "MotionBlur", { {"geometry", StringReference},
398       {"radius", RealReference}, {"sigma", RealReference},
399       {"angle", RealReference}, {"channel", MagickChannelOptions} } },
400     { "OrderedDither", { {"threshold", StringReference},
401       {"channel", MagickChannelOptions} } },
402     { "Shave", { {"geometry", StringReference}, {"width", IntegerReference},
403       {"height", IntegerReference} } },
404     { "Level", { {"levels", StringReference}, {"black-point", RealReference},
405       {"white-point", RealReference}, {"gamma", RealReference},
406       {"channel", MagickChannelOptions}, {"level", StringReference} } },
407     { "Clip", { {"id", StringReference}, {"inside", MagickBooleanOptions} } },
408     { "AffineTransform", { {"affine", ArrayReference},
409       {"translate", StringReference}, {"scale", StringReference},
410       {"rotate", RealReference}, {"skewX", RealReference},
411       {"skewY", RealReference}, {"interpolate", MagickInterpolateOptions},
412       {"background", StringReference} } },
413     { "Difference", { {"image", ImageReference}, {"fuzz", StringReference} } },
414     { "AdaptiveThreshold", { {"geometry", StringReference},
415       {"width", IntegerReference}, {"height", IntegerReference},
416       {"offset", IntegerReference} } },
417     { "Resample", { {"density", StringReference}, {"x", RealReference},
418       {"y", RealReference}, {"filter", MagickFilterOptions},
419       {"support", RealReference }, {"blur", RealReference } } },
420     { "Describe", { {"file", FileReference} } },
421     { "BlackThreshold", { {"threshold", StringReference},
422       {"channel", MagickChannelOptions} } },
423     { "WhiteThreshold", { {"threshold", StringReference},
424       {"channel", MagickChannelOptions} } },
425     { "RadialBlur", { {"geometry", StringReference}, {"angle", RealReference},
426       {"channel", MagickChannelOptions} } },
427     { "Thumbnail", { {"geometry", StringReference}, {"width", IntegerReference},
428       {"height", IntegerReference} } },
429     { "Strip", },
430     { "Tint", { {"fill", StringReference}, {"opacity", StringReference} } },
431     { "Channel", { {"channel", MagickChannelOptions} } },
432     { "Splice", { {"geometry", StringReference}, {"width", IntegerReference},
433       {"height", IntegerReference}, {"x", IntegerReference},
434       {"y", IntegerReference}, {"fuzz", StringReference},
435       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
436     { "Posterize", { {"levels", IntegerReference},
437       {"dither", MagickBooleanOptions} } },
438     { "Shadow", { {"geometry", StringReference}, {"opacity", RealReference},
439       {"sigma", RealReference}, {"x", IntegerReference},
440       {"y", IntegerReference} } },
441     { "Identify", { {"file", FileReference}, {"features", StringReference},
442       {"unique", MagickBooleanOptions} } },
443     { "SepiaTone", { {"threshold", RealReference} } },
444     { "SigmoidalContrast", { {"geometry", StringReference},
445       {"contrast", RealReference}, {"mid-point", RealReference},
446       {"channel", MagickChannelOptions}, {"sharpen", MagickBooleanOptions} } },
447     { "Extent", { {"geometry", StringReference}, {"width", IntegerReference},
448       {"height", IntegerReference}, {"x", IntegerReference},
449       {"y", IntegerReference}, {"fuzz", StringReference},
450       {"background", StringReference}, {"gravity", MagickGravityOptions} } },
451     { "Vignette", { {"geometry", StringReference}, {"radius", RealReference},
452       {"sigma", RealReference}, {"x", IntegerReference},
453       {"y", IntegerReference}, {"background", StringReference} } },
454     { "ContrastStretch", { {"levels", StringReference},
455       {"black-point", RealReference},{"white-point", RealReference},
456       {"channel", MagickChannelOptions} } },
457     { "Sans0", },
458     { "Sans1", },
459     { "AdaptiveSharpen", { {"geometry", StringReference},
460       {"radius", RealReference}, {"sigma", RealReference},
461       {"channel", MagickChannelOptions} } },
462     { "Transpose", },
463     { "Transverse", },
464     { "AutoOrient", },
465     { "AdaptiveBlur", { {"geometry", StringReference},
466       {"radius", RealReference}, {"sigma", RealReference},
467       {"channel", MagickChannelOptions} } },
468     { "Sketch", { {"geometry", StringReference},
469       {"radius", RealReference}, {"sigma", RealReference},
470       {"angle", RealReference} } },
471     { "UniqueColors", },
472     { "AdaptiveResize", { {"geometry", StringReference},
473       {"width", IntegerReference}, {"height", IntegerReference},
474       {"filter", MagickFilterOptions}, {"support", StringReference },
475       {"blur", RealReference } } },
476     { "ClipMask", { {"mask", ImageReference} } },
477     { "LinearStretch", { {"levels", StringReference},
478       {"black-point", RealReference},{"white-point", RealReference} } },
479     { "Recolor", { {"matrix", ArrayReference} } },
480     { "Mask", { {"mask", ImageReference} } },
481     { "Polaroid", { {"caption", StringReference}, {"angle", RealReference},
482       {"font", StringReference}, {"stroke", StringReference},
483       {"fill", StringReference}, {"strokewidth", RealReference},
484       {"pointsize", RealReference}, {"gravity", MagickGravityOptions},
485       {"background", StringReference} } },
486     { "FloodfillPaint", { {"geometry", StringReference},
487       {"x", IntegerReference}, {"y", IntegerReference},
488       {"fill", StringReference}, {"bordercolor", StringReference},
489       {"fuzz", StringReference}, {"channel", MagickChannelOptions},
490       {"invert", MagickBooleanOptions} } },
491     { "Distort", { {"points", ArrayReference}, {"method", MagickDistortOptions},
492       {"virtual-pixel", MagickVirtualPixelOptions},
493       {"best-fit", MagickBooleanOptions} } },
494     { "Clut", { {"image", ImageReference},
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}, {"dither", MagickBooleanOptions},
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     { "Filter", { {"kernel", StringReference},
529       {"channel", MagickChannelOptions}, {"bias", StringReference} } },
530     { "BrightnessContrast", { {"levels", StringReference},
531       {"brightness", RealReference},{"contrast", RealReference},
532       {"channel", MagickChannelOptions} } },
533     { "Morphology", { {"kernel", StringReference},
534       {"channel", MagickChannelOptions}, {"method", MagickMorphologyOptions},
535       {"iterations", IntegerReference} } },
536     { "ColorMatrix", { {"matrix", ArrayReference} } },
537     { "Color", { {"color", StringReference} } },
538     { "Mode", { {"geometry", StringReference},
539       {"width", IntegerReference},{"height", IntegerReference},
540       {"channel", MagickChannelOptions} } },
541     { "Statistic", { {"geometry", StringReference},
542       {"width", IntegerReference},{"height", IntegerReference},
543       {"channel", MagickChannelOptions}, {"type", MagickStatisticOptions} } }
544   };
545
546 static SplayTreeInfo
547   *magick_registry = (SplayTreeInfo *) NULL;
548 \f
549 /*
550   Forward declarations.
551 */
552 static Image
553   *SetupList(pTHX_ SV *,struct PackageInfo **,SV ***,ExceptionInfo *);
554
555 static ssize_t
556   strEQcase(const char *,const char *);
557 \f
558 /*
559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 %                                                                             %
561 %                                                                             %
562 %                                                                             %
563 %   C l o n e P a c k a g e I n f o                                           %
564 %                                                                             %
565 %                                                                             %
566 %                                                                             %
567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
568 %
569 %  ClonePackageInfo makes a duplicate of the given info, or if info is NULL,
570 %  a new one.
571 %
572 %  The format of the ClonePackageInfo routine is:
573 %
574 %      struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
575 %        exception)
576 %
577 %  A description of each parameter follows:
578 %
579 %    o info: a structure of type info.
580 %
581 %    o exception: Return any errors or warnings in this structure.
582 %
583 */
584 static struct PackageInfo *ClonePackageInfo(struct PackageInfo *info,
585   ExceptionInfo *exception)
586 {
587   struct PackageInfo
588     *clone_info;
589
590   clone_info=(struct PackageInfo *) AcquireQuantumMemory(1,sizeof(*clone_info));
591   if (clone_info == (struct PackageInfo *) NULL)
592     {
593       ThrowPerlException(exception,ResourceLimitError,
594         "UnableToClonePackageInfo",PackageName);
595       return((struct PackageInfo *) NULL);
596     }
597   if (info == (struct PackageInfo *) NULL)
598     {
599       clone_info->image_info=CloneImageInfo((ImageInfo *) NULL);
600       return(clone_info);
601     }
602   *clone_info=(*info);
603   clone_info->image_info=CloneImageInfo(info->image_info);
604   return(clone_info);
605 }
606 \f
607 /*
608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 %                                                                             %
610 %                                                                             %
611 %                                                                             %
612 %   c o n s t a n t                                                           %
613 %                                                                             %
614 %                                                                             %
615 %                                                                             %
616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617 %
618 %  constant() returns a double value for the specified name.
619 %
620 %  The format of the constant routine is:
621 %
622 %      double constant(char *name,ssize_t sans)
623 %
624 %  A description of each parameter follows:
625 %
626 %    o value: Method constant returns a double value for the specified name.
627 %
628 %    o name: The name of the constant.
629 %
630 %    o sans: This integer value is not used.
631 %
632 */
633 static double constant(char *name,ssize_t sans)
634 {
635   (void) sans;
636   errno=0;
637   switch (*name)
638   {
639     case 'B':
640     {
641       if (strEQ(name,"BlobError"))
642         return(BlobError);
643       if (strEQ(name,"BlobWarning"))
644         return(BlobWarning);
645       break;
646     }
647     case 'C':
648     {
649       if (strEQ(name,"CacheError"))
650         return(CacheError);
651       if (strEQ(name,"CacheWarning"))
652         return(CacheWarning);
653       if (strEQ(name,"CoderError"))
654         return(CoderError);
655       if (strEQ(name,"CoderWarning"))
656         return(CoderWarning);
657       if (strEQ(name,"ConfigureError"))
658         return(ConfigureError);
659       if (strEQ(name,"ConfigureWarning"))
660         return(ConfigureWarning);
661       if (strEQ(name,"CorruptImageError"))
662         return(CorruptImageError);
663       if (strEQ(name,"CorruptImageWarning"))
664         return(CorruptImageWarning);
665       break;
666     }
667     case 'D':
668     {
669       if (strEQ(name,"DelegateError"))
670         return(DelegateError);
671       if (strEQ(name,"DelegateWarning"))
672         return(DelegateWarning);
673       if (strEQ(name,"DrawError"))
674         return(DrawError);
675       if (strEQ(name,"DrawWarning"))
676         return(DrawWarning);
677       break;
678     }
679     case 'E':
680     {
681       if (strEQ(name,"ErrorException"))
682         return(ErrorException);
683       if (strEQ(name,"ExceptionError"))
684         return(CoderError);
685       if (strEQ(name,"ExceptionWarning"))
686         return(CoderWarning);
687       break;
688     }
689     case 'F':
690     {
691       if (strEQ(name,"FatalErrorException"))
692         return(FatalErrorException);
693       if (strEQ(name,"FileOpenError"))
694         return(FileOpenError);
695       if (strEQ(name,"FileOpenWarning"))
696         return(FileOpenWarning);
697       break;
698     }
699     case 'I':
700     {
701       if (strEQ(name,"ImageError"))
702         return(ImageError);
703       if (strEQ(name,"ImageWarning"))
704         return(ImageWarning);
705       break;
706     }
707     case 'M':
708     {
709       if (strEQ(name,"MaxRGB"))
710         return(QuantumRange);
711       if (strEQ(name,"MissingDelegateError"))
712         return(MissingDelegateError);
713       if (strEQ(name,"MissingDelegateWarning"))
714         return(MissingDelegateWarning);
715       if (strEQ(name,"ModuleError"))
716         return(ModuleError);
717       if (strEQ(name,"ModuleWarning"))
718         return(ModuleWarning);
719       break;
720     }
721     case 'O':
722     {
723       if (strEQ(name,"Opaque"))
724         return(OpaqueAlpha);
725       if (strEQ(name,"OptionError"))
726         return(OptionError);
727       if (strEQ(name,"OptionWarning"))
728         return(OptionWarning);
729       break;
730     }
731     case 'Q':
732     {
733       if (strEQ(name,"MAGICKCORE_QUANTUM_DEPTH"))
734         return(MAGICKCORE_QUANTUM_DEPTH);
735       if (strEQ(name,"QuantumDepth"))
736         return(MAGICKCORE_QUANTUM_DEPTH);
737       if (strEQ(name,"QuantumRange"))
738         return(QuantumRange);
739       break;
740     }
741     case 'R':
742     {
743       if (strEQ(name,"ResourceLimitError"))
744         return(ResourceLimitError);
745       if (strEQ(name,"ResourceLimitWarning"))
746         return(ResourceLimitWarning);
747       if (strEQ(name,"RegistryError"))
748         return(RegistryError);
749       if (strEQ(name,"RegistryWarning"))
750         return(RegistryWarning);
751       break;
752     }
753     case 'S':
754     {
755       if (strEQ(name,"StreamError"))
756         return(StreamError);
757       if (strEQ(name,"StreamWarning"))
758         return(StreamWarning);
759       if (strEQ(name,"Success"))
760         return(0);
761       break;
762     }
763     case 'T':
764     {
765       if (strEQ(name,"Transparent"))
766         return(TransparentAlpha);
767       if (strEQ(name,"TypeError"))
768         return(TypeError);
769       if (strEQ(name,"TypeWarning"))
770         return(TypeWarning);
771       break;
772     }
773     case 'W':
774     {
775       if (strEQ(name,"WarningException"))
776         return(WarningException);
777       break;
778     }
779     case 'X':
780     {
781       if (strEQ(name,"XServerError"))
782         return(XServerError);
783       if (strEQ(name,"XServerWarning"))
784         return(XServerWarning);
785       break;
786     }
787   }
788   errno=EINVAL;
789   return(0);
790 }
791 \f
792 /*
793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
794 %                                                                             %
795 %                                                                             %
796 %                                                                             %
797 %   D e s t r o y P a c k a g e I n f o                                       %
798 %                                                                             %
799 %                                                                             %
800 %                                                                             %
801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 %
803 %  Method DestroyPackageInfo frees a previously created info structure.
804 %
805 %  The format of the DestroyPackageInfo routine is:
806 %
807 %      DestroyPackageInfo(struct PackageInfo *info)
808 %
809 %  A description of each parameter follows:
810 %
811 %    o info: a structure of type info.
812 %
813 */
814 static void DestroyPackageInfo(struct PackageInfo *info)
815 {
816   info->image_info=DestroyImageInfo(info->image_info);
817   info=(struct PackageInfo *) RelinquishMagickMemory(info);
818 }
819 \f
820 /*
821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
822 %                                                                             %
823 %                                                                             %
824 %                                                                             %
825 %   G e t L i s t                                                             %
826 %                                                                             %
827 %                                                                             %
828 %                                                                             %
829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
830 %
831 %  Method GetList is recursively called by SetupList to traverse the
832 %  Image__Magick reference.  If building an reference_vector (see SetupList),
833 %  *current is the current position in *reference_vector and *last is the final
834 %  entry in *reference_vector.
835 %
836 %  The format of the GetList routine is:
837 %
838 %      GetList(info)
839 %
840 %  A description of each parameter follows:
841 %
842 %    o info: a structure of type info.
843 %
844 */
845 static Image *GetList(pTHX_ SV *reference,SV ***reference_vector,
846   ssize_t *current,ssize_t *last,ExceptionInfo *exception)
847 {
848   Image
849     *image;
850
851   if (reference == (SV *) NULL)
852     return(NULL);
853   switch (SvTYPE(reference))
854   {
855     case SVt_PVAV:
856     {
857       AV
858         *av;
859
860       Image
861         *head,
862         *previous;
863
864       register ssize_t
865         i;
866
867       ssize_t
868         n;
869
870       /*
871         Array of images.
872       */
873       previous=(Image *) NULL;
874       head=(Image *) NULL;
875       av=(AV *) reference;
876       n=av_len(av);
877       for (i=0; i <= n; i++)
878       {
879         SV
880           **rv;
881
882         rv=av_fetch(av,i,0);
883         if (rv && *rv && sv_isobject(*rv))
884           {
885             image=GetList(aTHX_ SvRV(*rv),reference_vector,current,last,
886               exception);
887             if (image == (Image *) NULL)
888               continue;
889             if (image == previous)
890               {
891                 image=CloneImage(image,0,0,MagickTrue,exception);
892                 if (image == (Image *) NULL)
893                   return(NULL);
894               }
895             image->previous=previous;
896             *(previous ? &previous->next : &head)=image;
897             for (previous=image; previous->next; previous=previous->next) ;
898           }
899       }
900       return(head);
901     }
902     case SVt_PVMG:
903     {
904       /*
905         Blessed scalar, one image.
906       */
907       image=(Image *) SvIV(reference);
908       if (image == (Image *) NULL)
909         return(NULL);
910       image->previous=(Image *) NULL;
911       image->next=(Image *) NULL;
912       if (reference_vector)
913         {
914           if (*current == *last)
915             {
916               *last+=256;
917               if (*reference_vector == (SV **) NULL)
918                 *reference_vector=(SV **) AcquireQuantumMemory(*last,
919                   sizeof(*reference_vector));
920               else
921                 *reference_vector=(SV **) ResizeQuantumMemory(*reference_vector,
922                   *last,sizeof(*reference_vector));
923             }
924           if (*reference_vector == (SV **) NULL)
925             {
926               ThrowPerlException(exception,ResourceLimitError,
927                 "MemoryAllocationFailed",PackageName);
928               return((Image *) NULL);
929             }
930           (*reference_vector)[*current]=reference;
931           (*reference_vector)[++(*current)]=NULL;
932         }
933       return(image);
934     }
935     default:
936       break;
937   }
938   (void) fprintf(stderr,"GetList: UnrecognizedType %.20g\n",
939     (double) SvTYPE(reference));
940   return((Image *) NULL);
941 }
942 \f
943 /*
944 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
945 %                                                                             %
946 %                                                                             %
947 %                                                                             %
948 %   G e t P a c k a g e I n f o                                               %
949 %                                                                             %
950 %                                                                             %
951 %                                                                             %
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
953 %
954 %  Method GetPackageInfo looks up or creates an info structure for the given
955 %  Image__Magick reference.  If it does create a new one, the information in
956 %  package_info is used to initialize it.
957 %
958 %  The format of the GetPackageInfo routine is:
959 %
960 %      struct PackageInfo *GetPackageInfo(void *reference,
961 %        struct PackageInfo *package_info,ExceptionInfo *exception)
962 %
963 %  A description of each parameter follows:
964 %
965 %    o info: a structure of type info.
966 %
967 %    o exception: Return any errors or warnings in this structure.
968 %
969 */
970 static struct PackageInfo *GetPackageInfo(pTHX_ void *reference,
971   struct PackageInfo *package_info,ExceptionInfo *exception)
972 {
973   char
974     message[MaxTextExtent];
975
976   struct PackageInfo
977     *clone_info;
978
979   SV
980     *sv;
981
982   (void) FormatLocaleString(message,MaxTextExtent,"%s::package%s%p",
983     PackageName,XS_VERSION,reference);
984   sv=perl_get_sv(message,(TRUE | 0x02));
985   if (sv == (SV *) NULL)
986     {
987       ThrowPerlException(exception,ResourceLimitError,"UnableToGetPackageInfo",
988         message);
989       return(package_info);
990     }
991   if (SvREFCNT(sv) == 0)
992     (void) SvREFCNT_inc(sv);
993   if (SvIOKp(sv) && (clone_info=(struct PackageInfo *) SvIV(sv)))
994     return(clone_info);
995   clone_info=ClonePackageInfo(package_info,exception);
996   sv_setiv(sv,(IV) clone_info);
997   return(clone_info);
998 }
999 \f
1000 /*
1001 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002 %                                                                             %
1003 %                                                                             %
1004 %                                                                             %
1005 %   S e t A t t r i b u t e                                                   %
1006 %                                                                             %
1007 %                                                                             %
1008 %                                                                             %
1009 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1010 %
1011 %  SetAttribute() sets the attribute to the value in sval.  This can change
1012 %  either or both of image or info.
1013 %
1014 %  The format of the SetAttribute routine is:
1015 %
1016 %      SetAttribute(struct PackageInfo *info,Image *image,char *attribute,
1017 %        SV *sval,ExceptionInfo *exception)
1018 %
1019 %  A description of each parameter follows:
1020 %
1021 %    o list: a list of strings.
1022 %
1023 %    o string: a character string.
1024 %
1025 */
1026
1027 static double SiPrefixToDouble(const char *string,const double interval)
1028 {
1029   char
1030     *q;
1031
1032   double
1033     scale,
1034     value;
1035
1036   value=InterpretLocaleValue(string,&q);
1037   scale=1000.0;
1038   if ((*q != '\0') && (tolower((int) ((unsigned char) *(q+1))) == 'i'))
1039     scale=1024.0;
1040   switch (tolower((int) ((unsigned char) *q)))
1041   {
1042     case '%': value*=pow(scale,0)*interval/100.0; break;
1043     case 'k': value*=pow(scale,1); break;
1044     case 'm': value*=pow(scale,2); break;
1045     case 'g': value*=pow(scale,3); break;
1046     case 't': value*=pow(scale,4); break;
1047     case 'p': value*=pow(scale,5); break;
1048     case 'e': value*=pow(scale,6); break;
1049     case 'z': value*=pow(scale,7); break;
1050     case 'y': value*=pow(scale,8); break;
1051     default:  break;
1052   }
1053   return(value);
1054 }
1055
1056 static inline ssize_t StringToLong(const char *value)
1057 {
1058   return(strtol(value,(char **) NULL,10));
1059 }
1060
1061 static void SetAttribute(pTHX_ struct PackageInfo *info,Image *image,
1062   const char *attribute,SV *sval,ExceptionInfo *exception)
1063 {
1064   GeometryInfo
1065     geometry_info;
1066
1067   long
1068     x,
1069     y;
1070
1071   PixelInfo
1072     pixel;
1073
1074   MagickStatusType
1075     flags;
1076
1077   PixelPacket
1078     *color,
1079     target_color;
1080
1081   ssize_t
1082     sp;
1083
1084   switch (*attribute)
1085   {
1086     case 'A':
1087     case 'a':
1088     {
1089       if (LocaleCompare(attribute,"adjoin") == 0)
1090         {
1091           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1092             SvPV(sval,na)) : SvIV(sval);
1093           if (sp < 0)
1094             {
1095               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1096                 SvPV(sval,na));
1097               break;
1098             }
1099           if (info)
1100             info->image_info->adjoin=sp != 0 ? MagickTrue : MagickFalse;
1101           break;
1102         }
1103       if (LocaleCompare(attribute,"alpha") == 0)
1104         {
1105           sp=SvPOK(sval) ? ParseCommandOption(MagickAlphaOptions,MagickFalse,
1106             SvPV(sval,na)) : SvIV(sval);
1107           if (sp < 0)
1108             {
1109               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1110                 SvPV(sval,na));
1111               break;
1112             }
1113           for ( ; image; image=image->next)
1114             (void) SetImageAlphaChannel(image,(AlphaChannelType) sp);
1115           break;
1116         }
1117       if (LocaleCompare(attribute,"antialias") == 0)
1118         {
1119           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1120             SvPV(sval,na)) : SvIV(sval);
1121           if (sp < 0)
1122             {
1123               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1124                 SvPV(sval,na));
1125               break;
1126             }
1127           if (info)
1128             info->image_info->antialias=sp != 0 ? MagickTrue : MagickFalse;
1129           break;
1130         }
1131       if (LocaleCompare(attribute,"area-limit") == 0)
1132         {
1133           MagickSizeType
1134             limit;
1135
1136           limit=MagickResourceInfinity;
1137           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1138             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1139           (void) SetMagickResourceLimit(AreaResource,limit);
1140           break;
1141         }
1142       if (LocaleCompare(attribute,"attenuate") == 0)
1143         {
1144           if (info)
1145             (void) SetImageOption(info->image_info,attribute,SvPV(sval,na));
1146           break;
1147         }
1148       if (LocaleCompare(attribute,"authenticate") == 0)
1149         {
1150           if (info)
1151             (void) CloneString(&info->image_info->authenticate,SvPV(sval,na));
1152           break;
1153         }
1154       if (info)
1155         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1156       for ( ; image; image=image->next)
1157         SetImageProperty(image,attribute,SvPV(sval,na));
1158       break;
1159     }
1160     case 'B':
1161     case 'b':
1162     {
1163       if (LocaleCompare(attribute,"background") == 0)
1164         {
1165           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1166           if (info)
1167             info->image_info->background_color=target_color;
1168           for ( ; image; image=image->next)
1169             image->background_color=target_color;
1170           break;
1171         }
1172       if (LocaleCompare(attribute,"bias") == 0)
1173         {
1174           for ( ; image; image=image->next)
1175             image->bias=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1176           break;
1177         }
1178       if (LocaleCompare(attribute,"blue-primary") == 0)
1179         {
1180           for ( ; image; image=image->next)
1181           {
1182             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1183             image->chromaticity.blue_primary.x=geometry_info.rho;
1184             image->chromaticity.blue_primary.y=geometry_info.sigma;
1185             if ((flags & SigmaValue) == 0)
1186               image->chromaticity.blue_primary.y=
1187                 image->chromaticity.blue_primary.x;
1188           }
1189           break;
1190         }
1191       if (LocaleCompare(attribute,"bordercolor") == 0)
1192         {
1193           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1194           if (info)
1195             info->image_info->border_color=target_color;
1196           for ( ; image; image=image->next)
1197             image->border_color=target_color;
1198           break;
1199         }
1200       if (info)
1201         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1202       for ( ; image; image=image->next)
1203         SetImageProperty(image,attribute,SvPV(sval,na));
1204       break;
1205     }
1206     case 'C':
1207     case 'c':
1208     {
1209       if (LocaleCompare(attribute,"cache-threshold") == 0)
1210         {
1211           (void) SetMagickResourceLimit(MemoryResource,(MagickSizeType)
1212             SiPrefixToDouble(SvPV(sval,na),100.0));
1213           (void) SetMagickResourceLimit(MapResource,(MagickSizeType)
1214             (2*SiPrefixToDouble(SvPV(sval,na),100.0)));
1215           break;
1216         }
1217       if (LocaleCompare(attribute,"clip-mask") == 0)
1218         {
1219           Image
1220             *clip_mask;
1221
1222           clip_mask=(Image *) NULL;
1223           if (SvPOK(sval))
1224             clip_mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1225           for ( ; image; image=image->next)
1226             SetImageClipMask(image,clip_mask);
1227           break;
1228         }
1229       if (LocaleNCompare(attribute,"colormap",8) == 0)
1230         {
1231           for ( ; image; image=image->next)
1232           {
1233             int
1234               items;
1235
1236             long
1237               i;
1238
1239             if (image->storage_class == DirectClass)
1240               continue;
1241             i=0;
1242             items=sscanf(attribute,"%*[^[][%ld",&i);
1243             (void) items;
1244             if (i > (ssize_t) image->colors)
1245               i%=image->colors;
1246             if ((strchr(SvPV(sval,na),',') == 0) ||
1247                 (strchr(SvPV(sval,na),')') != 0))
1248               QueryColorDatabase(SvPV(sval,na),image->colormap+i,exception);
1249             else
1250               {
1251                 color=image->colormap+i;
1252                 pixel.red=color->red;
1253                 pixel.green=color->green;
1254                 pixel.blue=color->blue;
1255                 flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1256                 pixel.red=geometry_info.rho;
1257                 pixel.green=geometry_info.sigma;
1258                 pixel.blue=geometry_info.xi;
1259                 color->red=ClampToQuantum(pixel.red);
1260                 color->green=ClampToQuantum(pixel.green);
1261                 color->blue=ClampToQuantum(pixel.blue);
1262               }
1263           }
1264           break;
1265         }
1266       if (LocaleCompare(attribute,"colorspace") == 0)
1267         {
1268           sp=SvPOK(sval) ? ParseCommandOption(MagickColorspaceOptions,
1269             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1270           if (sp < 0)
1271             {
1272               ThrowPerlException(exception,OptionError,"UnrecognizedColorspace",
1273                 SvPV(sval,na));
1274               break;
1275             }
1276           for ( ; image; image=image->next)
1277             (void) TransformImageColorspace(image,(ColorspaceType) sp);
1278           break;
1279         }
1280       if (LocaleCompare(attribute,"comment") == 0)
1281         {
1282           for ( ; image; image=image->next)
1283             (void) SetImageProperty(image,"Comment",InterpretImageProperties(
1284               info ? info->image_info : (ImageInfo *) NULL,image,
1285               SvPV(sval,na)));
1286           break;
1287         }
1288       if (LocaleCompare(attribute,"compression") == 0)
1289         {
1290           sp=SvPOK(sval) ? ParseCommandOption(MagickCompressOptions,
1291             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1292           if (sp < 0)
1293             {
1294               ThrowPerlException(exception,OptionError,
1295                 "UnrecognizedImageCompression",SvPV(sval,na));
1296               break;
1297             }
1298           if (info)
1299             info->image_info->compression=(CompressionType) sp;
1300           for ( ; image; image=image->next)
1301             image->compression=(CompressionType) sp;
1302           break;
1303         }
1304       if (info)
1305         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1306       for ( ; image; image=image->next)
1307         SetImageProperty(image,attribute,SvPV(sval,na));
1308       break;
1309     }
1310     case 'D':
1311     case 'd':
1312     {
1313       if (LocaleCompare(attribute,"debug") == 0)
1314         {
1315           SetLogEventMask(SvPV(sval,na));
1316           break;
1317         }
1318       if (LocaleCompare(attribute,"delay") == 0)
1319         {
1320           flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1321           for ( ; image; image=image->next)
1322           {
1323             image->delay=(size_t) floor(geometry_info.rho+0.5);
1324             if ((flags & SigmaValue) != 0)
1325               image->ticks_per_second=(ssize_t)
1326                 floor(geometry_info.sigma+0.5);
1327           }
1328           break;
1329         }
1330       if (LocaleCompare(attribute,"disk-limit") == 0)
1331         {
1332           MagickSizeType
1333             limit;
1334
1335           limit=MagickResourceInfinity;
1336           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1337             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1338           (void) SetMagickResourceLimit(DiskResource,limit);
1339           break;
1340         }
1341       if (LocaleCompare(attribute,"density") == 0)
1342         {
1343           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1344             {
1345               ThrowPerlException(exception,OptionError,"MissingGeometry",
1346                 SvPV(sval,na));
1347               break;
1348             }
1349           if (info)
1350             (void) CloneString(&info->image_info->density,SvPV(sval,na));
1351           for ( ; image; image=image->next)
1352           {
1353             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1354             image->x_resolution=geometry_info.rho;
1355             image->y_resolution=geometry_info.sigma;
1356             if ((flags & SigmaValue) == 0)
1357               image->y_resolution=image->x_resolution;
1358           }
1359           break;
1360         }
1361       if (LocaleCompare(attribute,"depth") == 0)
1362         {
1363           if (info)
1364             info->image_info->depth=SvIV(sval);
1365           for ( ; image; image=image->next)
1366             (void) SetImageDepth(image,SvIV(sval));
1367           break;
1368         }
1369       if (LocaleCompare(attribute,"dispose") == 0)
1370         {
1371           sp=SvPOK(sval) ? ParseCommandOption(MagickDisposeOptions,MagickFalse,
1372             SvPV(sval,na)) : SvIV(sval);
1373           if (sp < 0)
1374             {
1375               ThrowPerlException(exception,OptionError,
1376                 "UnrecognizedDisposeMethod",SvPV(sval,na));
1377               break;
1378             }
1379           for ( ; image; image=image->next)
1380             image->dispose=(DisposeType) sp;
1381           break;
1382         }
1383       if (LocaleCompare(attribute,"dither") == 0)
1384         {
1385           if (info)
1386             {
1387               sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,
1388                 MagickFalse,SvPV(sval,na)) : SvIV(sval);
1389               if (sp < 0)
1390                 {
1391                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
1392                     SvPV(sval,na));
1393                   break;
1394                 }
1395               info->image_info->dither=sp != 0 ? MagickTrue : MagickFalse;
1396             }
1397           break;
1398         }
1399       if (LocaleCompare(attribute,"display") == 0)
1400         {
1401           display:
1402           if (info)
1403             (void) CloneString(&info->image_info->server_name,SvPV(sval,na));
1404           break;
1405         }
1406       if (info)
1407         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1408       for ( ; image; image=image->next)
1409         SetImageProperty(image,attribute,SvPV(sval,na));
1410       break;
1411     }
1412     case 'E':
1413     case 'e':
1414     {
1415       if (LocaleCompare(attribute,"endian") == 0)
1416         {
1417           sp=SvPOK(sval) ? ParseCommandOption(MagickEndianOptions,MagickFalse,
1418             SvPV(sval,na)) : SvIV(sval);
1419           if (sp < 0)
1420             {
1421               ThrowPerlException(exception,OptionError,"UnrecognizedEndianType",
1422                 SvPV(sval,na));
1423               break;
1424             }
1425           if (info)
1426             info->image_info->endian=(EndianType) sp;
1427           for ( ; image; image=image->next)
1428             image->endian=(EndianType) sp;
1429           break;
1430         }
1431       if (LocaleCompare(attribute,"extract") == 0)
1432         {
1433           /*
1434             Set image extract geometry.
1435           */
1436           (void) CloneString(&info->image_info->extract,SvPV(sval,na));
1437           break;
1438         }
1439       if (info)
1440         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1441       for ( ; image; image=image->next)
1442         SetImageProperty(image,attribute,SvPV(sval,na));
1443       break;
1444     }
1445     case 'F':
1446     case 'f':
1447     {
1448       if (LocaleCompare(attribute,"filename") == 0)
1449         {
1450           if (info)
1451             (void) CopyMagickString(info->image_info->filename,SvPV(sval,na),
1452               MaxTextExtent);
1453           for ( ; image; image=image->next)
1454             (void) CopyMagickString(image->filename,SvPV(sval,na),
1455               MaxTextExtent);
1456           break;
1457         }
1458       if (LocaleCompare(attribute,"file") == 0)
1459         {
1460           FILE
1461             *file;
1462
1463           PerlIO
1464             *io_info;
1465
1466           if (info == (struct PackageInfo *) NULL)
1467             break;
1468           io_info=IoIFP(sv_2io(sval));
1469           if (io_info == (PerlIO *) NULL)
1470             {
1471               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1472                 PackageName);
1473               break;
1474             }
1475           file=PerlIO_findFILE(io_info);
1476           if (file == (FILE *) NULL)
1477             {
1478               ThrowPerlException(exception,BlobError,"UnableToOpenFile",
1479                 PackageName);
1480               break;
1481             }
1482           SetImageInfoFile(info->image_info,file);
1483           break;
1484         }
1485       if (LocaleCompare(attribute,"fill") == 0)
1486         {
1487           if (info)
1488             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1489           break;
1490         }
1491       if (LocaleCompare(attribute,"font") == 0)
1492         {
1493           if (info)
1494             (void) CloneString(&info->image_info->font,SvPV(sval,na));
1495           break;
1496         }
1497       if (LocaleCompare(attribute,"foreground") == 0)
1498         break;
1499       if (LocaleCompare(attribute,"fuzz") == 0)
1500         {
1501           if (info)
1502             info->image_info->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1503           for ( ; image; image=image->next)
1504             image->fuzz=SiPrefixToDouble(SvPV(sval,na),QuantumRange);
1505           break;
1506         }
1507       if (info)
1508         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1509       for ( ; image; image=image->next)
1510         SetImageProperty(image,attribute,SvPV(sval,na));
1511       break;
1512     }
1513     case 'G':
1514     case 'g':
1515     {
1516       if (LocaleCompare(attribute,"gamma") == 0)
1517         {
1518           for ( ; image; image=image->next)
1519             image->gamma=SvNV(sval);
1520           break;
1521         }
1522       if (LocaleCompare(attribute,"gravity") == 0)
1523         {
1524           sp=SvPOK(sval) ? ParseCommandOption(MagickGravityOptions,MagickFalse,
1525             SvPV(sval,na)) : SvIV(sval);
1526           if (sp < 0)
1527             {
1528               ThrowPerlException(exception,OptionError,
1529                 "UnrecognizedGravityType",SvPV(sval,na));
1530               break;
1531             }
1532           if (info)
1533             SetImageOption(info->image_info,attribute,SvPV(sval,na));
1534           for ( ; image; image=image->next)
1535             image->gravity=(GravityType) sp;
1536           break;
1537         }
1538       if (LocaleCompare(attribute,"green-primary") == 0)
1539         {
1540           for ( ; image; image=image->next)
1541           {
1542             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1543             image->chromaticity.green_primary.x=geometry_info.rho;
1544             image->chromaticity.green_primary.y=geometry_info.sigma;
1545             if ((flags & SigmaValue) == 0)
1546               image->chromaticity.green_primary.y=
1547                 image->chromaticity.green_primary.x;
1548           }
1549           break;
1550         }
1551       if (info)
1552         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1553       for ( ; image; image=image->next)
1554         SetImageProperty(image,attribute,SvPV(sval,na));
1555       break;
1556     }
1557     case 'I':
1558     case 'i':
1559     {
1560       if (LocaleNCompare(attribute,"index",5) == 0)
1561         {
1562           int
1563             items;
1564
1565           long
1566             index;
1567
1568           register Quantum
1569             *q;
1570
1571           CacheView
1572             *image_view;
1573
1574           for ( ; image; image=image->next)
1575           {
1576             if (image->storage_class != PseudoClass)
1577               continue;
1578             x=0;
1579             y=0;
1580             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1581             (void) items;
1582             image_view=AcquireCacheView(image);
1583             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1584             if (q != (Quantum *) NULL)
1585               {
1586                 items=sscanf(SvPV(sval,na),"%ld",&index);
1587                 if ((index >= 0) && (index < (ssize_t) image->colors))
1588                   SetPixelIndex(image,index,q);
1589                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1590               }
1591             image_view=DestroyCacheView(image_view);
1592           }
1593           break;
1594         }
1595       if (LocaleCompare(attribute,"iterations") == 0)
1596         {
1597   iterations:
1598           for ( ; image; image=image->next)
1599             image->iterations=SvIV(sval);
1600           break;
1601         }
1602       if (LocaleCompare(attribute,"interlace") == 0)
1603         {
1604           sp=SvPOK(sval) ? ParseCommandOption(MagickInterlaceOptions,
1605             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1606           if (sp < 0)
1607             {
1608               ThrowPerlException(exception,OptionError,
1609                 "UnrecognizedInterlaceType",SvPV(sval,na));
1610               break;
1611             }
1612           if (info)
1613             info->image_info->interlace=(InterlaceType) sp;
1614           for ( ; image; image=image->next)
1615             image->interlace=(InterlaceType) sp;
1616           break;
1617         }
1618       if (info)
1619         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1620       for ( ; image; image=image->next)
1621         SetImageProperty(image,attribute,SvPV(sval,na));
1622       break;
1623     }
1624     case 'L':
1625     case 'l':
1626     {
1627       if (LocaleCompare(attribute,"label") == 0)
1628         {
1629           for ( ; image; image=image->next)
1630             (void) SetImageProperty(image,"label",InterpretImageProperties(
1631               info ? info->image_info : (ImageInfo *) NULL,image,
1632               SvPV(sval,na)));
1633           break;
1634         }
1635       if (LocaleCompare(attribute,"loop") == 0)
1636         goto iterations;
1637       if (info)
1638         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1639       for ( ; image; image=image->next)
1640         SetImageProperty(image,attribute,SvPV(sval,na));
1641       break;
1642     }
1643     case 'M':
1644     case 'm':
1645     {
1646       if (LocaleCompare(attribute,"magick") == 0)
1647         {
1648           if (info)
1649             (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
1650               "%s:",SvPV(sval,na));
1651           for ( ; image; image=image->next)
1652             (void) CopyMagickString(image->magick,SvPV(sval,na),MaxTextExtent);
1653           break;
1654         }
1655       if (LocaleCompare(attribute,"map-limit") == 0)
1656         {
1657           MagickSizeType
1658             limit;
1659
1660           limit=MagickResourceInfinity;
1661           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1662             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1663           (void) SetMagickResourceLimit(MapResource,limit);
1664           break;
1665         }
1666       if (LocaleCompare(attribute,"mask") == 0)
1667         {
1668           Image
1669             *mask;
1670
1671           mask=(Image *) NULL;
1672           if (SvPOK(sval))
1673             mask=SetupList(aTHX_ SvRV(sval),&info,(SV ***) NULL,exception);
1674           for ( ; image; image=image->next)
1675             SetImageMask(image,mask);
1676           break;
1677         }
1678       if (LocaleCompare(attribute,"mattecolor") == 0)
1679         {
1680           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
1681           if (info)
1682             info->image_info->matte_color=target_color;
1683           for ( ; image; image=image->next)
1684             image->matte_color=target_color;
1685           break;
1686         }
1687       if (LocaleCompare(attribute,"matte") == 0)
1688         {
1689           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1690             SvPV(sval,na)) : SvIV(sval);
1691           if (sp < 0)
1692             {
1693               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1694                 SvPV(sval,na));
1695               break;
1696             }
1697           for ( ; image; image=image->next)
1698             image->matte=sp != 0 ? MagickTrue : MagickFalse;
1699           break;
1700         }
1701       if (LocaleCompare(attribute,"memory-limit") == 0)
1702         {
1703           MagickSizeType
1704             limit;
1705
1706           limit=MagickResourceInfinity;
1707           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
1708             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
1709           (void) SetMagickResourceLimit(MemoryResource,limit);
1710           break;
1711         }
1712       if (LocaleCompare(attribute,"monochrome") == 0)
1713         {
1714           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
1715             SvPV(sval,na)) : SvIV(sval);
1716           if (sp < 0)
1717             {
1718               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1719                 SvPV(sval,na));
1720               break;
1721             }
1722           if (info)
1723             info->image_info->monochrome=sp != 0 ? MagickTrue : MagickFalse;
1724           for ( ; image; image=image->next)
1725             (void) SetImageType(image,BilevelType);
1726           break;
1727         }
1728       if (info)
1729         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1730       for ( ; image; image=image->next)
1731         SetImageProperty(image,attribute,SvPV(sval,na));
1732       break;
1733     }
1734     case 'O':
1735     case 'o':
1736     {
1737       if (LocaleCompare(attribute,"option") == 0)
1738         {
1739           if (info)
1740             DefineImageOption(info->image_info,SvPV(sval,na));
1741           break;
1742         }
1743       if (LocaleCompare(attribute,"orientation") == 0)
1744         {
1745           sp=SvPOK(sval) ? ParseCommandOption(MagickOrientationOptions,
1746             MagickFalse,SvPV(sval,na)) : SvIV(sval);
1747           if (sp < 0)
1748             {
1749               ThrowPerlException(exception,OptionError,
1750                 "UnrecognizedOrientationType",SvPV(sval,na));
1751               break;
1752             }
1753           if (info)
1754             info->image_info->orientation=(OrientationType) sp;
1755           for ( ; image; image=image->next)
1756             image->orientation=(OrientationType) sp;
1757           break;
1758         }
1759       if (info)
1760         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1761       for ( ; image; image=image->next)
1762         SetImageProperty(image,attribute,SvPV(sval,na));
1763       break;
1764     }
1765     case 'P':
1766     case 'p':
1767     {
1768       if (LocaleCompare(attribute,"page") == 0)
1769         {
1770           char
1771             *geometry;
1772
1773           geometry=GetPageGeometry(SvPV(sval,na));
1774           if (info)
1775             (void) CloneString(&info->image_info->page,geometry);
1776           for ( ; image; image=image->next)
1777             (void) ParsePageGeometry(image,geometry,&image->page,exception);
1778           geometry=(char *) RelinquishMagickMemory(geometry);
1779           break;
1780         }
1781       if (LocaleCompare(attribute,"pen") == 0)
1782         {
1783           if (info)
1784             (void) SetImageOption(info->image_info,"fill",SvPV(sval,na));
1785           break;
1786         }
1787       if (LocaleNCompare(attribute,"pixel",5) == 0)
1788         {
1789           int
1790             items;
1791
1792           PixelInfo
1793             pixel;
1794
1795           register Quantum
1796             *q;
1797
1798           CacheView
1799             *image_view;
1800
1801           for ( ; image; image=image->next)
1802           {
1803             if (SetImageStorageClass(image,DirectClass) == MagickFalse)
1804               break;
1805             x=0;
1806             y=0;
1807             items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
1808             (void) items;
1809             image_view=AcquireCacheView(image);
1810             q=GetCacheViewAuthenticPixels(image_view,x,y,1,1,exception);
1811             if (q != (Quantum *) NULL)
1812               {
1813                 if ((strchr(SvPV(sval,na),',') == 0) ||
1814                     (strchr(SvPV(sval,na),')') != 0))
1815                   QueryMagickColor(SvPV(sval,na),&pixel,exception);
1816                 else
1817                   {
1818                     GetPixelInfo(image,&pixel);
1819                     flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1820                     pixel.red=geometry_info.rho;
1821                     if ((flags & SigmaValue) != 0)
1822                       pixel.green=geometry_info.sigma;
1823                     if ((flags & XiValue) != 0)
1824                       pixel.blue=geometry_info.xi;
1825                     if ((flags & PsiValue) != 0)
1826                       pixel.alpha=geometry_info.psi;
1827                     if ((flags & ChiValue) != 0)
1828                       pixel.black=geometry_info.chi;
1829                   }
1830                 SetPixelRed(image,ClampToQuantum(pixel.red),q);
1831                 SetPixelGreen(image,ClampToQuantum(pixel.green),q);
1832                 SetPixelBlue(image,ClampToQuantum(pixel.blue),q);
1833                 if (image->colorspace == CMYKColorspace)
1834                   SetPixelBlack(image,ClampToQuantum(pixel.black),q);
1835                 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q);
1836                 (void) SyncCacheViewAuthenticPixels(image_view,exception);
1837               }
1838             image_view=DestroyCacheView(image_view);
1839           }
1840           break;
1841         }
1842       if (LocaleCompare(attribute,"pointsize") == 0)
1843         {
1844           if (info)
1845             {
1846               (void) ParseGeometry(SvPV(sval,na),&geometry_info);
1847               info->image_info->pointsize=geometry_info.rho;
1848             }
1849           break;
1850         }
1851       if (LocaleCompare(attribute,"preview") == 0)
1852         {
1853           sp=SvPOK(sval) ? ParseCommandOption(MagickPreviewOptions,MagickFalse,
1854             SvPV(sval,na)) : SvIV(sval);
1855           if (sp < 0)
1856             {
1857               ThrowPerlException(exception,OptionError,"UnrecognizedType",
1858                 SvPV(sval,na));
1859               break;
1860             }
1861           if (info)
1862             info->image_info->preview_type=(PreviewType) sp;
1863           break;
1864         }
1865       if (info)
1866         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1867       for ( ; image; image=image->next)
1868         SetImageProperty(image,attribute,SvPV(sval,na));
1869       break;
1870     }
1871     case 'Q':
1872     case 'q':
1873     {
1874       if (LocaleCompare(attribute,"quality") == 0)
1875         {
1876           if (info)
1877             info->image_info->quality=SvIV(sval);
1878           for ( ; image; image=image->next)
1879             image->quality=SvIV(sval);
1880           break;
1881         }
1882       if (info)
1883         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1884       for ( ; image; image=image->next)
1885         SetImageProperty(image,attribute,SvPV(sval,na));
1886       break;
1887     }
1888     case 'R':
1889     case 'r':
1890     {
1891       if (LocaleCompare(attribute,"red-primary") == 0)
1892         {
1893           for ( ; image; image=image->next)
1894           {
1895             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
1896             image->chromaticity.red_primary.x=geometry_info.rho;
1897             image->chromaticity.red_primary.y=geometry_info.sigma;
1898             if ((flags & SigmaValue) == 0)
1899               image->chromaticity.red_primary.y=
1900                 image->chromaticity.red_primary.x;
1901           }
1902           break;
1903         }
1904       if (LocaleCompare(attribute,"render") == 0)
1905         {
1906           sp=SvPOK(sval) ? ParseCommandOption(MagickIntentOptions,MagickFalse,
1907             SvPV(sval,na)) : SvIV(sval);
1908           if (sp < 0)
1909             {
1910               ThrowPerlException(exception,OptionError,"UnrecognizedIntentType",
1911                 SvPV(sval,na));
1912               break;
1913             }
1914          for ( ; image; image=image->next)
1915            image->rendering_intent=(RenderingIntent) sp;
1916          break;
1917        }
1918       if (LocaleCompare(attribute,"repage") == 0)
1919         {
1920           RectangleInfo
1921             geometry;
1922
1923           for ( ; image; image=image->next)
1924           {
1925             flags=ParseAbsoluteGeometry(SvPV(sval,na),&geometry);
1926             if ((flags & WidthValue) != 0)
1927               {
1928                 if ((flags & HeightValue) == 0)
1929                   geometry.height=geometry.width;
1930                 image->page.width=geometry.width;
1931                 image->page.height=geometry.height;
1932               }
1933             if ((flags & AspectValue) != 0)
1934               {
1935                 if ((flags & XValue) != 0)
1936                   image->page.x+=geometry.x;
1937                 if ((flags & YValue) != 0)
1938                   image->page.y+=geometry.y;
1939               }
1940             else
1941               {
1942                 if ((flags & XValue) != 0)
1943                   {
1944                     image->page.x=geometry.x;
1945                     if (((flags & WidthValue) != 0) && (geometry.x > 0))
1946                       image->page.width=image->columns+geometry.x;
1947                   }
1948                 if ((flags & YValue) != 0)
1949                   {
1950                     image->page.y=geometry.y;
1951                     if (((flags & HeightValue) != 0) && (geometry.y > 0))
1952                       image->page.height=image->rows+geometry.y;
1953                   }
1954               }
1955           }
1956           break;
1957         }
1958       if (info)
1959         SetImageOption(info->image_info,attribute,SvPV(sval,na));
1960       for ( ; image; image=image->next)
1961         SetImageProperty(image,attribute,SvPV(sval,na));
1962       break;
1963     }
1964     case 'S':
1965     case 's':
1966     {
1967       if (LocaleCompare(attribute,"sampling-factor") == 0)
1968         {
1969           if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1970             {
1971               ThrowPerlException(exception,OptionError,"MissingGeometry",
1972                 SvPV(sval,na));
1973               break;
1974             }
1975           if (info)
1976             (void) CloneString(&info->image_info->sampling_factor,
1977               SvPV(sval,na));
1978           break;
1979         }
1980       if (LocaleCompare(attribute,"scene") == 0)
1981         {
1982           for ( ; image; image=image->next)
1983             image->scene=SvIV(sval);
1984           break;
1985         }
1986       if (LocaleCompare(attribute,"server") == 0)
1987         goto display;
1988       if (LocaleCompare(attribute,"size") == 0)
1989         {
1990           if (info)
1991             {
1992               if (IsGeometry(SvPV(sval,na)) == MagickFalse)
1993                 {
1994                   ThrowPerlException(exception,OptionError,"MissingGeometry",
1995                     SvPV(sval,na));
1996                   break;
1997                 }
1998               (void) CloneString(&info->image_info->size,SvPV(sval,na));
1999             }
2000           break;
2001         }
2002       if (LocaleCompare(attribute,"stroke") == 0)
2003         {
2004           if (info)
2005             (void) SetImageOption(info->image_info,"stroke",SvPV(sval,na));
2006           break;
2007         }
2008       if (info)
2009         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2010       for ( ; image; image=image->next)
2011         SetImageProperty(image,attribute,SvPV(sval,na));
2012       break;
2013     }
2014     case 'T':
2015     case 't':
2016     {
2017       if (LocaleCompare(attribute,"texture") == 0)
2018         {
2019           if (info)
2020             (void) CloneString(&info->image_info->texture,SvPV(sval,na));
2021           break;
2022         }
2023       if (LocaleCompare(attribute,"thread-limit") == 0)
2024         {
2025           MagickSizeType
2026             limit;
2027
2028           limit=MagickResourceInfinity;
2029           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2030             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2031           (void) SetMagickResourceLimit(ThreadResource,limit);
2032           break;
2033         }
2034       if (LocaleCompare(attribute,"tile-offset") == 0)
2035         {
2036           char
2037             *geometry;
2038
2039           geometry=GetPageGeometry(SvPV(sval,na));
2040           if (info)
2041             (void) CloneString(&info->image_info->page,geometry);
2042           for ( ; image; image=image->next)
2043             (void) ParsePageGeometry(image,geometry,&image->tile_offset,
2044               exception);
2045           geometry=(char *) RelinquishMagickMemory(geometry);
2046           break;
2047         }
2048       if (LocaleCompare(attribute,"time-limit") == 0)
2049         {
2050           MagickSizeType
2051             limit;
2052
2053           limit=MagickResourceInfinity;
2054           if (LocaleCompare(SvPV(sval,na),"unlimited") != 0)
2055             limit=(MagickSizeType) SiPrefixToDouble(SvPV(sval,na),100.0);
2056           (void) SetMagickResourceLimit(TimeResource,limit);
2057           break;
2058         }
2059       if (LocaleCompare(attribute,"transparent-color") == 0)
2060         {
2061           (void) QueryColorDatabase(SvPV(sval,na),&target_color,exception);
2062           if (info)
2063             info->image_info->transparent_color=target_color;
2064           for ( ; image; image=image->next)
2065             image->transparent_color=target_color;
2066           break;
2067         }
2068       if (LocaleCompare(attribute,"type") == 0)
2069         {
2070           sp=SvPOK(sval) ? ParseCommandOption(MagickTypeOptions,MagickFalse,
2071             SvPV(sval,na)) : SvIV(sval);
2072           if (sp < 0)
2073             {
2074               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2075                 SvPV(sval,na));
2076               break;
2077             }
2078           if (info)
2079             info->image_info->type=(ImageType) sp;
2080           for ( ; image; image=image->next)
2081             SetImageType(image,(ImageType) sp);
2082           break;
2083         }
2084       if (info)
2085         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2086       for ( ; image; image=image->next)
2087         SetImageProperty(image,attribute,SvPV(sval,na));
2088       break;
2089     }
2090     case 'U':
2091     case 'u':
2092     {
2093       if (LocaleCompare(attribute,"units") == 0)
2094         {
2095           sp=SvPOK(sval) ? ParseCommandOption(MagickResolutionOptions,
2096             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2097           if (sp < 0)
2098             {
2099               ThrowPerlException(exception,OptionError,"UnrecognizedUnitsType",
2100                 SvPV(sval,na));
2101               break;
2102             }
2103           if (info)
2104             info->image_info->units=(ResolutionType) sp;
2105           for ( ; image; image=image->next)
2106           {
2107             ResolutionType
2108               units;
2109
2110             units=(ResolutionType) sp;
2111             if (image->units != units)
2112               switch (image->units)
2113               {
2114                 case UndefinedResolution:
2115                 case PixelsPerInchResolution:
2116                 {
2117                   if (units == PixelsPerCentimeterResolution)
2118                     {
2119                       image->x_resolution*=2.54;
2120                       image->y_resolution*=2.54;
2121                     }
2122                   break;
2123                 }
2124                 case PixelsPerCentimeterResolution:
2125                 {
2126                   if (units == PixelsPerInchResolution)
2127                     {
2128                       image->x_resolution/=2.54;
2129                       image->y_resolution/=2.54;
2130                     }
2131                   break;
2132                 }
2133               }
2134             image->units=units;
2135           }
2136           break;
2137         }
2138       if (info)
2139         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2140       for ( ; image; image=image->next)
2141         SetImageProperty(image,attribute,SvPV(sval,na));
2142       break;
2143     }
2144     case 'V':
2145     case 'v':
2146     {
2147       if (LocaleCompare(attribute,"verbose") == 0)
2148         {
2149           sp=SvPOK(sval) ? ParseCommandOption(MagickBooleanOptions,MagickFalse,
2150             SvPV(sval,na)) : SvIV(sval);
2151           if (sp < 0)
2152             {
2153               ThrowPerlException(exception,OptionError,"UnrecognizedType",
2154                 SvPV(sval,na));
2155               break;
2156             }
2157           if (info)
2158             info->image_info->verbose=sp != 0 ? MagickTrue : MagickFalse;
2159           break;
2160         }
2161       if (LocaleCompare(attribute,"view") == 0)
2162         {
2163           if (info)
2164             (void) CloneString(&info->image_info->view,SvPV(sval,na));
2165           break;
2166         }
2167       if (LocaleCompare(attribute,"virtual-pixel") == 0)
2168         {
2169           sp=SvPOK(sval) ? ParseCommandOption(MagickVirtualPixelOptions,
2170             MagickFalse,SvPV(sval,na)) : SvIV(sval);
2171           if (sp < 0)
2172             {
2173               ThrowPerlException(exception,OptionError,
2174                 "UnrecognizedVirtualPixelMethod",SvPV(sval,na));
2175               break;
2176             }
2177           if (info)
2178             info->image_info->virtual_pixel_method=(VirtualPixelMethod) sp;
2179           for ( ; image; image=image->next)
2180             SetImageVirtualPixelMethod(image,(VirtualPixelMethod) sp);
2181           break;
2182         }
2183       if (info)
2184         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2185       for ( ; image; image=image->next)
2186         SetImageProperty(image,attribute,SvPV(sval,na));
2187       break;
2188     }
2189     case 'W':
2190     case 'w':
2191     {
2192       if (LocaleCompare(attribute,"white-point") == 0)
2193         {
2194           for ( ; image; image=image->next)
2195           {
2196             flags=ParseGeometry(SvPV(sval,na),&geometry_info);
2197             image->chromaticity.white_point.x=geometry_info.rho;
2198             image->chromaticity.white_point.y=geometry_info.sigma;
2199             if ((flags & SigmaValue) == 0)
2200               image->chromaticity.white_point.y=
2201                 image->chromaticity.white_point.x;
2202           }
2203           break;
2204         }
2205       if (info)
2206         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2207       for ( ; image; image=image->next)
2208         SetImageProperty(image,attribute,SvPV(sval,na));
2209       break;
2210     }
2211     default:
2212     {
2213       if (info)
2214         SetImageOption(info->image_info,attribute,SvPV(sval,na));
2215       for ( ; image; image=image->next)
2216         SetImageProperty(image,attribute,SvPV(sval,na));
2217       break;
2218     }
2219   }
2220 }
2221 \f
2222 /*
2223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2224 %                                                                             %
2225 %                                                                             %
2226 %                                                                             %
2227 %   S e t u p L i s t                                                         %
2228 %                                                                             %
2229 %                                                                             %
2230 %                                                                             %
2231 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2232 %
2233 %  Method SetupList returns the list of all the images linked by their
2234 %  image->next and image->previous link lists for use with ImageMagick.  If
2235 %  info is non-NULL, an info structure is returned in *info.  If
2236 %  reference_vector is non-NULL,an array of SV* are returned in
2237 %  *reference_vector.  Reference_vector is used when the images are going to be
2238 %  replaced with new Image*'s.
2239 %
2240 %  The format of the SetupList routine is:
2241 %
2242 %      Image *SetupList(SV *reference,struct PackageInfo **info,
2243 %        SV ***reference_vector,ExceptionInfo *exception)
2244 %
2245 %  A description of each parameter follows:
2246 %
2247 %    o list: a list of strings.
2248 %
2249 %    o string: a character string.
2250 %
2251 %    o exception: Return any errors or warnings in this structure.
2252 %
2253 */
2254 static Image *SetupList(pTHX_ SV *reference,struct PackageInfo **info,
2255   SV ***reference_vector,ExceptionInfo *exception)
2256 {
2257   Image
2258     *image;
2259
2260   ssize_t
2261     current,
2262     last;
2263
2264   if (reference_vector)
2265     *reference_vector=NULL;
2266   if (info)
2267     *info=NULL;
2268   current=0;
2269   last=0;
2270   image=GetList(aTHX_ reference,reference_vector,&current,&last,exception);
2271   if (info && (SvTYPE(reference) == SVt_PVAV))
2272     *info=GetPackageInfo(aTHX_ (void *) reference,(struct PackageInfo *) NULL,
2273       exception);
2274   return(image);
2275 }
2276 \f
2277 /*
2278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279 %                                                                             %
2280 %                                                                             %
2281 %                                                                             %
2282 %   s t r E Q c a s e                                                         %
2283 %                                                                             %
2284 %                                                                             %
2285 %                                                                             %
2286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287 %
2288 %  strEQcase() compares two strings and returns 0 if they are the
2289 %  same or if the second string runs out first.  The comparison is case
2290 %  insensitive.
2291 %
2292 %  The format of the strEQcase routine is:
2293 %
2294 %      ssize_t strEQcase(const char *p,const char *q)
2295 %
2296 %  A description of each parameter follows:
2297 %
2298 %    o p: a character string.
2299 %
2300 %    o q: a character string.
2301 %
2302 %
2303 */
2304 static ssize_t strEQcase(const char *p,const char *q)
2305 {
2306   char
2307     c;
2308
2309   register ssize_t
2310     i;
2311
2312   for (i=0 ; (c=(*q)) != 0; i++)
2313   {
2314     if ((isUPPER((unsigned char) c) ? toLOWER(c) : c) !=
2315         (isUPPER((unsigned char) *p) ? toLOWER(*p) : *p))
2316       return(0);
2317     p++;
2318     q++;
2319   }
2320   return(((*q == 0) && (*p == 0)) ? i : 0);
2321 }
2322 \f
2323 /*
2324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2325 %                                                                             %
2326 %                                                                             %
2327 %                                                                             %
2328 %   I m a g e : : M a g i c k                                                 %
2329 %                                                                             %
2330 %                                                                             %
2331 %                                                                             %
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 %
2334 %
2335 */
2336 MODULE = Image::Magick PACKAGE = Image::Magick
2337
2338 PROTOTYPES: ENABLE
2339
2340 BOOT:
2341   MagickCoreGenesis("PerlMagick",MagickFalse);
2342   SetWarningHandler(NULL);
2343   SetErrorHandler(NULL);
2344   magick_registry=NewSplayTree((int (*)(const void *,const void *))
2345     NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
2346
2347 void
2348 UNLOAD()
2349   PPCODE:
2350   {
2351     if (magick_registry != (SplayTreeInfo *) NULL)
2352       magick_registry=DestroySplayTree(magick_registry);
2353     MagickCoreTerminus();
2354   }
2355
2356 double
2357 constant(name,argument)
2358   char *name
2359   ssize_t argument
2360 \f
2361 #
2362 ###############################################################################
2363 #                                                                             #
2364 #                                                                             #
2365 #                                                                             #
2366 #   A n i m a t e                                                             #
2367 #                                                                             #
2368 #                                                                             #
2369 #                                                                             #
2370 ###############################################################################
2371 #
2372 #
2373 void
2374 Animate(ref,...)
2375   Image::Magick ref=NO_INIT
2376   ALIAS:
2377     AnimateImage  = 1
2378     animate       = 2
2379     animateimage  = 3
2380   PPCODE:
2381   {
2382     ExceptionInfo
2383       *exception;
2384
2385     Image
2386       *image;
2387
2388     register ssize_t
2389       i;
2390
2391     struct PackageInfo
2392       *info,
2393       *package_info;
2394
2395     SV
2396       *perl_exception,
2397       *reference;
2398
2399     PERL_UNUSED_VAR(ref);
2400     PERL_UNUSED_VAR(ix);
2401     exception=AcquireExceptionInfo();
2402     perl_exception=newSVpv("",0);
2403     package_info=(struct PackageInfo *) NULL;
2404     if (sv_isobject(ST(0)) == 0)
2405       {
2406         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2407           PackageName);
2408         goto PerlException;
2409       }
2410     reference=SvRV(ST(0));
2411     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2412     if (image == (Image *) NULL)
2413       {
2414         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2415           PackageName);
2416         goto PerlException;
2417       }
2418     package_info=ClonePackageInfo(info,exception);
2419     if (items == 2)
2420       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
2421     else
2422       if (items > 2)
2423         for (i=2; i < items; i+=2)
2424           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
2425             exception);
2426     (void) AnimateImages(package_info->image_info,image);
2427     (void) CatchImageException(image);
2428     InheritException(exception,&image->exception);
2429
2430   PerlException:
2431     if (package_info != (struct PackageInfo *) NULL)
2432       DestroyPackageInfo(package_info);
2433     InheritPerlException(exception,perl_exception);
2434     exception=DestroyExceptionInfo(exception);
2435     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2436     SvPOK_on(perl_exception);
2437     ST(0)=sv_2mortal(perl_exception);
2438     XSRETURN(1);
2439   }
2440 \f
2441 #
2442 ###############################################################################
2443 #                                                                             #
2444 #                                                                             #
2445 #                                                                             #
2446 #   A p p e n d                                                               #
2447 #                                                                             #
2448 #                                                                             #
2449 #                                                                             #
2450 ###############################################################################
2451 #
2452 #
2453 void
2454 Append(ref,...)
2455   Image::Magick ref=NO_INIT
2456   ALIAS:
2457     AppendImage  = 1
2458     append       = 2
2459     appendimage  = 3
2460   PPCODE:
2461   {
2462     AV
2463       *av;
2464
2465     char
2466       *attribute;
2467
2468     ExceptionInfo
2469       *exception;
2470
2471     HV
2472       *hv;
2473
2474     Image
2475       *image;
2476
2477     register ssize_t
2478       i;
2479
2480     ssize_t
2481       stack;
2482
2483     struct PackageInfo
2484       *info;
2485
2486     SV
2487       *av_reference,
2488       *perl_exception,
2489       *reference,
2490       *rv,
2491       *sv;
2492
2493     PERL_UNUSED_VAR(ref);
2494     PERL_UNUSED_VAR(ix);
2495     exception=AcquireExceptionInfo();
2496     perl_exception=newSVpv("",0);
2497     sv=NULL;
2498     attribute=NULL;
2499     av=NULL;
2500     if (sv_isobject(ST(0)) == 0)
2501       {
2502         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2503           PackageName);
2504         goto PerlException;
2505       }
2506     reference=SvRV(ST(0));
2507     hv=SvSTASH(reference);
2508     av=newAV();
2509     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2510     SvREFCNT_dec(av);
2511     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2512     if (image == (Image *) NULL)
2513       {
2514         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2515           PackageName);
2516         goto PerlException;
2517       }
2518     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2519     /*
2520       Get options.
2521     */
2522     stack=MagickTrue;
2523     for (i=2; i < items; i+=2)
2524     {
2525       attribute=(char *) SvPV(ST(i-1),na);
2526       switch (*attribute)
2527       {
2528         case 'S':
2529         case 's':
2530         {
2531           if (LocaleCompare(attribute,"stack") == 0)
2532             {
2533               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
2534                 SvPV(ST(i),na));
2535               if (stack < 0)
2536                 {
2537                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
2538                     SvPV(ST(i),na));
2539                   return;
2540                 }
2541               break;
2542             }
2543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2544             attribute);
2545           break;
2546         }
2547         default:
2548         {
2549           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
2550             attribute);
2551           break;
2552         }
2553       }
2554     }
2555     image=AppendImages(image,stack != 0 ? MagickTrue : MagickFalse,exception);
2556     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2557       goto PerlException;
2558     for ( ; image; image=image->next)
2559     {
2560       AddImageToRegistry(sv,image);
2561       rv=newRV(sv);
2562       av_push(av,sv_bless(rv,hv));
2563       SvREFCNT_dec(sv);
2564     }
2565     exception=DestroyExceptionInfo(exception);
2566     ST(0)=av_reference;
2567     SvREFCNT_dec(perl_exception);
2568     XSRETURN(1);
2569
2570   PerlException:
2571     InheritPerlException(exception,perl_exception);
2572     exception=DestroyExceptionInfo(exception);
2573     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2574     SvPOK_on(perl_exception);
2575     ST(0)=sv_2mortal(perl_exception);
2576     XSRETURN(1);
2577   }
2578 \f
2579 #
2580 ###############################################################################
2581 #                                                                             #
2582 #                                                                             #
2583 #                                                                             #
2584 #   A v e r a g e                                                             #
2585 #                                                                             #
2586 #                                                                             #
2587 #                                                                             #
2588 ###############################################################################
2589 #
2590 #
2591 void
2592 Average(ref)
2593   Image::Magick ref=NO_INIT
2594   ALIAS:
2595     AverageImage   = 1
2596     average        = 2
2597     averageimage   = 3
2598   PPCODE:
2599   {
2600     AV
2601       *av;
2602
2603     char
2604       *p;
2605
2606     ExceptionInfo
2607       *exception;
2608
2609     HV
2610       *hv;
2611
2612     Image
2613       *image;
2614
2615     struct PackageInfo
2616       *info;
2617
2618     SV
2619       *perl_exception,
2620       *reference,
2621       *rv,
2622       *sv;
2623
2624     PERL_UNUSED_VAR(ref);
2625     PERL_UNUSED_VAR(ix);
2626     exception=AcquireExceptionInfo();
2627     perl_exception=newSVpv("",0);
2628     sv=NULL;
2629     if (sv_isobject(ST(0)) == 0)
2630       {
2631         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2632           PackageName);
2633         goto PerlException;
2634       }
2635     reference=SvRV(ST(0));
2636     hv=SvSTASH(reference);
2637     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2638     if (image == (Image *) NULL)
2639       {
2640         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2641           PackageName);
2642         goto PerlException;
2643       }
2644     image=EvaluateImages(image,MeanEvaluateOperator,exception);
2645     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2646       goto PerlException;
2647     /*
2648       Create blessed Perl array for the returned image.
2649     */
2650     av=newAV();
2651     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2652     SvREFCNT_dec(av);
2653     AddImageToRegistry(sv,image);
2654     rv=newRV(sv);
2655     av_push(av,sv_bless(rv,hv));
2656     SvREFCNT_dec(sv);
2657     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
2658     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
2659       "average-%.*s",(int) (MaxTextExtent-9),
2660       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
2661     (void) CopyMagickString(image->filename,info->image_info->filename,
2662       MaxTextExtent);
2663     SetImageInfo(info->image_info,0,exception);
2664     exception=DestroyExceptionInfo(exception);
2665     SvREFCNT_dec(perl_exception);
2666     XSRETURN(1);
2667
2668   PerlException:
2669     InheritPerlException(exception,perl_exception);
2670     exception=DestroyExceptionInfo(exception);
2671     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2672     SvPOK_on(perl_exception);
2673     ST(0)=sv_2mortal(perl_exception);
2674     XSRETURN(1);
2675   }
2676 \f
2677 #
2678 ###############################################################################
2679 #                                                                             #
2680 #                                                                             #
2681 #                                                                             #
2682 #   B l o b T o I m a g e                                                     #
2683 #                                                                             #
2684 #                                                                             #
2685 #                                                                             #
2686 ###############################################################################
2687 #
2688 #
2689 void
2690 BlobToImage(ref,...)
2691   Image::Magick ref=NO_INIT
2692   ALIAS:
2693     BlobToImage  = 1
2694     blobtoimage  = 2
2695     blobto       = 3
2696   PPCODE:
2697   {
2698     AV
2699       *av;
2700
2701     char
2702       **keep,
2703       **list;
2704
2705     ExceptionInfo
2706       *exception;
2707
2708     HV
2709       *hv;
2710
2711     Image
2712       *image;
2713
2714     register char
2715       **p;
2716
2717     register ssize_t
2718       i;
2719
2720     ssize_t
2721       ac,
2722       n,
2723       number_images;
2724
2725     STRLEN
2726       *length;
2727
2728     struct PackageInfo
2729       *info;
2730
2731     SV
2732       *perl_exception,
2733       *reference,
2734       *rv,
2735       *sv;
2736
2737     PERL_UNUSED_VAR(ref);
2738     PERL_UNUSED_VAR(ix);
2739     exception=AcquireExceptionInfo();
2740     perl_exception=newSVpv("",0);
2741     sv=NULL;
2742     number_images=0;
2743     ac=(items < 2) ? 1 : items-1;
2744     length=(STRLEN *) NULL;
2745     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
2746     if (list == (char **) NULL)
2747       {
2748         ThrowPerlException(exception,ResourceLimitError,
2749           "MemoryAllocationFailed",PackageName);
2750         goto PerlException;
2751       }
2752     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
2753     if (length == (STRLEN *) NULL)
2754       {
2755         ThrowPerlException(exception,ResourceLimitError,
2756           "MemoryAllocationFailed",PackageName);
2757         goto PerlException;
2758       }
2759     if (sv_isobject(ST(0)) == 0)
2760       {
2761         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2762           PackageName);
2763         goto PerlException;
2764       }
2765     reference=SvRV(ST(0));
2766     hv=SvSTASH(reference);
2767     if (SvTYPE(reference) != SVt_PVAV)
2768       {
2769         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2770           PackageName);
2771         goto PerlException;
2772       }
2773     av=(AV *) reference;
2774     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
2775       exception);
2776     n=1;
2777     if (items <= 1)
2778       {
2779         ThrowPerlException(exception,OptionError,"NoBlobDefined",PackageName);
2780         goto PerlException;
2781       }
2782     for (n=0, i=0; i < ac; i++)
2783     {
2784       list[n]=(char *) (SvPV(ST(i+1),length[n]));
2785       if ((items >= 3) && strEQcase((char *) SvPV(ST(i+1),na),"blob"))
2786         {
2787           list[n]=(char *) (SvPV(ST(i+2),length[n]));
2788           continue;
2789         }
2790       n++;
2791     }
2792     list[n]=(char *) NULL;
2793     keep=list;
2794     for (i=number_images=0; i < n; i++)
2795     {
2796       image=BlobToImage(info->image_info,list[i],length[i],exception);
2797       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
2798         break;
2799       for ( ; image; image=image->next)
2800       {
2801         AddImageToRegistry(sv,image);
2802         rv=newRV(sv);
2803         av_push(av,sv_bless(rv,hv));
2804         SvREFCNT_dec(sv);
2805         number_images++;
2806       }
2807     }
2808     /*
2809       Free resources.
2810     */
2811     for (i=0; i < n; i++)
2812       if (list[i] != (char *) NULL)
2813         for (p=keep; list[i] != *p++; )
2814           if (*p == (char *) NULL)
2815             {
2816               list[i]=(char *) RelinquishMagickMemory(list[i]);
2817               break;
2818             }
2819
2820   PerlException:
2821     if (list)
2822       list=(char **) RelinquishMagickMemory(list);
2823     if (length)
2824       length=(STRLEN *) RelinquishMagickMemory(length);
2825     InheritPerlException(exception,perl_exception);
2826     exception=DestroyExceptionInfo(exception);
2827     sv_setiv(perl_exception,(IV) number_images);
2828     SvPOK_on(perl_exception);
2829     ST(0)=sv_2mortal(perl_exception);
2830     XSRETURN(1);
2831   }
2832 \f
2833 #
2834 ###############################################################################
2835 #                                                                             #
2836 #                                                                             #
2837 #                                                                             #
2838 #   C l o n e                                                                 #
2839 #                                                                             #
2840 #                                                                             #
2841 #                                                                             #
2842 ###############################################################################
2843 #
2844 #
2845 void
2846 Clone(ref)
2847   Image::Magick ref=NO_INIT
2848   ALIAS:
2849     CopyImage   = 1
2850     copy        = 2
2851     copyimage   = 3
2852     CloneImage  = 4
2853     clone       = 5
2854     cloneimage  = 6
2855     Clone       = 7
2856   PPCODE:
2857   {
2858     AV
2859       *av;
2860
2861     ExceptionInfo
2862       *exception;
2863
2864     HV
2865       *hv;
2866
2867     Image
2868       *clone,
2869       *image;
2870
2871     struct PackageInfo
2872       *info;
2873
2874     SV
2875       *perl_exception,
2876       *reference,
2877       *rv,
2878       *sv;
2879
2880     PERL_UNUSED_VAR(ref);
2881     PERL_UNUSED_VAR(ix);
2882     exception=AcquireExceptionInfo();
2883     perl_exception=newSVpv("",0);
2884     sv=NULL;
2885     if (sv_isobject(ST(0)) == 0)
2886       {
2887         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
2888           PackageName);
2889         goto PerlException;
2890       }
2891     reference=SvRV(ST(0));
2892     hv=SvSTASH(reference);
2893     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
2894     if (image == (Image *) NULL)
2895       {
2896         ThrowPerlException(exception,OptionError,"NoImagesDefined",
2897           PackageName);
2898         goto PerlException;
2899       }
2900     /*
2901       Create blessed Perl array for the returned image.
2902     */
2903     av=newAV();
2904     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
2905     SvREFCNT_dec(av);
2906     for ( ; image; image=image->next)
2907     {
2908       clone=CloneImage(image,0,0,MagickTrue,exception);
2909       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
2910         break;
2911       AddImageToRegistry(sv,clone);
2912       rv=newRV(sv);
2913       av_push(av,sv_bless(rv,hv));
2914       SvREFCNT_dec(sv);
2915     }
2916     exception=DestroyExceptionInfo(exception);
2917     SvREFCNT_dec(perl_exception);
2918     XSRETURN(1);
2919
2920   PerlException:
2921     InheritPerlException(exception,perl_exception);
2922     exception=DestroyExceptionInfo(exception);
2923     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
2924     SvPOK_on(perl_exception);
2925     ST(0)=sv_2mortal(perl_exception);
2926     XSRETURN(1);
2927   }
2928 \f
2929 #
2930 ###############################################################################
2931 #                                                                             #
2932 #                                                                             #
2933 #                                                                             #
2934 #   C L O N E                                                                 #
2935 #                                                                             #
2936 #                                                                             #
2937 #                                                                             #
2938 ###############################################################################
2939 #
2940 #
2941 void
2942 CLONE(ref,...)
2943   SV *ref;
2944   CODE:
2945   {
2946     PERL_UNUSED_VAR(ref);
2947     if (magick_registry != (SplayTreeInfo *) NULL)
2948       {
2949         register Image
2950           *p;
2951
2952         ResetSplayTreeIterator(magick_registry);
2953         p=(Image *) GetNextKeyInSplayTree(magick_registry);
2954         while (p != (Image *) NULL)
2955         {
2956           ReferenceImage(p);
2957           p=(Image *) GetNextKeyInSplayTree(magick_registry);
2958         }
2959       }
2960   }
2961 \f
2962 #
2963 ###############################################################################
2964 #                                                                             #
2965 #                                                                             #
2966 #                                                                             #
2967 #   C o a l e s c e                                                           #
2968 #                                                                             #
2969 #                                                                             #
2970 #                                                                             #
2971 ###############################################################################
2972 #
2973 #
2974 void
2975 Coalesce(ref)
2976   Image::Magick ref=NO_INIT
2977   ALIAS:
2978     CoalesceImage   = 1
2979     coalesce        = 2
2980     coalesceimage   = 3
2981   PPCODE:
2982   {
2983     AV
2984       *av;
2985
2986     ExceptionInfo
2987       *exception;
2988
2989     HV
2990       *hv;
2991
2992     Image
2993       *image;
2994
2995     struct PackageInfo
2996       *info;
2997
2998     SV
2999       *av_reference,
3000       *perl_exception,
3001       *reference,
3002       *rv,
3003       *sv;
3004
3005     PERL_UNUSED_VAR(ref);
3006     PERL_UNUSED_VAR(ix);
3007     exception=AcquireExceptionInfo();
3008     perl_exception=newSVpv("",0);
3009     sv=NULL;
3010     if (sv_isobject(ST(0)) == 0)
3011       {
3012         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3013           PackageName);
3014         goto PerlException;
3015       }
3016     reference=SvRV(ST(0));
3017     hv=SvSTASH(reference);
3018     av=newAV();
3019     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3020     SvREFCNT_dec(av);
3021     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3022     if (image == (Image *) NULL)
3023       {
3024         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3025           PackageName);
3026         goto PerlException;
3027       }
3028     image=CoalesceImages(image,exception);
3029     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3030       goto PerlException;
3031     for ( ; image; image=image->next)
3032     {
3033       AddImageToRegistry(sv,image);
3034       rv=newRV(sv);
3035       av_push(av,sv_bless(rv,hv));
3036       SvREFCNT_dec(sv);
3037     }
3038     exception=DestroyExceptionInfo(exception);
3039     ST(0)=av_reference;
3040     SvREFCNT_dec(perl_exception);
3041     XSRETURN(1);
3042
3043   PerlException:
3044     InheritPerlException(exception,perl_exception);
3045     exception=DestroyExceptionInfo(exception);
3046     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3047     SvPOK_on(perl_exception);
3048     ST(0)=sv_2mortal(perl_exception);
3049     XSRETURN(1);
3050   }
3051 \f
3052 #
3053 ###############################################################################
3054 #                                                                             #
3055 #                                                                             #
3056 #                                                                             #
3057 #   C o m p a r e                                                             #
3058 #                                                                             #
3059 #                                                                             #
3060 #                                                                             #
3061 ###############################################################################
3062 #
3063 #
3064 void
3065 Compare(ref,...)
3066   Image::Magick ref=NO_INIT
3067   ALIAS:
3068     CompareImage = 1
3069     compare      = 2
3070     compareimage = 3
3071   PPCODE:
3072   {
3073     AV
3074       *av;
3075
3076     char
3077       *attribute;
3078
3079     ChannelType
3080       channel;
3081
3082     double
3083       distortion;
3084
3085     ExceptionInfo
3086       *exception;
3087
3088     HV
3089       *hv;
3090
3091     Image
3092       *difference_image,
3093       *image,
3094       *reconstruct_image;
3095
3096     MetricType
3097       metric;
3098
3099     register ssize_t
3100       i;
3101
3102     ssize_t
3103       option;
3104
3105     struct PackageInfo
3106       *info;
3107
3108     SV
3109       *av_reference,
3110       *perl_exception,
3111       *reference,
3112       *rv,
3113       *sv;
3114
3115     PERL_UNUSED_VAR(ref);
3116     PERL_UNUSED_VAR(ix);
3117     exception=AcquireExceptionInfo();
3118     perl_exception=newSVpv("",0);
3119     sv=NULL;
3120     av=NULL;
3121     attribute=NULL;
3122     if (sv_isobject(ST(0)) == 0)
3123       {
3124         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3125           PackageName);
3126         goto PerlException;
3127       }
3128     reference=SvRV(ST(0));
3129     hv=SvSTASH(reference);
3130     av=newAV();
3131     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3132     SvREFCNT_dec(av);
3133     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3134     if (image == (Image *) NULL)
3135       {
3136         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3137           PackageName);
3138         goto PerlException;
3139       }
3140     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3141     /*
3142       Get attribute.
3143     */
3144     channel=DefaultChannels;
3145     reconstruct_image=image;
3146     metric=RootMeanSquaredErrorMetric;
3147     for (i=2; i < items; i+=2)
3148     {
3149       attribute=(char *) SvPV(ST(i-1),na);
3150       switch (*attribute)
3151       {
3152         case 'C':
3153         case 'c':
3154         {
3155           if (LocaleCompare(attribute,"channel") == 0)
3156             {
3157               ssize_t
3158                 option;
3159
3160               option=ParseChannelOption(SvPV(ST(i),na));
3161               if (option < 0)
3162                 {
3163                   ThrowPerlException(exception,OptionError,
3164                     "UnrecognizedType",SvPV(ST(i),na));
3165                   return;
3166                 }
3167               channel=(ChannelType) option;
3168               break;
3169             }
3170           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3171             attribute);
3172           break;
3173         }
3174         case 'F':
3175         case 'f':
3176         {
3177           if (LocaleCompare(attribute,"fuzz") == 0)
3178             {
3179               image->fuzz=SiPrefixToDouble(SvPV(ST(i),na),100.0);
3180               break;
3181             }
3182           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3183             attribute);
3184           break;
3185         }
3186         case 'I':
3187         case 'i':
3188         {
3189           if (LocaleCompare(attribute,"image") == 0)
3190             {
3191               reconstruct_image=SetupList(aTHX_ SvRV(ST(i)),
3192                 (struct PackageInfo **) NULL,(SV ***) NULL,exception);
3193               break;
3194             }
3195           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3196             attribute);
3197           break;
3198         }
3199         case 'M':
3200         case 'm':
3201         {
3202           if (LocaleCompare(attribute,"metric") == 0)
3203             {
3204               option=ParseCommandOption(MagickMetricOptions,MagickFalse,
3205                 SvPV(ST(i),na));
3206               if (option < 0)
3207                 {
3208                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3209                     SvPV(ST(i),na));
3210                   break;
3211                 }
3212               metric=(MetricType) option;
3213               break;
3214             }
3215           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3216             attribute);
3217           break;
3218         }
3219         default:
3220         {
3221           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3222             attribute);
3223           break;
3224         }
3225       }
3226     }
3227     difference_image=CompareImageChannels(image,reconstruct_image,channel,
3228       metric,&distortion,exception);
3229     if (difference_image != (Image *) NULL)
3230       {
3231         difference_image->error.mean_error_per_pixel=distortion;
3232         AddImageToRegistry(sv,difference_image);
3233         rv=newRV(sv);
3234         av_push(av,sv_bless(rv,hv));
3235         SvREFCNT_dec(sv);
3236       }
3237     exception=DestroyExceptionInfo(exception);
3238     ST(0)=av_reference;
3239     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
3240     XSRETURN(1);
3241
3242   PerlException:
3243     InheritPerlException(exception,perl_exception);
3244     exception=DestroyExceptionInfo(exception);
3245     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3246     SvPOK_on(perl_exception);
3247     ST(0)=sv_2mortal(perl_exception);
3248     XSRETURN(1);
3249   }
3250 \f
3251 #
3252 ###############################################################################
3253 #                                                                             #
3254 #                                                                             #
3255 #                                                                             #
3256 #   C o m p a r e L a y e r s                                                 #
3257 #                                                                             #
3258 #                                                                             #
3259 #                                                                             #
3260 ###############################################################################
3261 #
3262 #
3263 void
3264 CompareLayers(ref)
3265   Image::Magick ref=NO_INIT
3266   ALIAS:
3267     CompareImageLayers   = 1
3268     comparelayers        = 2
3269     compareimagelayers   = 3
3270   PPCODE:
3271   {
3272     AV
3273       *av;
3274
3275     char
3276       *attribute;
3277
3278     ExceptionInfo
3279       *exception;
3280
3281     HV
3282       *hv;
3283
3284     Image
3285       *image;
3286
3287     ImageLayerMethod
3288       method;
3289
3290     register ssize_t
3291       i;
3292
3293     ssize_t
3294       option;
3295
3296     struct PackageInfo
3297       *info;
3298
3299     SV
3300       *av_reference,
3301       *perl_exception,
3302       *reference,
3303       *rv,
3304       *sv;
3305
3306     PERL_UNUSED_VAR(ref);
3307     PERL_UNUSED_VAR(ix);
3308     exception=AcquireExceptionInfo();
3309     perl_exception=newSVpv("",0);
3310     sv=NULL;
3311     if (sv_isobject(ST(0)) == 0)
3312       {
3313         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3314           PackageName);
3315         goto PerlException;
3316       }
3317     reference=SvRV(ST(0));
3318     hv=SvSTASH(reference);
3319     av=newAV();
3320     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3321     SvREFCNT_dec(av);
3322     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3323     if (image == (Image *) NULL)
3324       {
3325         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3326           PackageName);
3327         goto PerlException;
3328       }
3329     method=CompareAnyLayer;
3330     for (i=2; i < items; i+=2)
3331     {
3332       attribute=(char *) SvPV(ST(i-1),na);
3333       switch (*attribute)
3334       {
3335         case 'M':
3336         case 'm':
3337         {
3338           if (LocaleCompare(attribute,"method") == 0)
3339             {
3340               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
3341                 SvPV(ST(i),na));
3342               if (option < 0)
3343                 {
3344                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
3345                     SvPV(ST(i),na));
3346                   break;
3347                 }
3348                method=(ImageLayerMethod) option;
3349               break;
3350             }
3351           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3352             attribute);
3353           break;
3354         }
3355         default:
3356         {
3357           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3358             attribute);
3359           break;
3360         }
3361       }
3362     }
3363     image=CompareImageLayers(image,method,exception);
3364     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3365       goto PerlException;
3366     for ( ; image; image=image->next)
3367     {
3368       AddImageToRegistry(sv,image);
3369       rv=newRV(sv);
3370       av_push(av,sv_bless(rv,hv));
3371       SvREFCNT_dec(sv);
3372     }
3373     exception=DestroyExceptionInfo(exception);
3374     ST(0)=av_reference;
3375     SvREFCNT_dec(perl_exception);
3376     XSRETURN(1);
3377
3378   PerlException:
3379     InheritPerlException(exception,perl_exception);
3380     exception=DestroyExceptionInfo(exception);
3381     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3382     SvPOK_on(perl_exception);
3383     ST(0)=sv_2mortal(perl_exception);
3384     XSRETURN(1);
3385   }
3386 \f
3387 #
3388 ###############################################################################
3389 #                                                                             #
3390 #                                                                             #
3391 #                                                                             #
3392 #   D e s t r o y                                                             #
3393 #                                                                             #
3394 #                                                                             #
3395 #                                                                             #
3396 ###############################################################################
3397 #
3398 #
3399 void
3400 DESTROY(ref)
3401   Image::Magick ref=NO_INIT
3402   PPCODE:
3403   {
3404     SV
3405       *reference;
3406
3407     PERL_UNUSED_VAR(ref);
3408     if (sv_isobject(ST(0)) == 0)
3409       croak("ReferenceIsNotMyType");
3410     reference=SvRV(ST(0));
3411     switch (SvTYPE(reference))
3412     {
3413       case SVt_PVAV:
3414       {
3415         char
3416           message[MaxTextExtent];
3417
3418         const SV
3419           *key;
3420
3421         HV
3422           *hv;
3423
3424         GV
3425           **gvp;
3426
3427         struct PackageInfo
3428           *info;
3429
3430         SV
3431           *sv;
3432
3433         /*
3434           Array (AV *) reference
3435         */
3436         (void) FormatLocaleString(message,MaxTextExtent,"package%s%p",
3437           XS_VERSION,reference);
3438         hv=gv_stashpv(PackageName, FALSE);
3439         if (!hv)
3440           break;
3441         gvp=(GV **) hv_fetch(hv,message,(long) strlen(message),FALSE);
3442         if (!gvp)
3443           break;
3444         sv=GvSV(*gvp);
3445         if (sv && (SvREFCNT(sv) == 1) && SvIOK(sv))
3446           {
3447             info=(struct PackageInfo *) SvIV(sv);
3448             DestroyPackageInfo(info);
3449           }
3450         key=hv_delete(hv,message,(long) strlen(message),G_DISCARD);
3451         (void) key;
3452         break;
3453       }
3454       case SVt_PVMG:
3455       {
3456         Image
3457           *image;
3458
3459         /*
3460           Blessed scalar = (Image *) SvIV(reference)
3461         */
3462         image=(Image *) SvIV(reference);
3463         if (image != (Image *) NULL)
3464           DeleteImageFromRegistry(reference,image);
3465         break;
3466       }
3467       default:
3468         break;
3469     }
3470   }
3471 \f
3472 #
3473 ###############################################################################
3474 #                                                                             #
3475 #                                                                             #
3476 #                                                                             #
3477 #   D i s p l a y                                                             #
3478 #                                                                             #
3479 #                                                                             #
3480 #                                                                             #
3481 ###############################################################################
3482 #
3483 #
3484 void
3485 Display(ref,...)
3486   Image::Magick ref=NO_INIT
3487   ALIAS:
3488     DisplayImage  = 1
3489     display       = 2
3490     displayimage  = 3
3491   PPCODE:
3492   {
3493     ExceptionInfo
3494       *exception;
3495
3496     Image
3497       *image;
3498
3499     register ssize_t
3500       i;
3501
3502     struct PackageInfo
3503       *info,
3504       *package_info;
3505
3506     SV
3507       *perl_exception,
3508       *reference;
3509
3510     PERL_UNUSED_VAR(ref);
3511     PERL_UNUSED_VAR(ix);
3512     exception=AcquireExceptionInfo();
3513     perl_exception=newSVpv("",0);
3514     package_info=(struct PackageInfo *) NULL;
3515     if (sv_isobject(ST(0)) == 0)
3516       {
3517         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3518           PackageName);
3519         goto PerlException;
3520       }
3521     reference=SvRV(ST(0));
3522     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3523     if (image == (Image *) NULL)
3524       {
3525         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3526           PackageName);
3527         goto PerlException;
3528       }
3529     package_info=ClonePackageInfo(info,exception);
3530     if (items == 2)
3531       SetAttribute(aTHX_ package_info,NULL,"server",ST(1),exception);
3532     else
3533       if (items > 2)
3534         for (i=2; i < items; i+=2)
3535           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
3536             exception);
3537     (void) DisplayImages(package_info->image_info,image);
3538     (void) CatchImageException(image);
3539     InheritException(exception,&image->exception);
3540
3541   PerlException:
3542     if (package_info != (struct PackageInfo *) NULL)
3543       DestroyPackageInfo(package_info);
3544     InheritPerlException(exception,perl_exception);
3545     exception=DestroyExceptionInfo(exception);
3546     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3547     SvPOK_on(perl_exception);
3548     ST(0)=sv_2mortal(perl_exception);
3549     XSRETURN(1);
3550   }
3551 \f
3552 #
3553 ###############################################################################
3554 #                                                                             #
3555 #                                                                             #
3556 #                                                                             #
3557 #   E v a l u a t e I m a g e s                                               #
3558 #                                                                             #
3559 #                                                                             #
3560 #                                                                             #
3561 ###############################################################################
3562 #
3563 #
3564 void
3565 EvaluateImages(ref)
3566   Image::Magick ref=NO_INIT
3567   ALIAS:
3568     EvaluateImages   = 1
3569     evaluateimages   = 2
3570   PPCODE:
3571   {
3572     AV
3573       *av;
3574
3575     char
3576       *attribute,
3577       *p;
3578
3579     ExceptionInfo
3580       *exception;
3581
3582     HV
3583       *hv;
3584
3585     Image
3586       *image;
3587
3588     MagickEvaluateOperator
3589       op;
3590
3591     register ssize_t
3592       i;
3593
3594     struct PackageInfo
3595       *info;
3596
3597     SV
3598       *perl_exception,
3599       *reference,
3600       *rv,
3601       *sv;
3602
3603     PERL_UNUSED_VAR(ref);
3604     PERL_UNUSED_VAR(ix);
3605     exception=AcquireExceptionInfo();
3606     perl_exception=newSVpv("",0);
3607     sv=NULL;
3608     if (sv_isobject(ST(0)) == 0)
3609       {
3610         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3611           PackageName);
3612         goto PerlException;
3613       }
3614     reference=SvRV(ST(0));
3615     hv=SvSTASH(reference);
3616     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3617     if (image == (Image *) NULL)
3618       {
3619         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3620           PackageName);
3621         goto PerlException;
3622       }
3623     op=MeanEvaluateOperator;
3624     if (items == 2)
3625       {
3626         ssize_t
3627           in;
3628
3629         in=ParseCommandOption(MagickEvaluateOptions,MagickFalse,(char *)
3630           SvPV(ST(1),na));
3631         if (in < 0)
3632           {
3633             ThrowPerlException(exception,OptionError,"UnrecognizedType",
3634               SvPV(ST(1),na));
3635             return;
3636           }
3637         op=(MagickEvaluateOperator) in;
3638       }
3639     else
3640       for (i=2; i < items; i+=2)
3641       {
3642         attribute=(char *) SvPV(ST(i-1),na);
3643         switch (*attribute)
3644         {
3645           case 'O':
3646           case 'o':
3647           {
3648             if (LocaleCompare(attribute,"operator") == 0)
3649               {
3650                 ssize_t
3651                   in;
3652
3653                 in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
3654                   MagickEvaluateOptions,MagickFalse,SvPV(ST(i),na));
3655                 if (in < 0)
3656                   {
3657                     ThrowPerlException(exception,OptionError,"UnrecognizedType",
3658                       SvPV(ST(i),na));
3659                     return;
3660                   }
3661                 op=(MagickEvaluateOperator) in;
3662                 break;
3663               }
3664             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3665               attribute);
3666             break;
3667           }
3668           default:
3669           {
3670             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3671               attribute);
3672             break;
3673           }
3674         }
3675       }
3676     image=EvaluateImages(image,op,exception);
3677     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3678       goto PerlException;
3679     /*
3680       Create blessed Perl array for the returned image.
3681     */
3682     av=newAV();
3683     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3684     SvREFCNT_dec(av);
3685     AddImageToRegistry(sv,image);
3686     rv=newRV(sv);
3687     av_push(av,sv_bless(rv,hv));
3688     SvREFCNT_dec(sv);
3689     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3690     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
3691       "evaluate-%.*s",(int) (MaxTextExtent-9),
3692       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
3693     (void) CopyMagickString(image->filename,info->image_info->filename,
3694       MaxTextExtent);
3695     SetImageInfo(info->image_info,0,exception);
3696     exception=DestroyExceptionInfo(exception);
3697     SvREFCNT_dec(perl_exception);
3698     XSRETURN(1);
3699
3700   PerlException:
3701     InheritPerlException(exception,perl_exception);
3702     exception=DestroyExceptionInfo(exception);
3703     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
3704     SvPOK_on(perl_exception);
3705     ST(0)=sv_2mortal(perl_exception);
3706     XSRETURN(1);
3707   }
3708 \f
3709 #
3710 ###############################################################################
3711 #                                                                             #
3712 #                                                                             #
3713 #                                                                             #
3714 #   F e a t u r e s                                                           #
3715 #                                                                             #
3716 #                                                                             #
3717 #                                                                             #
3718 ###############################################################################
3719 #
3720 #
3721 void
3722 Features(ref,...)
3723   Image::Magick ref=NO_INIT
3724   ALIAS:
3725     FeaturesImage = 1
3726     features      = 2
3727     featuresimage = 3
3728   PPCODE:
3729   {
3730 #define ChannelFeatures(channel,direction) \
3731 { \
3732   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3733     channel_features[channel].angular_second_moment[direction]); \
3734   PUSHs(sv_2mortal(newSVpv(message,0))); \
3735   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3736     channel_features[channel].contrast[direction]); \
3737   PUSHs(sv_2mortal(newSVpv(message,0))); \
3738   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3739     channel_features[channel].contrast[direction]); \
3740   PUSHs(sv_2mortal(newSVpv(message,0))); \
3741   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3742     channel_features[channel].variance_sum_of_squares[direction]); \
3743   PUSHs(sv_2mortal(newSVpv(message,0))); \
3744   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3745     channel_features[channel].inverse_difference_moment[direction]); \
3746   PUSHs(sv_2mortal(newSVpv(message,0))); \
3747   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3748     channel_features[channel].sum_average[direction]); \
3749   PUSHs(sv_2mortal(newSVpv(message,0))); \
3750   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3751     channel_features[channel].sum_variance[direction]); \
3752   PUSHs(sv_2mortal(newSVpv(message,0))); \
3753   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3754     channel_features[channel].sum_entropy[direction]); \
3755   PUSHs(sv_2mortal(newSVpv(message,0))); \
3756   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3757     channel_features[channel].entropy[direction]); \
3758   PUSHs(sv_2mortal(newSVpv(message,0))); \
3759   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3760     channel_features[channel].difference_variance[direction]); \
3761   PUSHs(sv_2mortal(newSVpv(message,0))); \
3762   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3763     channel_features[channel].difference_entropy[direction]); \
3764   PUSHs(sv_2mortal(newSVpv(message,0))); \
3765   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3766     channel_features[channel].measure_of_correlation_1[direction]); \
3767   PUSHs(sv_2mortal(newSVpv(message,0))); \
3768   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3769     channel_features[channel].measure_of_correlation_2[direction]); \
3770   PUSHs(sv_2mortal(newSVpv(message,0))); \
3771   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
3772     channel_features[channel].maximum_correlation_coefficient[direction]); \
3773   PUSHs(sv_2mortal(newSVpv(message,0))); \
3774 }
3775
3776     AV
3777       *av;
3778
3779     char
3780       *attribute,
3781       message[MaxTextExtent];
3782
3783     ChannelFeatures
3784       *channel_features;
3785
3786     double
3787       distance;
3788
3789     ExceptionInfo
3790       *exception;
3791
3792     Image
3793       *image;
3794
3795     register ssize_t
3796       i;
3797
3798     ssize_t
3799       count;
3800
3801     struct PackageInfo
3802       *info;
3803
3804     SV
3805       *perl_exception,
3806       *reference;
3807
3808     PERL_UNUSED_VAR(ref);
3809     PERL_UNUSED_VAR(ix);
3810     exception=AcquireExceptionInfo();
3811     perl_exception=newSVpv("",0);
3812     av=NULL;
3813     if (sv_isobject(ST(0)) == 0)
3814       {
3815         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3816           PackageName);
3817         goto PerlException;
3818       }
3819     reference=SvRV(ST(0));
3820     av=newAV();
3821     SvREFCNT_dec(av);
3822     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3823     if (image == (Image *) NULL)
3824       {
3825         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3826           PackageName);
3827         goto PerlException;
3828       }
3829     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
3830     distance=1;
3831     for (i=2; i < items; i+=2)
3832     {
3833       attribute=(char *) SvPV(ST(i-1),na);
3834       switch (*attribute)
3835       {
3836         case 'D':
3837         case 'd':
3838         {
3839           if (LocaleCompare(attribute,"distance") == 0)
3840             {
3841               distance=StringToLong((char *) SvPV(ST(1),na));
3842               break;
3843             }
3844           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3845             attribute);
3846           break;
3847         }
3848         default:
3849         {
3850           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3851             attribute);
3852           break;
3853         }
3854       }
3855     }
3856     count=0;
3857     for ( ; image; image=image->next)
3858     {
3859       channel_features=GetImageChannelFeatures(image,distance,
3860         &image->exception);
3861       if (channel_features == (ChannelFeatures *) NULL)
3862         continue;
3863       count++;
3864       EXTEND(sp,75*count);
3865       for (i=0; i < 4; i++)
3866       {
3867         ChannelFeatures(RedChannel,i);
3868         ChannelFeatures(GreenChannel,i);
3869         ChannelFeatures(BlueChannel,i);
3870         if (image->colorspace == CMYKColorspace)
3871           ChannelFeatures(BlackChannel,i);
3872         if (image->matte != MagickFalse)
3873           ChannelFeatures(AlphaChannel,i);
3874       }
3875       channel_features=(ChannelFeatures *)
3876         RelinquishMagickMemory(channel_features);
3877     }
3878
3879   PerlException:
3880     InheritPerlException(exception,perl_exception);
3881     exception=DestroyExceptionInfo(exception);
3882     SvREFCNT_dec(perl_exception);
3883   }
3884 \f
3885 #
3886 ###############################################################################
3887 #                                                                             #
3888 #                                                                             #
3889 #                                                                             #
3890 #   F l a t t e n                                                             #
3891 #                                                                             #
3892 #                                                                             #
3893 #                                                                             #
3894 ###############################################################################
3895 #
3896 #
3897 void
3898 Flatten(ref)
3899   Image::Magick ref=NO_INIT
3900   ALIAS:
3901     FlattenImage   = 1
3902     flatten        = 2
3903     flattenimage   = 3
3904   PPCODE:
3905   {
3906     AV
3907       *av;
3908
3909     char
3910       *attribute,
3911       *p;
3912
3913     ExceptionInfo
3914       *exception;
3915
3916     HV
3917       *hv;
3918
3919     Image
3920       *image;
3921
3922     PixelPacket
3923       background_color;
3924
3925     register ssize_t
3926       i;
3927
3928     struct PackageInfo
3929       *info;
3930
3931     SV
3932       *perl_exception,
3933       *reference,
3934       *rv,
3935       *sv;
3936
3937     PERL_UNUSED_VAR(ref);
3938     PERL_UNUSED_VAR(ix);
3939     exception=AcquireExceptionInfo();
3940     perl_exception=newSVpv("",0);
3941     sv=NULL;
3942     if (sv_isobject(ST(0)) == 0)
3943       {
3944         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
3945           PackageName);
3946         goto PerlException;
3947       }
3948     reference=SvRV(ST(0));
3949     hv=SvSTASH(reference);
3950     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
3951     if (image == (Image *) NULL)
3952       {
3953         ThrowPerlException(exception,OptionError,"NoImagesDefined",
3954           PackageName);
3955         goto PerlException;
3956       }
3957     background_color=image->background_color;
3958     if (items == 2)
3959       (void) QueryColorDatabase((char *) SvPV(ST(1),na),&background_color,
3960         exception);
3961     else
3962       for (i=2; i < items; i+=2)
3963       {
3964         attribute=(char *) SvPV(ST(i-1),na);
3965         switch (*attribute)
3966         {
3967           case 'B':
3968           case 'b':
3969           {
3970             if (LocaleCompare(attribute,"background") == 0)
3971               {
3972                 (void) QueryColorDatabase((char *) SvPV(ST(1),na),
3973                   &background_color,exception);
3974                 break;
3975               }
3976             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3977               attribute);
3978             break;
3979           }
3980           default:
3981           {
3982             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
3983               attribute);
3984             break;
3985           }
3986         }
3987       }
3988     image->background_color=background_color;
3989     image=MergeImageLayers(image,FlattenLayer,exception);
3990     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
3991       goto PerlException;
3992     /*
3993       Create blessed Perl array for the returned image.
3994     */
3995     av=newAV();
3996     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
3997     SvREFCNT_dec(av);
3998     AddImageToRegistry(sv,image);
3999     rv=newRV(sv);
4000     av_push(av,sv_bless(rv,hv));
4001     SvREFCNT_dec(sv);
4002     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4003     (void) FormatLocaleString(info->image_info->filename,MaxTextExtent,
4004       "flatten-%.*s",(int) (MaxTextExtent-9),
4005       ((p=strrchr(image->filename,'/')) ? p+1 : image->filename));
4006     (void) CopyMagickString(image->filename,info->image_info->filename,
4007       MaxTextExtent);
4008     SetImageInfo(info->image_info,0,exception);
4009     exception=DestroyExceptionInfo(exception);
4010     SvREFCNT_dec(perl_exception);
4011     XSRETURN(1);
4012
4013   PerlException:
4014     InheritPerlException(exception,perl_exception);
4015     exception=DestroyExceptionInfo(exception);
4016     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4017     SvPOK_on(perl_exception);  /* return messages in string context */
4018     ST(0)=sv_2mortal(perl_exception);
4019     XSRETURN(1);
4020   }
4021 \f
4022 #
4023 ###############################################################################
4024 #                                                                             #
4025 #                                                                             #
4026 #                                                                             #
4027 #   F x                                                                       #
4028 #                                                                             #
4029 #                                                                             #
4030 #                                                                             #
4031 ###############################################################################
4032 #
4033 #
4034 void
4035 Fx(ref,...)
4036   Image::Magick ref=NO_INIT
4037   ALIAS:
4038     FxImage  = 1
4039     fx       = 2
4040     fximage  = 3
4041   PPCODE:
4042   {
4043     AV
4044       *av;
4045
4046     char
4047       *attribute,
4048       expression[MaxTextExtent];
4049
4050     ChannelType
4051       channel;
4052
4053     ExceptionInfo
4054       *exception;
4055
4056     HV
4057       *hv;
4058
4059     Image
4060       *image;
4061
4062     register ssize_t
4063       i;
4064
4065     struct PackageInfo
4066       *info;
4067
4068     SV
4069       *av_reference,
4070       *perl_exception,
4071       *reference,
4072       *rv,
4073       *sv;
4074
4075     PERL_UNUSED_VAR(ref);
4076     PERL_UNUSED_VAR(ix);
4077     exception=AcquireExceptionInfo();
4078     perl_exception=newSVpv("",0);
4079     sv=NULL;
4080     attribute=NULL;
4081     av=NULL;
4082     if (sv_isobject(ST(0)) == 0)
4083       {
4084         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4085           PackageName);
4086         goto PerlException;
4087       }
4088     reference=SvRV(ST(0));
4089     hv=SvSTASH(reference);
4090     av=newAV();
4091     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
4092     SvREFCNT_dec(av);
4093     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4094     if (image == (Image *) NULL)
4095       {
4096         ThrowPerlException(exception,OptionError,"NoImagesDefined",
4097           PackageName);
4098         goto PerlException;
4099       }
4100     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
4101     /*
4102       Get options.
4103     */
4104     channel=DefaultChannels;
4105     (void) CopyMagickString(expression,"u",MaxTextExtent);
4106     if (items == 2)
4107       (void) CopyMagickString(expression,(char *) SvPV(ST(1),na),MaxTextExtent);
4108     else
4109       for (i=2; i < items; i+=2)
4110       {
4111         attribute=(char *) SvPV(ST(i-1),na);
4112         switch (*attribute)
4113         {
4114           case 'C':
4115           case 'c':
4116           {
4117             if (LocaleCompare(attribute,"channel") == 0)
4118               {
4119                 ssize_t
4120                   option;
4121
4122                 option=ParseChannelOption(SvPV(ST(i),na));
4123                 if (option < 0)
4124                   {
4125                     ThrowPerlException(exception,OptionError,
4126                       "UnrecognizedType",SvPV(ST(i),na));
4127                     return;
4128                   }
4129                 channel=(ChannelType) option;
4130                 break;
4131               }
4132             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4133               attribute);
4134             break;
4135           }
4136           case 'E':
4137           case 'e':
4138           {
4139             if (LocaleCompare(attribute,"expression") == 0)
4140               {
4141                 (void) CopyMagickString(expression,SvPV(ST(i),na),
4142                   MaxTextExtent);
4143                 break;
4144               }
4145             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4146               attribute);
4147             break;
4148           }
4149           default:
4150           {
4151             ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4152               attribute);
4153             break;
4154           }
4155         }
4156       }
4157     image=FxImageChannel(image,channel,expression,exception);
4158     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
4159       goto PerlException;
4160     for ( ; image; image=image->next)
4161     {
4162       AddImageToRegistry(sv,image);
4163       rv=newRV(sv);
4164       av_push(av,sv_bless(rv,hv));
4165       SvREFCNT_dec(sv);
4166     }
4167     exception=DestroyExceptionInfo(exception);
4168     ST(0)=av_reference;
4169     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
4170     XSRETURN(1);
4171
4172   PerlException:
4173     InheritPerlException(exception,perl_exception);
4174     exception=DestroyExceptionInfo(exception);
4175     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
4176     SvPOK_on(perl_exception);
4177     ST(0)=sv_2mortal(perl_exception);
4178     XSRETURN(1);
4179   }
4180 \f
4181 #
4182 ###############################################################################
4183 #                                                                             #
4184 #                                                                             #
4185 #                                                                             #
4186 #   G e t                                                                     #
4187 #                                                                             #
4188 #                                                                             #
4189 #                                                                             #
4190 ###############################################################################
4191 #
4192 #
4193 void
4194 Get(ref,...)
4195   Image::Magick ref=NO_INIT
4196   ALIAS:
4197     GetAttributes = 1
4198     GetAttribute  = 2
4199     get           = 3
4200     getattributes = 4
4201     getattribute  = 5
4202   PPCODE:
4203   {
4204     char
4205       *attribute,
4206       color[MaxTextExtent];
4207
4208     const char
4209       *value;
4210
4211     ExceptionInfo
4212       *exception;
4213
4214     Image
4215       *image;
4216
4217     long
4218       j;
4219
4220     register ssize_t
4221       i;
4222
4223     struct PackageInfo
4224       *info;
4225
4226     SV
4227       *perl_exception,
4228       *reference,
4229       *s;
4230
4231     PERL_UNUSED_VAR(ref);
4232     PERL_UNUSED_VAR(ix);
4233     exception=AcquireExceptionInfo();
4234     perl_exception=newSVpv("",0);
4235     if (sv_isobject(ST(0)) == 0)
4236       {
4237         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
4238           PackageName);
4239         XSRETURN_EMPTY;
4240       }
4241     reference=SvRV(ST(0));
4242     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
4243     if (image == (Image *) NULL && !info)
4244       XSRETURN_EMPTY;
4245     EXTEND(sp,items);
4246     for (i=1; i < items; i++)
4247     {
4248       attribute=(char *) SvPV(ST(i),na);
4249       s=NULL;
4250       switch (*attribute)
4251       {
4252         case 'A':
4253         case 'a':
4254         {
4255           if (LocaleCompare(attribute,"adjoin") == 0)
4256             {
4257               if (info)
4258                 s=newSViv((ssize_t) info->image_info->adjoin);
4259               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4260               continue;
4261             }
4262           if (LocaleCompare(attribute,"antialias") == 0)
4263             {
4264               if (info)
4265                 s=newSViv((ssize_t) info->image_info->antialias);
4266               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4267               continue;
4268             }
4269           if (LocaleCompare(attribute,"area") == 0)
4270             {
4271               s=newSViv(GetMagickResource(AreaResource));
4272               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4273               continue;
4274             }
4275           if (LocaleCompare(attribute,"attenuate") == 0)
4276             {
4277               const char
4278                 *value;
4279
4280               value=GetImageProperty(image,attribute);
4281               if (value != (const char *) NULL)
4282                 s=newSVpv(value,0);
4283               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4284               continue;
4285             }
4286           if (LocaleCompare(attribute,"authenticate") == 0)
4287             {
4288               if (info)
4289                 s=newSVpv(info->image_info->authenticate,0);
4290               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4291               continue;
4292             }
4293           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4294             attribute);
4295           break;
4296         }
4297         case 'B':
4298         case 'b':
4299         {
4300           if (LocaleCompare(attribute,"background") == 0)
4301             {
4302               if (image == (Image *) NULL)
4303                 break;
4304               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4305                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4306                 image->background_color.red,image->background_color.green,
4307                 image->background_color.blue,image->background_color.alpha);
4308               s=newSVpv(color,0);
4309               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4310               continue;
4311             }
4312           if (LocaleCompare(attribute,"base-columns") == 0)
4313             {
4314               if (image != (Image *) NULL)
4315                 s=newSViv((ssize_t) image->magick_columns);
4316               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4317               continue;
4318             }
4319           if (LocaleCompare(attribute,"base-filename") == 0)
4320             {
4321               if (image != (Image *) NULL)
4322                 s=newSVpv(image->magick_filename,0);
4323               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4324               continue;
4325             }
4326           if (LocaleCompare(attribute,"base-height") == 0)
4327             {
4328               if (image != (Image *) NULL)
4329                 s=newSViv((ssize_t) image->magick_rows);
4330               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4331               continue;
4332             }
4333           if (LocaleCompare(attribute,"base-rows") == 0)
4334             {
4335               if (image != (Image *) NULL)
4336                 s=newSViv((ssize_t) image->magick_rows);
4337               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4338               continue;
4339             }
4340           if (LocaleCompare(attribute,"base-width") == 0)
4341             {
4342               if (image != (Image *) NULL)
4343                 s=newSViv((ssize_t) image->magick_columns);
4344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4345               continue;
4346             }
4347           if (LocaleCompare(attribute,"bias") == 0)
4348             {
4349               if (image != (Image *) NULL)
4350                 s=newSVnv(image->bias);
4351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4352               continue;
4353             }
4354           if (LocaleCompare(attribute,"blue-primary") == 0)
4355             {
4356               if (image == (Image *) NULL)
4357                 break;
4358               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4359                 image->chromaticity.blue_primary.x,
4360                 image->chromaticity.blue_primary.y);
4361               s=newSVpv(color,0);
4362               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4363               continue;
4364             }
4365           if (LocaleCompare(attribute,"bordercolor") == 0)
4366             {
4367               if (image == (Image *) NULL)
4368                 break;
4369               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4370                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4371                 image->border_color.red,image->border_color.green,
4372                 image->border_color.blue,image->border_color.alpha);
4373               s=newSVpv(color,0);
4374               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4375               continue;
4376             }
4377           if (LocaleCompare(attribute,"bounding-box") == 0)
4378             {
4379               char
4380                 geometry[MaxTextExtent];
4381
4382               RectangleInfo
4383                 page;
4384
4385               if (image == (Image *) NULL)
4386                 break;
4387               page=GetImageBoundingBox(image,&image->exception);
4388               (void) FormatLocaleString(geometry,MaxTextExtent,
4389                 "%.20gx%.20g%+.20g%+.20g",(double) page.width,(double)
4390                 page.height,(double) page.x,(double) page.y);
4391               s=newSVpv(geometry,0);
4392               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4393               continue;
4394             }
4395           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4396             attribute);
4397           break;
4398         }
4399         case 'C':
4400         case 'c':
4401         {
4402           if (LocaleCompare(attribute,"class") == 0)
4403             {
4404               if (image == (Image *) NULL)
4405                 break;
4406               s=newSViv(image->storage_class);
4407               (void) sv_setpv(s,CommandOptionToMnemonic(MagickClassOptions,
4408                 image->storage_class));
4409               SvIOK_on(s);
4410               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4411               continue;
4412             }
4413           if (LocaleCompare(attribute,"clip-mask") == 0)
4414             {
4415               if (image != (Image *) NULL)
4416                 {
4417                   SV
4418                     *sv;
4419
4420                   sv=NULL;
4421                   if (image->mask == (Image *) NULL)
4422                     ClipImage(image);
4423                   if (image->mask != (Image *) NULL)
4424                     {
4425                       AddImageToRegistry(sv,image->mask);
4426                       s=sv_bless(newRV(sv),SvSTASH(reference));
4427                     }
4428                 }
4429               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4430               continue;
4431             }
4432           if (LocaleCompare(attribute,"clip-path") == 0)
4433             {
4434               if (image != (Image *) NULL)
4435                 {
4436                   SV
4437                     *sv;
4438
4439                   sv=NULL;
4440                   if (image->clip_mask == (Image *) NULL)
4441                     ClipImage(image);
4442                   if (image->clip_mask != (Image *) NULL)
4443                     {
4444                       AddImageToRegistry(sv,image->clip_mask);
4445                       s=sv_bless(newRV(sv),SvSTASH(reference));
4446                     }
4447                 }
4448               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4449               continue;
4450             }
4451           if (LocaleCompare(attribute,"compression") == 0)
4452             {
4453               j=info ? info->image_info->compression : image ?
4454                 image->compression : UndefinedCompression;
4455               if (info)
4456                 if (info->image_info->compression == UndefinedCompression)
4457                   j=image->compression;
4458               s=newSViv(j);
4459               (void) sv_setpv(s,CommandOptionToMnemonic(MagickCompressOptions,
4460                 j));
4461               SvIOK_on(s);
4462               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4463               continue;
4464             }
4465           if (LocaleCompare(attribute,"colorspace") == 0)
4466             {
4467               j=image ? image->colorspace : RGBColorspace;
4468               s=newSViv(j);
4469               (void) sv_setpv(s,CommandOptionToMnemonic(MagickColorspaceOptions,
4470                 j));
4471               SvIOK_on(s);
4472               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4473               continue;
4474             }
4475           if (LocaleCompare(attribute,"colors") == 0)
4476             {
4477               if (image != (Image *) NULL)
4478                 s=newSViv((ssize_t) GetNumberColors(image,(FILE *) NULL,
4479                   &image->exception));
4480               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4481               continue;
4482             }
4483           if (LocaleNCompare(attribute,"colormap",8) == 0)
4484             {
4485               int
4486                 items;
4487
4488               if (image == (Image *) NULL || !image->colormap)
4489                 break;
4490               j=0;
4491               items=sscanf(attribute,"%*[^[][%ld",&j);
4492               (void) items;
4493               if (j > (ssize_t) image->colors)
4494                 j%=image->colors;
4495               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4496                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4497                 image->colormap[j].red,image->colormap[j].green,
4498                 image->colormap[j].blue,image->colormap[j].alpha);
4499               s=newSVpv(color,0);
4500               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4501               continue;
4502             }
4503           if (LocaleCompare(attribute,"columns") == 0)
4504             {
4505               if (image != (Image *) NULL)
4506                 s=newSViv((ssize_t) image->columns);
4507               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4508               continue;
4509             }
4510           if (LocaleCompare(attribute,"comment") == 0)
4511             {
4512               const char
4513                 *value;
4514
4515               value=GetImageProperty(image,attribute);
4516               if (value != (const char *) NULL)
4517                 s=newSVpv(value,0);
4518               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4519               continue;
4520             }
4521           if (LocaleCompare(attribute,"copyright") == 0)
4522             {
4523               s=newSVpv(GetMagickCopyright(),0);
4524               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4525               continue;
4526             }
4527           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4528             attribute);
4529           break;
4530         }
4531         case 'D':
4532         case 'd':
4533         {
4534           if (LocaleCompare(attribute,"density") == 0)
4535             {
4536               char
4537                 geometry[MaxTextExtent];
4538
4539               if (image == (Image *) NULL)
4540                 break;
4541               (void) FormatLocaleString(geometry,MaxTextExtent,"%.15gx%.15g",
4542                 image->x_resolution,image->y_resolution);
4543               s=newSVpv(geometry,0);
4544               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4545               continue;
4546             }
4547           if (LocaleCompare(attribute,"delay") == 0)
4548             {
4549               if (image != (Image *) NULL)
4550                 s=newSViv((ssize_t) image->delay);
4551               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4552               continue;
4553             }
4554           if (LocaleCompare(attribute,"depth") == 0)
4555             {
4556               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
4557               if (image != (Image *) NULL)
4558                 s=newSViv((ssize_t) GetImageDepth(image,&image->exception));
4559               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4560               continue;
4561             }
4562           if (LocaleCompare(attribute,"directory") == 0)
4563             {
4564               if (image && image->directory)
4565                 s=newSVpv(image->directory,0);
4566               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4567               continue;
4568             }
4569           if (LocaleCompare(attribute,"dispose") == 0)
4570             {
4571               if (image == (Image *) NULL)
4572                 break;
4573
4574               s=newSViv(image->dispose);
4575               (void) sv_setpv(s,
4576                 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose));
4577               SvIOK_on(s);
4578               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4579               continue;
4580             }
4581           if (LocaleCompare(attribute,"disk") == 0)
4582             {
4583               s=newSViv(GetMagickResource(DiskResource));
4584               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4585               continue;
4586             }
4587           if (LocaleCompare(attribute,"dither") == 0)
4588             {
4589               if (info)
4590                 s=newSViv((ssize_t) info->image_info->dither);
4591               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4592               continue;
4593             }
4594           if (LocaleCompare(attribute,"display") == 0)  /* same as server */
4595             {
4596               if (info && info->image_info->server_name)
4597                 s=newSVpv(info->image_info->server_name,0);
4598               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4599               continue;
4600             }
4601           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4602             attribute);
4603           break;
4604         }
4605         case 'E':
4606         case 'e':
4607         {
4608           if (LocaleCompare(attribute,"elapsed-time") == 0)
4609             {
4610               if (image != (Image *) NULL)
4611                 s=newSVnv(GetElapsedTime(&image->timer));
4612               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4613               continue;
4614             }
4615           if (LocaleCompare(attribute,"endian") == 0)
4616             {
4617               j=info ? info->image_info->endian : image ? image->endian :
4618                 UndefinedEndian;
4619               s=newSViv(j);
4620               (void) sv_setpv(s,CommandOptionToMnemonic(MagickEndianOptions,j));
4621               SvIOK_on(s);
4622               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4623               continue;
4624             }
4625           if (LocaleCompare(attribute,"error") == 0)
4626             {
4627               if (image != (Image *) NULL)
4628                 s=newSVnv(image->error.mean_error_per_pixel);
4629               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4630               continue;
4631             }
4632           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4633             attribute);
4634           break;
4635         }
4636         case 'F':
4637         case 'f':
4638         {
4639           if (LocaleCompare(attribute,"filesize") == 0)
4640             {
4641               if (image != (Image *) NULL)
4642                 s=newSViv((ssize_t) GetBlobSize(image));
4643               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4644               continue;
4645             }
4646           if (LocaleCompare(attribute,"filename") == 0)
4647             {
4648               if (info && info->image_info->filename &&
4649                   *info->image_info->filename)
4650                 s=newSVpv(info->image_info->filename,0);
4651               if (image != (Image *) NULL)
4652                 s=newSVpv(image->filename,0);
4653               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4654               continue;
4655             }
4656           if (LocaleCompare(attribute,"filter") == 0)
4657             {
4658               s=image ? newSViv(image->filter) : newSViv(0);
4659               (void) sv_setpv(s,CommandOptionToMnemonic(MagickFilterOptions,
4660                 image->filter));
4661               SvIOK_on(s);
4662               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4663               continue;
4664             }
4665           if (LocaleCompare(attribute,"font") == 0)
4666             {
4667               if (info && info->image_info->font)
4668                 s=newSVpv(info->image_info->font,0);
4669               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4670               continue;
4671             }
4672           if (LocaleCompare(attribute,"foreground") == 0)
4673             continue;
4674           if (LocaleCompare(attribute,"format") == 0)
4675             {
4676               const MagickInfo
4677                 *magick_info;
4678
4679               magick_info=(const MagickInfo *) NULL;
4680               if (info && (*info->image_info->magick != '\0'))
4681                 magick_info=GetMagickInfo(info->image_info->magick,exception);
4682               if (image != (Image *) NULL)
4683                 magick_info=GetMagickInfo(image->magick,&image->exception);
4684               if ((magick_info != (const MagickInfo *) NULL) &&
4685                   (*magick_info->description != '\0'))
4686                 s=newSVpv((char *) magick_info->description,0);
4687               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4688               continue;
4689             }
4690           if (LocaleCompare(attribute,"fuzz") == 0)
4691             {
4692               if (info)
4693                 s=newSVnv(info->image_info->fuzz);
4694               if (image != (Image *) NULL)
4695                 s=newSVnv(image->fuzz);
4696               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4697               continue;
4698             }
4699           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4700             attribute);
4701           break;
4702         }
4703         case 'G':
4704         case 'g':
4705         {
4706           if (LocaleCompare(attribute,"gamma") == 0)
4707             {
4708               if (image != (Image *) NULL)
4709                 s=newSVnv(image->gamma);
4710               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4711               continue;
4712             }
4713           if (LocaleCompare(attribute,"geometry") == 0)
4714             {
4715               if (image && image->geometry)
4716                 s=newSVpv(image->geometry,0);
4717               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4718               continue;
4719             }
4720           if (LocaleCompare(attribute,"gravity") == 0)
4721             {
4722               s=image ? newSViv(image->gravity) : newSViv(0);
4723               (void) sv_setpv(s,CommandOptionToMnemonic(MagickGravityOptions,
4724                 image->gravity));
4725               SvIOK_on(s);
4726               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4727               continue;
4728             }
4729           if (LocaleCompare(attribute,"green-primary") == 0)
4730             {
4731               if (image == (Image *) NULL)
4732                 break;
4733               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
4734                 image->chromaticity.green_primary.x,
4735                 image->chromaticity.green_primary.y);
4736               s=newSVpv(color,0);
4737               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4738               continue;
4739             }
4740           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4741             attribute);
4742           break;
4743         }
4744         case 'H':
4745         case 'h':
4746         {
4747           if (LocaleCompare(attribute,"height") == 0)
4748             {
4749               if (image != (Image *) NULL)
4750                 s=newSViv((ssize_t) image->rows);
4751               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4752               continue;
4753             }
4754           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4755             attribute);
4756           break;
4757         }
4758         case 'I':
4759         case 'i':
4760         {
4761           if (LocaleCompare(attribute,"icc") == 0)
4762             {
4763               if (image != (Image *) NULL)
4764                 {
4765                   const StringInfo
4766                     *profile;
4767
4768                   profile=GetImageProfile(image,"icc");
4769                   if (profile != (StringInfo *) NULL)
4770                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4771                       GetStringInfoLength(profile));
4772                 }
4773               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4774               continue;
4775             }
4776           if (LocaleCompare(attribute,"icm") == 0)
4777             {
4778               if (image != (Image *) NULL)
4779                 {
4780                   const StringInfo
4781                     *profile;
4782
4783                   profile=GetImageProfile(image,"icm");
4784                   if (profile != (const StringInfo *) NULL)
4785                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4786                       GetStringInfoLength(profile));
4787                 }
4788               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4789               continue;
4790             }
4791           if (LocaleCompare(attribute,"id") == 0)
4792             {
4793               if (image != (Image *) NULL)
4794                 {
4795                   char
4796                     key[MaxTextExtent];
4797
4798                   MagickBooleanType
4799                     status;
4800
4801                   static ssize_t
4802                     id = 0;
4803
4804                   (void) FormatLocaleString(key,MaxTextExtent,"%.20g\n",(double)
4805                     id);
4806                   status=SetImageRegistry(ImageRegistryType,key,image,
4807                     &image->exception);
4808                   (void) status;
4809                   s=newSViv(id++);
4810                 }
4811               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4812               continue;
4813             }
4814           if (LocaleNCompare(attribute,"index",5) == 0)
4815             {
4816               char
4817                 name[MaxTextExtent];
4818
4819               int
4820                 items;
4821
4822               long
4823                 x,
4824                 y;
4825
4826               register const Quantum
4827                 *p;
4828
4829               CacheView
4830                 *image_view;
4831
4832               if (image == (Image *) NULL)
4833                 break;
4834               if (image->storage_class != PseudoClass)
4835                 break;
4836               x=0;
4837               y=0;
4838               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
4839               (void) items;
4840               image_view=AcquireCacheView(image);
4841               p=GetCacheViewVirtualPixels(image_view,x,y,1,1,&image->exception);
4842               if (p != (const Quantum *) NULL)
4843                 {
4844                   (void) FormatLocaleString(name,MaxTextExtent,QuantumFormat,
4845                     GetPixelIndex(image,p));
4846                   s=newSVpv(name,0);
4847                   PUSHs(s ? sv_2mortal(s) : &sv_undef);
4848                 }
4849               image_view=DestroyCacheView(image_view);
4850               continue;
4851             }
4852           if (LocaleCompare(attribute,"iptc") == 0)
4853             {
4854               if (image != (Image *) NULL)
4855                 {
4856                   const StringInfo
4857                     *profile;
4858
4859                   profile=GetImageProfile(image,"iptc");
4860                   if (profile != (const StringInfo *) NULL)
4861                     s=newSVpv((const char *) GetStringInfoDatum(profile),
4862                       GetStringInfoLength(profile));
4863                 }
4864               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4865               continue;
4866             }
4867           if (LocaleCompare(attribute,"iterations") == 0)  /* same as loop */
4868             {
4869               if (image != (Image *) NULL)
4870                 s=newSViv((ssize_t) image->iterations);
4871               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4872               continue;
4873             }
4874           if (LocaleCompare(attribute,"interlace") == 0)
4875             {
4876               j=info ? info->image_info->interlace : image ? image->interlace :
4877                 UndefinedInterlace;
4878               s=newSViv(j);
4879               (void) sv_setpv(s,CommandOptionToMnemonic(MagickInterlaceOptions,
4880                 j));
4881               SvIOK_on(s);
4882               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4883               continue;
4884             }
4885           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4886             attribute);
4887           break;
4888         }
4889         case 'L':
4890         case 'l':
4891         {
4892           if (LocaleCompare(attribute,"label") == 0)
4893             {
4894               const char
4895                 *value;
4896
4897               if (image == (Image *) NULL)
4898                 break;
4899               value=GetImageProperty(image,"Label");
4900               if (value != (const char *) NULL)
4901                 s=newSVpv(value,0);
4902               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4903               continue;
4904             }
4905           if (LocaleCompare(attribute,"loop") == 0)  /* same as iterations */
4906             {
4907               if (image != (Image *) NULL)
4908                 s=newSViv((ssize_t) image->iterations);
4909               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4910               continue;
4911             }
4912           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
4913             attribute);
4914           break;
4915         }
4916         case 'M':
4917         case 'm':
4918         {
4919           if (LocaleCompare(attribute,"magick") == 0)
4920             {
4921               if (info && *info->image_info->magick)
4922                 s=newSVpv(info->image_info->magick,0);
4923               if (image != (Image *) NULL)
4924                 s=newSVpv(image->magick,0);
4925               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4926               continue;
4927             }
4928           if (LocaleCompare(attribute,"map") == 0)
4929             {
4930               s=newSViv(GetMagickResource(MapResource));
4931               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4932               continue;
4933             }
4934           if (LocaleCompare(attribute,"maximum-error") == 0)
4935             {
4936               if (image != (Image *) NULL)
4937                 s=newSVnv(image->error.normalized_maximum_error);
4938               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4939               continue;
4940             }
4941           if (LocaleCompare(attribute,"memory") == 0)
4942             {
4943               s=newSViv(GetMagickResource(MemoryResource));
4944               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4945               continue;
4946             }
4947           if (LocaleCompare(attribute,"mean-error") == 0)
4948             {
4949               if (image != (Image *) NULL)
4950                 s=newSVnv(image->error.normalized_mean_error);
4951               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4952               continue;
4953             }
4954           if (LocaleCompare(attribute,"mime") == 0)
4955             {
4956               if (info && *info->image_info->magick)
4957                 s=newSVpv(MagickToMime(info->image_info->magick),0);
4958               if (image != (Image *) NULL)
4959                 s=newSVpv(MagickToMime(image->magick),0);
4960               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4961               continue;
4962             }
4963           if (LocaleCompare(attribute,"mattecolor") == 0)
4964             {
4965               if (image == (Image *) NULL)
4966                 break;
4967               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
4968                 QuantumFormat "," QuantumFormat "," QuantumFormat,
4969                 image->matte_color.red,image->matte_color.green,
4970                 image->matte_color.blue,image->matte_color.alpha);
4971               s=newSVpv(color,0);
4972               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4973               continue;
4974             }
4975           if (LocaleCompare(attribute,"matte") == 0)
4976             {
4977               if (image != (Image *) NULL)
4978                 s=newSViv((ssize_t) image->matte);
4979               PUSHs(s ? sv_2mortal(s) : &sv_undef);
4980               continue;
4981             }
4982           if (LocaleCompare(attribute,"mime") == 0)
4983             {
4984               const char
4985                 *magick;
4986
4987               magick=NULL;
4988               if (info && *info->image_info->magick)
4989                 magick=info->image_info->magick;
4990               if (image != (Image *) NULL)
4991                 magick=image->magick;
4992               if (magick)
4993                 {
4994                   char
4995                     *mime;
4996
4997                   mime=MagickToMime(magick);
4998                   s=newSVpv(mime,0);
4999                   mime=(char *) RelinquishMagickMemory(mime);
5000                 }
5001               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5002               continue;
5003             }
5004           if (LocaleCompare(attribute,"monochrome") == 0)
5005             {
5006               if (image == (Image *) NULL)
5007                 continue;
5008               j=info ? info->image_info->monochrome :
5009                 IsImageMonochrome(image,&image->exception);
5010               s=newSViv(j);
5011               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5012               continue;
5013             }
5014           if (LocaleCompare(attribute,"montage") == 0)
5015             {
5016               if (image && image->montage)
5017                 s=newSVpv(image->montage,0);
5018               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5019               continue;
5020             }
5021           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5022             attribute);
5023           break;
5024         }
5025         case 'O':
5026         case 'o':
5027         {
5028           if (LocaleCompare(attribute,"orientation") == 0)
5029             {
5030               j=info ? info->image_info->orientation : image ?
5031                 image->orientation : UndefinedOrientation;
5032               s=newSViv(j);
5033               (void) sv_setpv(s,CommandOptionToMnemonic(MagickOrientationOptions,
5034                 j));
5035               SvIOK_on(s);
5036               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5037               continue;
5038             }
5039           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5040             attribute);
5041           break;
5042         }
5043         case 'P':
5044         case 'p':
5045         {
5046           if (LocaleCompare(attribute,"page") == 0)
5047             {
5048               if (info && info->image_info->page)
5049                 s=newSVpv(info->image_info->page,0);
5050               if (image != (Image *) NULL)
5051                 {
5052                   char
5053                     geometry[MaxTextExtent];
5054
5055                   (void) FormatLocaleString(geometry,MaxTextExtent,
5056                     "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
5057                     (double) image->page.height,(double) image->page.x,(double)
5058                     image->page.y);
5059                   s=newSVpv(geometry,0);
5060                 }
5061               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5062               continue;
5063             }
5064           if (LocaleCompare(attribute,"page.x") == 0)
5065             {
5066               if (image != (Image *) NULL)
5067                 s=newSViv((ssize_t) image->page.x);
5068               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5069               continue;
5070             }
5071           if (LocaleCompare(attribute,"page.y") == 0)
5072             {
5073               if (image != (Image *) NULL)
5074                 s=newSViv((ssize_t) image->page.y);
5075               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5076               continue;
5077             }
5078           if (LocaleNCompare(attribute,"pixel",5) == 0)
5079             {
5080               char
5081                 tuple[MaxTextExtent];
5082
5083               int
5084                 items;
5085
5086               long
5087                 x,
5088                 y;
5089
5090               register const Quantum
5091                 *p;
5092
5093               if (image == (Image *) NULL)
5094                 break;
5095               x=0;
5096               y=0;
5097               items=sscanf(attribute,"%*[^[][%ld%*[,/]%ld",&x,&y);
5098               (void) items;
5099               p=GetVirtualPixels(image,x,y,1,1,exception);
5100               if (image->colorspace != CMYKColorspace)
5101                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5102                   QuantumFormat "," QuantumFormat "," QuantumFormat,
5103                   GetPixelRed(image,p),GetPixelGreen(image,p),
5104                   GetPixelBlue(image,p),GetPixelAlpha(image,p));
5105               else
5106                 (void) FormatLocaleString(tuple,MaxTextExtent,QuantumFormat ","
5107                   QuantumFormat "," QuantumFormat "," QuantumFormat ","
5108                   QuantumFormat,GetPixelRed(image,p),GetPixelGreen(image,p),
5109                   GetPixelBlue(image,p),GetPixelBlack(image,p),
5110                   GetPixelAlpha(image,p));
5111               s=newSVpv(tuple,0);
5112               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5113               continue;
5114             }
5115           if (LocaleCompare(attribute,"pointsize") == 0)
5116             {
5117               if (info)
5118                 s=newSViv((ssize_t) info->image_info->pointsize);
5119               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5120               continue;
5121             }
5122           if (LocaleCompare(attribute,"preview") == 0)
5123             {
5124               s=newSViv(info->image_info->preview_type);
5125               (void) sv_setpv(s,CommandOptionToMnemonic(MagickPreviewOptions,
5126                 info->image_info->preview_type));
5127               SvIOK_on(s);
5128               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5129               continue;
5130             }
5131           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5132             attribute);
5133           break;
5134         }
5135         case 'Q':
5136         case 'q':
5137         {
5138           if (LocaleCompare(attribute,"quality") == 0)
5139             {
5140               if (info)
5141                 s=newSViv((ssize_t) info->image_info->quality);
5142               if (image != (Image *) NULL)
5143                 s=newSViv((ssize_t) image->quality);
5144               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5145               continue;
5146             }
5147           if (LocaleCompare(attribute,"quantum") == 0)
5148             {
5149               if (info)
5150                 s=newSViv((ssize_t) MAGICKCORE_QUANTUM_DEPTH);
5151               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5152               continue;
5153             }
5154           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5155             attribute);
5156           break;
5157         }
5158         case 'R':
5159         case 'r':
5160         {
5161           if (LocaleCompare(attribute,"rendering-intent") == 0)
5162             {
5163               s=newSViv(image->rendering_intent);
5164               (void) sv_setpv(s,CommandOptionToMnemonic(MagickIntentOptions,
5165                 image->rendering_intent));
5166               SvIOK_on(s);
5167               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5168               continue;
5169             }
5170           if (LocaleCompare(attribute,"red-primary") == 0)
5171             {
5172               if (image == (Image *) NULL)
5173                 break;
5174               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5175                 image->chromaticity.red_primary.x,
5176                 image->chromaticity.red_primary.y);
5177               s=newSVpv(color,0);
5178               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5179               continue;
5180             }
5181           if (LocaleCompare(attribute,"rows") == 0)
5182             {
5183               if (image != (Image *) NULL)
5184                 s=newSViv((ssize_t) image->rows);
5185               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5186               continue;
5187             }
5188           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5189             attribute);
5190           break;
5191         }
5192         case 'S':
5193         case 's':
5194         {
5195           if (LocaleCompare(attribute,"sampling-factor") == 0)
5196             {
5197               if (info && info->image_info->sampling_factor)
5198                 s=newSVpv(info->image_info->sampling_factor,0);
5199               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5200               continue;
5201             }
5202           if (LocaleCompare(attribute,"server") == 0)  /* same as display */
5203             {
5204               if (info && info->image_info->server_name)
5205                 s=newSVpv(info->image_info->server_name,0);
5206               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5207               continue;
5208             }
5209           if (LocaleCompare(attribute,"size") == 0)
5210             {
5211               if (info && info->image_info->size)
5212                 s=newSVpv(info->image_info->size,0);
5213               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5214               continue;
5215             }
5216           if (LocaleCompare(attribute,"scene") == 0)
5217             {
5218               if (image != (Image *) NULL)
5219                 s=newSViv((ssize_t) image->scene);
5220               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5221               continue;
5222             }
5223           if (LocaleCompare(attribute,"scenes") == 0)
5224             {
5225               if (image != (Image *) NULL)
5226                 s=newSViv((ssize_t) info->image_info->number_scenes);
5227               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5228               continue;
5229             }
5230           if (LocaleCompare(attribute,"signature") == 0)
5231             {
5232               const char
5233                 *value;
5234
5235               if (image == (Image *) NULL)
5236                 break;
5237               (void) SignatureImage(image);
5238               value=GetImageProperty(image,"Signature");
5239               if (value != (const char *) NULL)
5240                 s=newSVpv(value,0);
5241               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5242               continue;
5243             }
5244           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5245             attribute);
5246           break;
5247         }
5248         case 'T':
5249         case 't':
5250         {
5251           if (LocaleCompare(attribute,"taint") == 0)
5252             {
5253               if (image != (Image *) NULL)
5254                 s=newSViv((ssize_t) IsTaintImage(image));
5255               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5256               continue;
5257             }
5258           if (LocaleCompare(attribute,"texture") == 0)
5259             {
5260               if (info && info->image_info->texture)
5261                 s=newSVpv(info->image_info->texture,0);
5262               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5263               continue;
5264             }
5265           if (LocaleCompare(attribute,"total-ink-density") == 0)
5266             {
5267               s=newSViv(MAGICKCORE_QUANTUM_DEPTH);
5268               if (image != (Image *) NULL)
5269                 s=newSVnv(GetImageTotalInkDensity(image));
5270               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5271               continue;
5272             }
5273           if (LocaleCompare(attribute,"transparent-color") == 0)
5274             {
5275               if (image == (Image *) NULL)
5276                 break;
5277               (void) FormatLocaleString(color,MaxTextExtent,QuantumFormat ","
5278                 QuantumFormat "," QuantumFormat "," QuantumFormat,
5279                 image->transparent_color.red,image->transparent_color.green,
5280                 image->transparent_color.blue,image->transparent_color.alpha);
5281               s=newSVpv(color,0);
5282               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5283               continue;
5284             }
5285           if (LocaleCompare(attribute,"type") == 0)
5286             {
5287               if (image == (Image *) NULL)
5288                 break;
5289               j=(ssize_t) GetImageType(image,&image->exception);
5290               s=newSViv(j);
5291               (void) sv_setpv(s,CommandOptionToMnemonic(MagickTypeOptions,j));
5292               SvIOK_on(s);
5293               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5294               continue;
5295             }
5296           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5297             attribute);
5298           break;
5299         }
5300         case 'U':
5301         case 'u':
5302         {
5303           if (LocaleCompare(attribute,"units") == 0)
5304             {
5305               j=info ? info->image_info->units : image ? image->units :
5306                 UndefinedResolution;
5307               if (info && (info->image_info->units == UndefinedResolution))
5308                 if (image)
5309                   j=image->units;
5310               if (j == UndefinedResolution)
5311                 s=newSVpv("undefined units",0);
5312               else
5313                 if (j == PixelsPerInchResolution)
5314                   s=newSVpv("pixels / inch",0);
5315                 else
5316                   s=newSVpv("pixels / centimeter",0);
5317               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5318               continue;
5319             }
5320           if (LocaleCompare(attribute,"user-time") == 0)
5321             {
5322               if (image != (Image *) NULL)
5323                 s=newSVnv(GetUserTime(&image->timer));
5324               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5325               continue;
5326             }
5327           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5328             attribute);
5329           break;
5330         }
5331         case 'V':
5332         case 'v':
5333         {
5334           if (LocaleCompare(attribute,"verbose") == 0)
5335             {
5336               if (info)
5337                 s=newSViv((ssize_t) info->image_info->verbose);
5338               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5339               continue;
5340             }
5341           if (LocaleCompare(attribute,"version") == 0)
5342             {
5343               s=newSVpv(GetMagickVersion((size_t *) NULL),0);
5344               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5345               continue;
5346             }
5347           if (LocaleCompare(attribute,"view") == 0)
5348             {
5349               if (info && info->image_info->view)
5350                 s=newSVpv(info->image_info->view,0);
5351               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5352               continue;
5353             }
5354           if (LocaleCompare(attribute,"virtual-pixel") == 0)
5355             {
5356               if (image == (Image *) NULL)
5357                 break;
5358               j=(ssize_t) GetImageVirtualPixelMethod(image);
5359               s=newSViv(j);
5360               (void) sv_setpv(s,CommandOptionToMnemonic(
5361                 MagickVirtualPixelOptions,j));
5362               SvIOK_on(s);
5363               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5364               continue;
5365             }
5366           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5367             attribute);
5368           break;
5369         }
5370         case 'W':
5371         case 'w':
5372         {
5373           if (LocaleCompare(attribute,"white-point") == 0)
5374             {
5375               if (image == (Image *) NULL)
5376                 break;
5377               (void) FormatLocaleString(color,MaxTextExtent,"%.15g,%.15g",
5378                 image->chromaticity.white_point.x,
5379                 image->chromaticity.white_point.y);
5380               s=newSVpv(color,0);
5381               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5382               continue;
5383             }
5384           if (LocaleCompare(attribute,"width") == 0)
5385             {
5386               if (image != (Image *) NULL)
5387                 s=newSViv((ssize_t) image->columns);
5388               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5389               continue;
5390             }
5391           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5392              attribute);
5393           break;
5394         }
5395         case 'X':
5396         case 'x':
5397         {
5398           if (LocaleCompare(attribute,"x-resolution") == 0)
5399             {
5400               if (image != (Image *) NULL)
5401                 s=newSVnv(image->x_resolution);
5402               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5403               continue;
5404             }
5405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5406             attribute);
5407           break;
5408         }
5409         case 'Y':
5410         case 'y':
5411         {
5412           if (LocaleCompare(attribute,"y-resolution") == 0)
5413             {
5414               if (image != (Image *) NULL)
5415                 s=newSVnv(image->y_resolution);
5416               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5417               continue;
5418             }
5419           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5420             attribute);
5421           break;
5422         }
5423         default:
5424           break;
5425       }
5426       if (image == (Image *) NULL)
5427         ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5428           attribute)
5429       else
5430         {
5431           value=GetImageProperty(image,attribute);
5432           if (value != (const char *) NULL)
5433             {
5434               s=newSVpv(value,0);
5435               PUSHs(s ? sv_2mortal(s) : &sv_undef);
5436             }
5437           else
5438             if (*attribute != '%')
5439               ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5440                 attribute)
5441             else
5442               {
5443                  char
5444                    *meta;
5445
5446                  meta=InterpretImageProperties(info ? info->image_info :
5447                    (ImageInfo *) NULL,image,attribute);
5448                  s=newSVpv(meta,0);
5449                  PUSHs(s ? sv_2mortal(s) : &sv_undef);
5450                  meta=(char *) RelinquishMagickMemory(meta);
5451               }
5452         }
5453     }
5454     exception=DestroyExceptionInfo(exception);
5455     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
5456   }
5457 \f
5458 #
5459 ###############################################################################
5460 #                                                                             #
5461 #                                                                             #
5462 #                                                                             #
5463 #   G e t A u t h e n t i c P i x e l s                                       #
5464 #                                                                             #
5465 #                                                                             #
5466 #                                                                             #
5467 ###############################################################################
5468 #
5469 #
5470 void *
5471 GetAuthenticPixels(ref,...)
5472   Image::Magick ref = NO_INIT
5473   ALIAS:
5474     getauthenticpixels = 1
5475     GetImagePixels = 2
5476     getimagepixels = 3
5477   CODE:
5478   {
5479     char
5480       *attribute;
5481
5482     ExceptionInfo
5483       *exception;
5484
5485     Image
5486       *image;
5487
5488     RectangleInfo
5489       region;
5490
5491     ssize_t
5492       i;
5493
5494     struct PackageInfo
5495       *info;
5496
5497     SV
5498       *perl_exception,
5499       *reference;
5500
5501     void
5502       *blob = NULL;
5503
5504     PERL_UNUSED_VAR(ref);
5505     PERL_UNUSED_VAR(ix);
5506     exception=AcquireExceptionInfo();
5507     perl_exception=newSVpv("",0);
5508     if (sv_isobject(ST(0)) == 0)
5509       {
5510         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5511           PackageName);
5512         goto PerlException;
5513       }
5514     reference=SvRV(ST(0));
5515
5516     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5517     if (image == (Image *) NULL)
5518       {
5519         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5520           PackageName);
5521         goto PerlException;
5522       }
5523
5524     region.x=0;
5525     region.y=0;
5526     region.width=image->columns;
5527     region.height=1;
5528     if (items == 1)
5529       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5530     for (i=2; i < items; i+=2)
5531     {
5532       attribute=(char *) SvPV(ST(i-1),na);
5533       switch (*attribute)
5534       {
5535         case 'g':
5536         case 'G':
5537         {
5538           if (LocaleCompare(attribute,"geometry") == 0)
5539             {
5540               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5541               break;
5542             }
5543           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5544             attribute);
5545           break;
5546         }
5547         case 'H':
5548         case 'h':
5549         {
5550           if (LocaleCompare(attribute,"height") == 0)
5551             {
5552               region.height=SvIV(ST(i));
5553               continue;
5554             }
5555           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5556             attribute);
5557           break;
5558         }
5559         case 'X':
5560         case 'x':
5561         {
5562           if (LocaleCompare(attribute,"x") == 0)
5563             {
5564               region.x=SvIV(ST(i));
5565               continue;
5566             }
5567           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5568             attribute);
5569           break;
5570         }
5571         case 'Y':
5572         case 'y':
5573         {
5574           if (LocaleCompare(attribute,"y") == 0)
5575             {
5576               region.y=SvIV(ST(i));
5577               continue;
5578             }
5579           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5580             attribute);
5581           break;
5582         }
5583         case 'W':
5584         case 'w':
5585         {
5586           if (LocaleCompare(attribute,"width") == 0)
5587             {
5588               region.width=SvIV(ST(i));
5589               continue;
5590             }
5591           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5592             attribute);
5593           break;
5594         }
5595       }
5596     }
5597     blob=(void *) GetAuthenticPixels(image,region.x,region.y,region.width,
5598       region.height,exception);
5599     if (blob != (void *) NULL)
5600       goto PerlEnd;
5601
5602   PerlException:
5603     InheritPerlException(exception,perl_exception);
5604     exception=DestroyExceptionInfo(exception);
5605     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5606
5607   PerlEnd:
5608     RETVAL = blob;
5609   }
5610   OUTPUT:
5611     RETVAL
5612 \f
5613 #
5614 ###############################################################################
5615 #                                                                             #
5616 #                                                                             #
5617 #                                                                             #
5618 #   G e t V i r t u a l P i x e l s                                           #
5619 #                                                                             #
5620 #                                                                             #
5621 #                                                                             #
5622 ###############################################################################
5623 #
5624 #
5625 void *
5626 GetVirtualPixels(ref,...)
5627   Image::Magick ref = NO_INIT
5628   ALIAS:
5629     getvirtualpixels = 1
5630     AcquireImagePixels = 2
5631     acquireimagepixels = 3
5632   CODE:
5633   {
5634     char
5635       *attribute;
5636
5637     const void
5638       *blob = NULL;
5639
5640     ExceptionInfo
5641       *exception;
5642
5643     Image
5644       *image;
5645
5646     RectangleInfo
5647       region;
5648
5649     ssize_t
5650       i;
5651
5652     struct PackageInfo
5653       *info;
5654
5655     SV
5656       *perl_exception,
5657       *reference;
5658
5659     PERL_UNUSED_VAR(ref);
5660     PERL_UNUSED_VAR(ix);
5661     exception=AcquireExceptionInfo();
5662     perl_exception=newSVpv("",0);
5663     if (sv_isobject(ST(0)) == 0)
5664       {
5665         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5666           PackageName);
5667         goto PerlException;
5668       }
5669     reference=SvRV(ST(0));
5670
5671     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5672     if (image == (Image *) NULL)
5673       {
5674         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5675           PackageName);
5676         goto PerlException;
5677       }
5678
5679     region.x=0;
5680     region.y=0;
5681     region.width=image->columns;
5682     region.height=1;
5683     if (items == 1)
5684       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
5685     for (i=2; i < items; i+=2)
5686     {
5687       attribute=(char *) SvPV(ST(i-1),na);
5688       switch (*attribute)
5689       {
5690         case 'g':
5691         case 'G':
5692         {
5693           if (LocaleCompare(attribute,"geometry") == 0)
5694             {
5695               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
5696               break;
5697             }
5698           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
5699             attribute);
5700           break;
5701         }
5702         case 'H':
5703         case 'h':
5704         {
5705           if (LocaleCompare(attribute,"height") == 0)
5706             {
5707               region.height=SvIV(ST(i));
5708               continue;
5709             }
5710           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5711             attribute);
5712           break;
5713         }
5714         case 'X':
5715         case 'x':
5716         {
5717           if (LocaleCompare(attribute,"x") == 0)
5718             {
5719               region.x=SvIV(ST(i));
5720               continue;
5721             }
5722           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5723             attribute);
5724           break;
5725         }
5726         case 'Y':
5727         case 'y':
5728         {
5729           if (LocaleCompare(attribute,"y") == 0)
5730             {
5731               region.y=SvIV(ST(i));
5732               continue;
5733             }
5734           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5735             attribute);
5736           break;
5737         }
5738         case 'W':
5739         case 'w':
5740         {
5741           if (LocaleCompare(attribute,"width") == 0)
5742             {
5743               region.width=SvIV(ST(i));
5744               continue;
5745             }
5746           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
5747             attribute);
5748           break;
5749         }
5750       }
5751     }
5752     blob=(const void *) GetVirtualPixels(image,region.x,region.y,region.width,
5753       region.height,exception);
5754     if (blob != (void *) NULL)
5755       goto PerlEnd;
5756
5757   PerlException:
5758     InheritPerlException(exception,perl_exception);
5759     exception=DestroyExceptionInfo(exception);
5760     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5761
5762   PerlEnd:
5763     RETVAL = (void *) blob;
5764   }
5765   OUTPUT:
5766     RETVAL
5767 \f
5768 #
5769 ###############################################################################
5770 #                                                                             #
5771 #                                                                             #
5772 #                                                                             #
5773 #   G e t A u t h e n t i c M e t a c o n t e n t                             #
5774 #                                                                             #
5775 #                                                                             #
5776 #                                                                             #
5777 ###############################################################################
5778 #
5779 #
5780 void *
5781 GetAuthenticMetacontent(ref,...)
5782   Image::Magick ref = NO_INIT
5783   ALIAS:
5784     getauthenticmetacontent = 1
5785     GetMetacontent = 2
5786     getmetacontent = 3
5787   CODE:
5788   {
5789     ExceptionInfo
5790       *exception;
5791
5792     Image
5793       *image;
5794
5795     struct PackageInfo
5796       *info;
5797
5798     SV
5799       *perl_exception,
5800       *reference;
5801
5802     void
5803       *blob = NULL;
5804
5805     PERL_UNUSED_VAR(ref);
5806     PERL_UNUSED_VAR(ix);
5807     exception=AcquireExceptionInfo();
5808     perl_exception=newSVpv("",0);
5809     if (sv_isobject(ST(0)) == 0)
5810       {
5811         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5812           PackageName);
5813         goto PerlException;
5814       }
5815     reference=SvRV(ST(0));
5816
5817     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5818     if (image == (Image *) NULL)
5819       {
5820         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5821           PackageName);
5822         goto PerlException;
5823       }
5824
5825     blob=(void *) GetAuthenticMetacontent(image);
5826     if (blob != (void *) NULL)
5827       goto PerlEnd;
5828
5829   PerlException:
5830     InheritPerlException(exception,perl_exception);
5831     exception=DestroyExceptionInfo(exception);
5832     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5833
5834   PerlEnd:
5835     RETVAL = blob;
5836   }
5837   OUTPUT:
5838     RETVAL
5839 \f
5840 #
5841 ###############################################################################
5842 #                                                                             #
5843 #                                                                             #
5844 #                                                                             #
5845 #   G e t V i r t u a l M e t a c o n t e n t                                 #
5846 #                                                                             #
5847 #                                                                             #
5848 #                                                                             #
5849 ###############################################################################
5850 #
5851 #
5852 void *
5853 GetVirtualMetacontent(ref,...)
5854   Image::Magick ref = NO_INIT
5855   ALIAS:
5856     getvirtualmetacontent = 1
5857   CODE:
5858   {
5859     ExceptionInfo
5860       *exception;
5861
5862     Image
5863       *image;
5864
5865     struct PackageInfo
5866       *info;
5867
5868     SV
5869       *perl_exception,
5870       *reference;
5871
5872     void
5873       *blob = NULL;
5874
5875     PERL_UNUSED_VAR(ref);
5876     PERL_UNUSED_VAR(ix);
5877     exception=AcquireExceptionInfo();
5878     perl_exception=newSVpv("",0);
5879     if (sv_isobject(ST(0)) == 0)
5880       {
5881         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5882           PackageName);
5883         goto PerlException;
5884       }
5885     reference=SvRV(ST(0));
5886
5887     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5888     if (image == (Image *) NULL)
5889       {
5890         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5891           PackageName);
5892         goto PerlException;
5893       }
5894
5895     blob=(void *) GetVirtualMetacontent(image);
5896     if (blob != (void *) NULL)
5897       goto PerlEnd;
5898
5899   PerlException:
5900     InheritPerlException(exception,perl_exception);
5901     exception=DestroyExceptionInfo(exception);
5902     SvREFCNT_dec(perl_exception);  /* throw away all errors */
5903
5904   PerlEnd:
5905     RETVAL = blob;
5906   }
5907   OUTPUT:
5908     RETVAL
5909 \f
5910 #
5911 ###############################################################################
5912 #                                                                             #
5913 #                                                                             #
5914 #                                                                             #
5915 #   H i s t o g r a m                                                         #
5916 #                                                                             #
5917 #                                                                             #
5918 #                                                                             #
5919 ###############################################################################
5920 #
5921 #
5922 void
5923 Histogram(ref,...)
5924   Image::Magick ref=NO_INIT
5925   ALIAS:
5926     HistogramImage = 1
5927     histogram      = 2
5928     histogramimage = 3
5929   PPCODE:
5930   {
5931     AV
5932       *av;
5933
5934     char
5935       message[MaxTextExtent];
5936
5937     PixelPacket
5938       *histogram;
5939
5940     ExceptionInfo
5941       *exception;
5942
5943     Image
5944       *image;
5945
5946     register ssize_t
5947       i;
5948
5949     ssize_t
5950       count;
5951
5952     struct PackageInfo
5953       *info;
5954
5955     SV
5956       *perl_exception,
5957       *reference;
5958
5959     size_t
5960       number_colors;
5961
5962     PERL_UNUSED_VAR(ref);
5963     PERL_UNUSED_VAR(ix);
5964     exception=AcquireExceptionInfo();
5965     perl_exception=newSVpv("",0);
5966     av=NULL;
5967     if (sv_isobject(ST(0)) == 0)
5968       {
5969         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
5970           PackageName);
5971         goto PerlException;
5972       }
5973     reference=SvRV(ST(0));
5974     av=newAV();
5975     SvREFCNT_dec(av);
5976     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
5977     if (image == (Image *) NULL)
5978       {
5979         ThrowPerlException(exception,OptionError,"NoImagesDefined",
5980           PackageName);
5981         goto PerlException;
5982       }
5983     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
5984     count=0;
5985     for ( ; image; image=image->next)
5986     {
5987       histogram=GetImageHistogram(image,&number_colors,&image->exception);
5988       if (histogram == (PixelPacket *) NULL)
5989         continue;
5990       count+=(ssize_t) number_colors;
5991       EXTEND(sp,6*count);
5992       for (i=0; i < (ssize_t) number_colors; i++)
5993       {
5994         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5995           histogram[i].red);
5996         PUSHs(sv_2mortal(newSVpv(message,0)));
5997         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
5998           histogram[i].green);
5999         PUSHs(sv_2mortal(newSVpv(message,0)));
6000         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6001           histogram[i].blue);
6002         PUSHs(sv_2mortal(newSVpv(message,0)));
6003         if (image->colorspace == CMYKColorspace)
6004           {
6005             (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6006               histogram[i].black);
6007             PUSHs(sv_2mortal(newSVpv(message,0)));
6008           }
6009         (void) FormatLocaleString(message,MaxTextExtent,QuantumFormat,
6010           histogram[i].alpha);
6011         PUSHs(sv_2mortal(newSVpv(message,0)));
6012         (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
6013           histogram[i].count);
6014         PUSHs(sv_2mortal(newSVpv(message,0)));
6015       }
6016       histogram=(PixelPacket *) RelinquishMagickMemory(histogram);
6017     }
6018
6019   PerlException:
6020     InheritPerlException(exception,perl_exception);
6021     exception=DestroyExceptionInfo(exception);
6022     SvREFCNT_dec(perl_exception);
6023   }
6024 \f
6025 #
6026 ###############################################################################
6027 #                                                                             #
6028 #                                                                             #
6029 #                                                                             #
6030 #   G e t P i x e l                                                           #
6031 #                                                                             #
6032 #                                                                             #
6033 #                                                                             #
6034 ###############################################################################
6035 #
6036 #
6037 void
6038 GetPixel(ref,...)
6039   Image::Magick ref=NO_INIT
6040   ALIAS:
6041     getpixel = 1
6042     getPixel = 2
6043   PPCODE:
6044   {
6045     AV
6046       *av;
6047
6048     char
6049       *attribute;
6050
6051     ChannelType
6052       channel;
6053
6054     ExceptionInfo
6055       *exception;
6056
6057     Image
6058       *image;
6059
6060     MagickBooleanType
6061       normalize;
6062
6063     RectangleInfo
6064       region;
6065
6066     register const Quantum
6067       *p;
6068
6069     register ssize_t
6070       i;
6071
6072     ssize_t
6073       option;
6074
6075     struct PackageInfo
6076       *info;
6077
6078     SV
6079       *perl_exception,
6080       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6081
6082     PERL_UNUSED_VAR(ref);
6083     PERL_UNUSED_VAR(ix);
6084     exception=AcquireExceptionInfo();
6085     perl_exception=newSVpv("",0);
6086     reference=SvRV(ST(0));
6087     av=(AV *) reference;
6088     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6089       exception);
6090     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6091     if (image == (Image *) NULL)
6092       {
6093         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6094           PackageName);
6095         goto PerlException;
6096       }
6097     channel=DefaultChannels;
6098     normalize=MagickTrue;
6099     region.x=0;
6100     region.y=0;
6101     region.width=image->columns;
6102     region.height=1;
6103     if (items == 1)
6104       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6105     for (i=2; i < items; i+=2)
6106     {
6107       attribute=(char *) SvPV(ST(i-1),na);
6108       switch (*attribute)
6109       {
6110         case 'C':
6111         case 'c':
6112         {
6113           if (LocaleCompare(attribute,"channel") == 0)
6114             {
6115               ssize_t
6116                 option;
6117
6118               option=ParseChannelOption(SvPV(ST(i),na));
6119               if (option < 0)
6120                 {
6121                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6122                     SvPV(ST(i),na));
6123                   return;
6124                 }
6125                channel=(ChannelType) option;
6126               break;
6127             }
6128           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6129             attribute);
6130           break;
6131         }
6132         case 'g':
6133         case 'G':
6134         {
6135           if (LocaleCompare(attribute,"geometry") == 0)
6136             {
6137               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6138               break;
6139             }
6140           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6141             attribute);
6142           break;
6143         }
6144         case 'N':
6145         case 'n':
6146         {
6147           if (LocaleCompare(attribute,"normalize") == 0)
6148             {
6149               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6150                 SvPV(ST(i),na));
6151               if (option < 0)
6152                 {
6153                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6154                     SvPV(ST(i),na));
6155                   break;
6156                 }
6157              normalize=option != 0 ? MagickTrue : MagickFalse;
6158              break;
6159             }
6160           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6161             attribute);
6162           break;
6163         }
6164         case 'x':
6165         case 'X':
6166         {
6167           if (LocaleCompare(attribute,"x") == 0)
6168             {
6169               region.x=SvIV(ST(i));
6170               break;
6171             }
6172           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6173             attribute);
6174           break;
6175         }
6176         case 'y':
6177         case 'Y':
6178         {
6179           if (LocaleCompare(attribute,"y") == 0)
6180             {
6181               region.y=SvIV(ST(i));
6182               break;
6183             }
6184           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6185             attribute);
6186           break;
6187         }
6188         default:
6189         {
6190           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6191             attribute);
6192           break;
6193         }
6194       }
6195     }
6196     p=GetVirtualPixels(image,region.x,region.y,1,1,exception);
6197     if (p == (const Quantum *) NULL)
6198       PUSHs(&sv_undef);
6199     else
6200       {
6201         double
6202           scale;
6203
6204         scale=1.0;
6205         if (normalize != MagickFalse)
6206           scale=1.0/QuantumRange;
6207         if ((GetPixelRedTraits(image) & ActivePixelTrait) != 0)
6208           PUSHs(sv_2mortal(newSVnv(scale*GetPixelRed(image,p))));
6209         if ((GetPixelGreenTraits(image) & ActivePixelTrait) != 0)
6210           PUSHs(sv_2mortal(newSVnv(scale*GetPixelGreen(image,p))));
6211         if ((GetPixelBlueTraits(image) & ActivePixelTrait) != 0)
6212           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlue(image,p))));
6213         if (((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
6214             (image->colorspace == CMYKColorspace))
6215           PUSHs(sv_2mortal(newSVnv(scale*GetPixelBlack(image,p))));
6216         if ((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0)
6217           PUSHs(sv_2mortal(newSVnv(scale*GetPixelAlpha(image,p))));
6218       }
6219
6220   PerlException:
6221     InheritPerlException(exception,perl_exception);
6222     exception=DestroyExceptionInfo(exception);
6223     SvREFCNT_dec(perl_exception);
6224   }
6225 \f
6226 #
6227 ###############################################################################
6228 #                                                                             #
6229 #                                                                             #
6230 #                                                                             #
6231 #   G e t P i x e l s                                                         #
6232 #                                                                             #
6233 #                                                                             #
6234 #                                                                             #
6235 ###############################################################################
6236 #
6237 #
6238 void
6239 GetPixels(ref,...)
6240   Image::Magick ref=NO_INIT
6241   ALIAS:
6242     getpixels = 1
6243     getPixels = 2
6244   PPCODE:
6245   {
6246     AV
6247       *av;
6248
6249     char
6250       *attribute;
6251
6252     const char
6253       *map;
6254
6255     ExceptionInfo
6256       *exception;
6257
6258     Image
6259       *image;
6260
6261     MagickBooleanType
6262       normalize,
6263       status;
6264
6265     RectangleInfo
6266       region;
6267
6268     register ssize_t
6269       i;
6270
6271     ssize_t
6272       option;
6273
6274     struct PackageInfo
6275       *info;
6276
6277     SV
6278       *perl_exception,
6279       *reference;  /* reference is the SV* of ref=SvIV(reference) */
6280
6281     PERL_UNUSED_VAR(ref);
6282     PERL_UNUSED_VAR(ix);
6283     exception=AcquireExceptionInfo();
6284     perl_exception=newSVpv("",0);
6285     reference=SvRV(ST(0));
6286     av=(AV *) reference;
6287     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
6288       exception);
6289     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6290     if (image == (Image *) NULL)
6291       {
6292         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6293           PackageName);
6294         goto PerlException;
6295       }
6296     map="RGB";
6297     if (image->matte != MagickFalse)
6298       map="RGBA";
6299     if (image->colorspace == CMYKColorspace)
6300       {
6301         map="CMYK";
6302         if (image->matte != MagickFalse)
6303           map="CMYKA";
6304       }
6305     normalize=MagickFalse;
6306     region.x=0;
6307     region.y=0;
6308     region.width=image->columns;
6309     region.height=1;
6310     if (items == 1)
6311       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
6312     for (i=2; i < items; i+=2)
6313     {
6314       attribute=(char *) SvPV(ST(i-1),na);
6315       switch (*attribute)
6316       {
6317         case 'g':
6318         case 'G':
6319         {
6320           if (LocaleCompare(attribute,"geometry") == 0)
6321             {
6322               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
6323               break;
6324             }
6325           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6326             attribute);
6327           break;
6328         }
6329         case 'H':
6330         case 'h':
6331         {
6332           if (LocaleCompare(attribute,"height") == 0)
6333             {
6334               region.height=SvIV(ST(i));
6335               break;
6336             }
6337           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6338             attribute);
6339           break;
6340         }
6341         case 'M':
6342         case 'm':
6343         {
6344           if (LocaleCompare(attribute,"map") == 0)
6345             {
6346               map=SvPV(ST(i),na);
6347               break;
6348             }
6349           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6350             attribute);
6351           break;
6352         }
6353         case 'N':
6354         case 'n':
6355         {
6356           if (LocaleCompare(attribute,"normalize") == 0)
6357             {
6358               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
6359                 SvPV(ST(i),na));
6360               if (option < 0)
6361                 {
6362                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6363                     SvPV(ST(i),na));
6364                   break;
6365                 }
6366              normalize=option != 0 ? MagickTrue : MagickFalse;
6367              break;
6368             }
6369           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6370             attribute);
6371           break;
6372         }
6373         case 'W':
6374         case 'w':
6375         {
6376           if (LocaleCompare(attribute,"width") == 0)
6377             {
6378               region.width=SvIV(ST(i));
6379               break;
6380             }
6381           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6382             attribute);
6383           break;
6384         }
6385         case 'x':
6386         case 'X':
6387         {
6388           if (LocaleCompare(attribute,"x") == 0)
6389             {
6390               region.x=SvIV(ST(i));
6391               break;
6392             }
6393           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6394             attribute);
6395           break;
6396         }
6397         case 'y':
6398         case 'Y':
6399         {
6400           if (LocaleCompare(attribute,"y") == 0)
6401             {
6402               region.y=SvIV(ST(i));
6403               break;
6404             }
6405           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6406             attribute);
6407           break;
6408         }
6409         default:
6410         {
6411           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6412             attribute);
6413           break;
6414         }
6415       }
6416     }
6417     if (normalize != MagickFalse)
6418       {
6419         float
6420           *pixels;
6421
6422         pixels=(float *) AcquireQuantumMemory(strlen(map)*region.width,
6423           region.height*sizeof(*pixels));
6424         if (pixels == (float *) NULL)
6425           {
6426             ThrowPerlException(exception,ResourceLimitError,
6427               "MemoryAllocationFailed",PackageName);
6428             goto PerlException;
6429           }
6430         status=ExportImagePixels(image,region.x,region.y,region.width,
6431           region.height,map,FloatPixel,pixels,exception);
6432         if (status == MagickFalse)
6433           PUSHs(&sv_undef);
6434         else
6435           {
6436             EXTEND(sp,strlen(map)*region.width*region.height);
6437             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6438               PUSHs(sv_2mortal(newSVnv(pixels[i])));
6439           }
6440         pixels=(float *) RelinquishMagickMemory(pixels);
6441       }
6442     else
6443       {
6444         Quantum
6445           *pixels;
6446
6447         pixels=(Quantum *) AcquireQuantumMemory(strlen(map)*region.width,
6448           region.height*sizeof(*pixels));
6449         if (pixels == (Quantum *) NULL)
6450           {
6451             ThrowPerlException(exception,ResourceLimitError,
6452               "MemoryAllocationFailed",PackageName);
6453             goto PerlException;
6454           }
6455         status=ExportImagePixels(image,region.x,region.y,region.width,
6456           region.height,map,QuantumPixel,pixels,exception);
6457         if (status == MagickFalse)
6458           PUSHs(&sv_undef);
6459         else
6460           {
6461             EXTEND(sp,strlen(map)*region.width*region.height);
6462             for (i=0; i < (ssize_t) (strlen(map)*region.width*region.height); i++)
6463               PUSHs(sv_2mortal(newSViv(pixels[i])));
6464           }
6465         pixels=(Quantum *) RelinquishMagickMemory(pixels);
6466       }
6467
6468   PerlException:
6469     InheritPerlException(exception,perl_exception);
6470     exception=DestroyExceptionInfo(exception);
6471     SvREFCNT_dec(perl_exception);
6472   }
6473 \f
6474 #
6475 ###############################################################################
6476 #                                                                             #
6477 #                                                                             #
6478 #                                                                             #
6479 #   I m a g e T o B l o b                                                     #
6480 #                                                                             #
6481 #                                                                             #
6482 #                                                                             #
6483 ###############################################################################
6484 #
6485 #
6486 void
6487 ImageToBlob(ref,...)
6488   Image::Magick ref=NO_INIT
6489   ALIAS:
6490     ImageToBlob  = 1
6491     imagetoblob  = 2
6492     toblob       = 3
6493     blob         = 4
6494   PPCODE:
6495   {
6496     char
6497       filename[MaxTextExtent];
6498
6499     ExceptionInfo
6500       *exception;
6501
6502     Image
6503       *image,
6504       *next;
6505
6506     register ssize_t
6507       i;
6508
6509     struct PackageInfo
6510       *info,
6511       *package_info;
6512
6513     size_t
6514       length;
6515
6516     ssize_t
6517       scene;
6518
6519     SV
6520       *perl_exception,
6521       *reference;
6522
6523     void
6524       *blob;
6525
6526     PERL_UNUSED_VAR(ref);
6527     PERL_UNUSED_VAR(ix);
6528     exception=AcquireExceptionInfo();
6529     perl_exception=newSVpv("",0);
6530     package_info=(struct PackageInfo *) NULL;
6531     if (sv_isobject(ST(0)) == 0)
6532       {
6533         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6534           PackageName);
6535         goto PerlException;
6536       }
6537     reference=SvRV(ST(0));
6538     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6539     if (image == (Image *) NULL)
6540       {
6541         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6542           PackageName);
6543         goto PerlException;
6544       }
6545     package_info=ClonePackageInfo(info,exception);
6546     for (i=2; i < items; i+=2)
6547       SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),exception);
6548     (void) CopyMagickString(filename,package_info->image_info->filename,
6549       MaxTextExtent);
6550     scene=0;
6551     for (next=image; next; next=next->next)
6552     {
6553       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
6554       next->scene=scene++;
6555     }
6556     SetImageInfo(package_info->image_info,(unsigned int)
6557       GetImageListLength(image),&image->exception);
6558     EXTEND(sp,(ssize_t) GetImageListLength(image));
6559     for ( ; image; image=image->next)
6560     {
6561       length=0;
6562       blob=ImagesToBlob(package_info->image_info,image,&length,exception);
6563       if (blob != (char *) NULL)
6564         {
6565           PUSHs(sv_2mortal(newSVpv((const char *) blob,length)));
6566           blob=(unsigned char *) RelinquishMagickMemory(blob);
6567         }
6568       if (package_info->image_info->adjoin)
6569         break;
6570     }
6571
6572   PerlException:
6573     if (package_info != (struct PackageInfo *) NULL)
6574       DestroyPackageInfo(package_info);
6575     InheritPerlException(exception,perl_exception);
6576     exception=DestroyExceptionInfo(exception);
6577     SvREFCNT_dec(perl_exception);  /* throw away all errors */
6578   }
6579 \f
6580 #
6581 ###############################################################################
6582 #                                                                             #
6583 #                                                                             #
6584 #                                                                             #
6585 #   L a y e r s                                                               #
6586 #                                                                             #
6587 #                                                                             #
6588 #                                                                             #
6589 ###############################################################################
6590 #
6591 #
6592 void
6593 Layers(ref,...)
6594   Image::Magick ref=NO_INIT
6595   ALIAS:
6596     Layers                = 1
6597     layers           = 2
6598     OptimizeImageLayers   = 3
6599     optimizelayers        = 4
6600     optimizeimagelayers   = 5
6601   PPCODE:
6602   {
6603     AV
6604       *av;
6605
6606     char
6607       *attribute;
6608
6609     CompositeOperator
6610       compose;
6611
6612     ExceptionInfo
6613       *exception;
6614
6615     HV
6616       *hv;
6617
6618     Image
6619       *image,
6620       *layers;
6621
6622     ImageLayerMethod
6623       method;
6624
6625     register ssize_t
6626       i;
6627
6628     ssize_t
6629       option,
6630       sp;
6631
6632     struct PackageInfo
6633       *info;
6634
6635     SV
6636       *av_reference,
6637       *perl_exception,
6638       *reference,
6639       *rv,
6640       *sv;
6641
6642     PERL_UNUSED_VAR(ref);
6643     PERL_UNUSED_VAR(ix);
6644     exception=AcquireExceptionInfo();
6645     perl_exception=newSVpv("",0);
6646     sv=NULL;
6647     if (sv_isobject(ST(0)) == 0)
6648       {
6649         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
6650           PackageName);
6651         goto PerlException;
6652       }
6653     reference=SvRV(ST(0));
6654     hv=SvSTASH(reference);
6655     av=newAV();
6656     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
6657     SvREFCNT_dec(av);
6658     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
6659     if (image == (Image *) NULL)
6660       {
6661         ThrowPerlException(exception,OptionError,"NoImagesDefined",
6662           PackageName);
6663         goto PerlException;
6664       }
6665     compose=image->compose;
6666     method=OptimizeLayer;
6667     for (i=2; i < items; i+=2)
6668     {
6669       attribute=(char *) SvPV(ST(i-1),na);
6670       switch (*attribute)
6671       {
6672         case 'C':
6673         case 'c':
6674         {
6675           if (LocaleCompare(attribute,"compose") == 0)
6676             {
6677               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
6678                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
6679               if (sp < 0)
6680                 {
6681                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6682                     SvPV(ST(i),na));
6683                   break;
6684                 }
6685               compose=(CompositeOperator) sp;
6686               break;
6687             }
6688           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6689             attribute);
6690           break;
6691         }
6692         case 'M':
6693         case 'm':
6694         {
6695           if (LocaleCompare(attribute,"method") == 0)
6696             {
6697               option=ParseCommandOption(MagickLayerOptions,MagickFalse,
6698                 SvPV(ST(i),na));
6699               if (option < 0)
6700                 {
6701                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
6702                     SvPV(ST(i),na));
6703                   break;
6704                 }
6705               method=(ImageLayerMethod) option;
6706               break;
6707             }
6708           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6709             attribute);
6710           break;
6711         }
6712         default:
6713         {
6714           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
6715             attribute);
6716           break;
6717         }
6718       }
6719     }
6720     layers=(Image *) NULL;
6721     switch (method)
6722     {
6723       case CompareAnyLayer:
6724       case CompareClearLayer:
6725       case CompareOverlayLayer:
6726       default:
6727       {
6728         layers=CompareImageLayers(image,method,exception);
6729         break;
6730       }
6731       case MergeLayer:
6732       case FlattenLayer:
6733       case MosaicLayer:
6734       {
6735         layers=MergeImageLayers(image,method,exception);
6736         break;
6737       }
6738       case DisposeLayer:
6739       {
6740         layers=DisposeImages(image,exception);
6741         break;
6742       }
6743       case OptimizeImageLayer:
6744       {
6745         layers=OptimizeImageLayers(image,exception);
6746         break;
6747       }
6748       case OptimizePlusLayer:
6749       {
6750         layers=OptimizePlusImageLayers(image,exception);
6751         break;
6752       }
6753       case OptimizeTransLayer:
6754       {
6755         OptimizeImageTransparency(image,exception);
6756         InheritException(&(image->exception),exception);
6757         break;
6758       }
6759       case RemoveDupsLayer:
6760       {
6761         RemoveDuplicateLayers(&image,exception);
6762         InheritException(&(image->exception),exception);
6763         break;
6764       }
6765       case RemoveZeroLayer:
6766       {
6767         RemoveZeroDelayLayers(&image,exception);
6768         InheritException(&(image->exception),exception);
6769         break;
6770       }
6771       case OptimizeLayer:
6772       {
6773         QuantizeInfo
6774           *quantize_info;
6775
6776         /*
6777           General Purpose, GIF Animation Optimizer.
6778         */
6779         layers=CoalesceImages(image,exception);
6780         if (layers == (Image *) NULL)
6781           break;
6782         InheritException(&(layers->exception),exception);
6783         image=layers;
6784         layers=OptimizeImageLayers(image,exception);
6785         if (layers == (Image *) NULL)
6786           break;
6787         InheritException(&(layers->exception),exception);
6788         image=DestroyImageList(image);
6789         image=layers;
6790         layers=(Image *) NULL;
6791         OptimizeImageTransparency(image,exception);
6792         InheritException(&(image->exception),exception);
6793         quantize_info=AcquireQuantizeInfo(info->image_info);
6794         (void) RemapImages(quantize_info,image,(Image *) NULL);
6795         quantize_info=DestroyQuantizeInfo(quantize_info);
6796         break;
6797       }
6798       case CompositeLayer:
6799       {
6800         Image
6801           *source;
6802
6803         RectangleInfo
6804           geometry;
6805
6806         /*
6807           Split image sequence at the first 'NULL:' image.
6808         */
6809         source=image;
6810         while (source != (Image *) NULL)
6811         {
6812           source=GetNextImageInList(source);
6813           if ((source != (Image *) NULL) &&
6814               (LocaleCompare(source->magick,"NULL") == 0))
6815             break;
6816         }
6817         if (source != (Image *) NULL)
6818           {
6819             if ((GetPreviousImageInList(source) == (Image *) NULL) ||
6820                 (GetNextImageInList(source) == (Image *) NULL))
6821               source=(Image *) NULL;
6822             else
6823               {
6824                 /*
6825                   Separate the two lists, junk the null: image.
6826                 */
6827                 source=SplitImageList(source->previous);
6828                 DeleteImageFromList(&source);
6829               }
6830           }
6831         if (source == (Image *) NULL)
6832           {
6833             (void) ThrowMagickException(exception,GetMagickModule(),
6834               OptionError,"MissingNullSeparator","layers Composite");
6835             break;
6836           }
6837         /*
6838           Adjust offset with gravity and virtual canvas.
6839         */
6840         SetGeometry(image,&geometry);
6841         (void) ParseAbsoluteGeometry(image->geometry,&geometry);
6842         geometry.width=source->page.width != 0 ? source->page.width :
6843           source->columns;
6844         geometry.height=source->page.height != 0 ? source->page.height :
6845           source->rows;
6846         GravityAdjustGeometry(image->page.width != 0 ? image->page.width :
6847           image->columns,image->page.height != 0 ? image->page.height :
6848           image->rows,image->gravity,&geometry);
6849         CompositeLayers(image,compose,source,geometry.x,geometry.y,exception);
6850         source=DestroyImageList(source);
6851         InheritException(&(image->exception),exception);
6852         break;
6853       }
6854     }
6855     if (layers != (Image *) NULL)
6856       {
6857         InheritException(&(layers->exception),exception);
6858         image=layers;
6859       }
6860     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
6861       goto PerlException;
6862     for ( ; image; image=image->next)
6863     {
6864       AddImageToRegistry(sv,image);
6865       rv=newRV(sv);
6866       av_push(av,sv_bless(rv,hv));
6867       SvREFCNT_dec(sv);
6868     }
6869     exception=DestroyExceptionInfo(exception);
6870     ST(0)=av_reference;
6871     SvREFCNT_dec(perl_exception);
6872     XSRETURN(1);
6873
6874   PerlException:
6875     InheritPerlException(exception,perl_exception);
6876     exception=DestroyExceptionInfo(exception);
6877     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
6878     SvPOK_on(perl_exception);
6879     ST(0)=sv_2mortal(perl_exception);
6880     XSRETURN(1);
6881   }
6882 \f
6883 #
6884 ###############################################################################
6885 #                                                                             #
6886 #                                                                             #
6887 #                                                                             #
6888 #   M a g i c k T o M i m e                                                   #
6889 #                                                                             #
6890 #                                                                             #
6891 #                                                                             #
6892 ###############################################################################
6893 #
6894 #
6895 SV *
6896 MagickToMime(ref,name)
6897   Image::Magick ref=NO_INIT
6898   char *name
6899   ALIAS:
6900     magicktomime = 1
6901   CODE:
6902   {
6903     char
6904       *mime;
6905
6906     PERL_UNUSED_VAR(ref);
6907     PERL_UNUSED_VAR(ix);
6908     mime=MagickToMime(name);
6909     RETVAL=newSVpv(mime,0);
6910     mime=(char *) RelinquishMagickMemory(mime);
6911   }
6912   OUTPUT:
6913     RETVAL
6914 \f
6915 #
6916 ###############################################################################
6917 #                                                                             #
6918 #                                                                             #
6919 #                                                                             #
6920 #   M o g r i f y                                                             #
6921 #                                                                             #
6922 #                                                                             #
6923 #                                                                             #
6924 ###############################################################################
6925 #
6926 #
6927 void
6928 Mogrify(ref,...)
6929   Image::Magick ref=NO_INIT
6930   ALIAS:
6931     Comment            =   1
6932     CommentImage       =   2
6933     Label              =   3
6934     LabelImage         =   4
6935     AddNoise           =   5
6936     AddNoiseImage      =   6
6937     Colorize           =   7
6938     ColorizeImage      =   8
6939     Border             =   9
6940     BorderImage        =  10
6941     Blur               =  11
6942     BlurImage          =  12
6943     Chop               =  13
6944     ChopImage          =  14
6945     Crop               =  15
6946     CropImage          =  16
6947     Despeckle          =  17
6948     DespeckleImage     =  18
6949     Edge               =  19
6950     EdgeImage          =  20
6951     Emboss             =  21
6952     EmbossImage        =  22
6953     Enhance            =  23
6954     EnhanceImage       =  24
6955     Flip               =  25
6956     FlipImage          =  26
6957     Flop               =  27
6958     FlopImage          =  28
6959     Frame              =  29
6960     FrameImage         =  30
6961     Implode            =  31
6962     ImplodeImage       =  32
6963     Magnify            =  33
6964     MagnifyImage       =  34
6965     MedianFilter       =  35
6966     MedianFilterImage  =  36
6967     Minify             =  37
6968     MinifyImage        =  38
6969     OilPaint           =  39
6970     OilPaintImage      =  40
6971     ReduceNoise        =  41
6972     ReduceNoiseImage   =  42
6973     Roll               =  43
6974     RollImage          =  44
6975     Rotate             =  45
6976     RotateImage        =  46
6977     Sample             =  47
6978     SampleImage        =  48
6979     Scale              =  49
6980     ScaleImage         =  50
6981     Shade              =  51
6982     ShadeImage         =  52
6983     Sharpen            =  53
6984     SharpenImage       =  54
6985     Shear              =  55
6986     ShearImage         =  56
6987     Spread             =  57
6988     SpreadImage        =  58
6989     Swirl              =  59
6990     SwirlImage         =  60
6991     Resize             =  61
6992     ResizeImage        =  62
6993     Zoom               =  63
6994     ZoomImage          =  64
6995     Annotate           =  65
6996     AnnotateImage      =  66
6997     ColorFloodfill     =  67
6998     ColorFloodfillImage=  68
6999     Composite          =  69
7000     CompositeImage     =  70
7001     Contrast           =  71
7002     ContrastImage      =  72
7003     CycleColormap      =  73
7004     CycleColormapImage =  74
7005     Draw               =  75
7006     DrawImage          =  76
7007     Equalize           =  77
7008     EqualizeImage      =  78
7009     Gamma              =  79
7010     GammaImage         =  80
7011     Map                =  81
7012     MapImage           =  82
7013     MatteFloodfill     =  83
7014     MatteFloodfillImage=  84
7015     Modulate           =  85
7016     ModulateImage      =  86
7017     Negate             =  87
7018     NegateImage        =  88
7019     Normalize          =  89
7020     NormalizeImage     =  90
7021     NumberColors       =  91
7022     NumberColorsImage  =  92
7023     Opaque             =  93
7024     OpaqueImage        =  94
7025     Quantize           =  95
7026     QuantizeImage      =  96
7027     Raise              =  97
7028     RaiseImage         =  98
7029     Segment            =  99
7030     SegmentImage       = 100
7031     Signature          = 101
7032     SignatureImage     = 102
7033     Solarize           = 103
7034     SolarizeImage      = 104
7035     Sync               = 105
7036     SyncImage          = 106
7037     Texture            = 107
7038     TextureImage       = 108
7039     Evaluate           = 109
7040     EvaluateImage      = 110
7041     Transparent        = 111
7042     TransparentImage   = 112
7043     Threshold          = 113
7044     ThresholdImage     = 114
7045     Charcoal           = 115
7046     CharcoalImage      = 116
7047     Trim               = 117
7048     TrimImage          = 118
7049     Wave               = 119
7050     WaveImage          = 120
7051     Separate           = 121
7052     SeparateImage      = 122
7053     Stereo             = 125
7054     StereoImage        = 126
7055     Stegano            = 127
7056     SteganoImage       = 128
7057     Deconstruct        = 129
7058     DeconstructImage   = 130
7059     GaussianBlur       = 131
7060     GaussianBlurImage  = 132
7061     Convolve           = 133
7062     ConvolveImage      = 134
7063     Profile            = 135
7064     ProfileImage       = 136
7065     UnsharpMask        = 137
7066     UnsharpMaskImage   = 138
7067     MotionBlur         = 139
7068     MotionBlurImage    = 140
7069     OrderedDither      = 141
7070     OrderedDitherImage = 142
7071     Shave              = 143
7072     ShaveImage         = 144
7073     Level              = 145
7074     LevelImage         = 146
7075     Clip               = 147
7076     ClipImage          = 148
7077     AffineTransform    = 149
7078     AffineTransformImage = 150
7079     Difference         = 151
7080     DifferenceImage    = 152
7081     AdaptiveThreshold  = 153
7082     AdaptiveThresholdImage = 154
7083     Resample           = 155
7084     ResampleImage      = 156
7085     Describe           = 157
7086     DescribeImage      = 158
7087     BlackThreshold     = 159
7088     BlackThresholdImage= 160
7089     WhiteThreshold     = 161
7090     WhiteThresholdImage= 162
7091     RadialBlur         = 163
7092     RadialBlurImage    = 164
7093     Thumbnail          = 165
7094     ThumbnailImage     = 166
7095     Strip              = 167
7096     StripImage         = 168
7097     Tint               = 169
7098     TintImage          = 170
7099     Channel            = 171
7100     ChannelImage       = 172
7101     Splice             = 173
7102     SpliceImage        = 174
7103     Posterize          = 175
7104     PosterizeImage     = 176
7105     Shadow             = 177
7106     ShadowImage        = 178
7107     Identify           = 179
7108     IdentifyImage      = 180
7109     SepiaTone          = 181
7110     SepiaToneImage     = 182
7111     SigmoidalContrast  = 183
7112     SigmoidalContrastImage = 184
7113     Extent             = 185
7114     ExtentImage        = 186
7115     Vignette           = 187
7116     VignetteImage      = 188
7117     ContrastStretch    = 189
7118     ContrastStretchImage = 190
7119     Sans0              = 191
7120     Sans0Image         = 192
7121     Sans1              = 193
7122     Sans1Image         = 194
7123     AdaptiveSharpen    = 195
7124     AdaptiveSharpenImage = 196
7125     Transpose          = 197
7126     TransposeImage     = 198
7127     Transverse         = 199
7128     TransverseImage    = 200
7129     AutoOrient         = 201
7130     AutoOrientImage    = 202
7131     AdaptiveBlur       = 203
7132     AdaptiveBlurImage  = 204
7133     Sketch             = 205
7134     SketchImage        = 206
7135     UniqueColors       = 207
7136     UniqueColorsImage  = 208
7137     AdaptiveResize     = 209
7138     AdaptiveResizeImage= 210
7139     ClipMask           = 211
7140     ClipMaskImage      = 212
7141     LinearStretch      = 213
7142     LinearStretchImage = 214
7143     RecolorImage       = 215
7144     Recolor            = 216
7145     Mask               = 217
7146     MaskImage          = 218
7147     Polaroid           = 219
7148     PolaroidImage      = 220
7149     FloodfillPaint     = 221
7150     FloodfillPaintImage= 222
7151     Distort            = 223
7152     DistortImage       = 224
7153     Clut               = 225
7154     ClutImage          = 226
7155     LiquidRescale      = 227
7156     LiquidRescaleImage = 228
7157     Encipher           = 229
7158     EncipherImage      = 230
7159     Decipher           = 231
7160     DecipherImage      = 232
7161     Deskew             = 233
7162     DeskewImage        = 234
7163     Remap              = 235
7164     RemapImage         = 236
7165     SparseColor        = 237
7166     SparseColorImage   = 238
7167     Function           = 239
7168     FunctionImage      = 240
7169     SelectiveBlur      = 241
7170     SelectiveBlurImage = 242
7171     HaldClut           = 243
7172     HaldClutImage      = 244
7173     BlueShift          = 245
7174     BlueShiftImage     = 246
7175     ForwardFourierTransform  = 247
7176     ForwardFourierTransformImage = 248
7177     InverseFourierTransform = 249
7178     InverseFourierTransformImage = 250
7179     ColorDecisionList  = 251
7180     ColorDecisionListImage = 252
7181     AutoGamma          = 253
7182     AutoGammaImage     = 254
7183     AutoLevel          = 255
7184     AutoLevelImage     = 256
7185     LevelColors        = 257
7186     LevelColorsImage   = 258
7187     Clamp              = 259
7188     ClampImage         = 260
7189     Filter             = 261
7190     FilterImage        = 262
7191     BrightnessContrast = 263
7192     BrightnessContrastImage = 264
7193     Morphology         = 265
7194     MorphologyImage    = 266
7195     ColorMatrix        = 267
7196     ColorMatrixImage   = 268
7197     Color              = 269
7198     ColorImage         = 270
7199     Mode               = 271
7200     ModeImage          = 272
7201     Statistic          = 273
7202     StatisticImage     = 274
7203     MogrifyRegion      = 666
7204   PPCODE:
7205   {
7206     AffineMatrix
7207       affine,
7208       current;
7209
7210     char
7211       attribute_flag[MaxArguments],
7212       message[MaxTextExtent];
7213
7214     ChannelType
7215       channel;
7216
7217     CompositeOperator
7218       compose;
7219
7220     const char
7221       *attribute,
7222       *value;
7223
7224     double
7225       angle;
7226
7227     ExceptionInfo
7228       *exception;
7229
7230     GeometryInfo
7231       geometry_info;
7232
7233     Image
7234       *image,
7235       *next,
7236       *region_image;
7237
7238     MagickBooleanType
7239       status;
7240
7241     MagickStatusType
7242       flags;
7243
7244     PixelPacket
7245       fill_color;
7246
7247     RectangleInfo
7248       geometry,
7249       region_info;
7250
7251     register ssize_t
7252       i;
7253
7254     ssize_t
7255       base,
7256       j,
7257       number_images;
7258
7259     struct Methods
7260       *rp;
7261
7262     struct PackageInfo
7263       *info;
7264
7265     SV
7266       *perl_exception,
7267       **pv,
7268       *reference,
7269       **reference_vector;
7270
7271     struct ArgumentList
7272       argument_list[MaxArguments];
7273
7274     PERL_UNUSED_VAR(ref);
7275     PERL_UNUSED_VAR(ix);
7276     exception=AcquireExceptionInfo();
7277     perl_exception=newSVpv("",0);
7278     reference_vector=NULL;
7279     region_image=NULL;
7280     number_images=0;
7281     base=2;
7282     if (sv_isobject(ST(0)) == 0)
7283       {
7284         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7285           PackageName);
7286         goto PerlException;
7287       }
7288     reference=SvRV(ST(0));
7289     region_info.width=0;
7290     region_info.height=0;
7291     region_info.x=0;
7292     region_info.y=0;
7293     region_image=(Image *) NULL;
7294     image=SetupList(aTHX_ reference,&info,&reference_vector,exception);
7295     if (ix && (ix != 666))
7296       {
7297         /*
7298           Called as Method(...)
7299         */
7300         ix=(ix+1)/2;
7301         rp=(&Methods[ix-1]);
7302         attribute=rp->name;
7303       }
7304     else
7305       {
7306         /*
7307           Called as Mogrify("Method",...)
7308         */
7309         attribute=(char *) SvPV(ST(1),na);
7310         if (ix)
7311           {
7312             flags=ParseGravityGeometry(image,attribute,&region_info,exception);
7313             attribute=(char *) SvPV(ST(2),na);
7314             base++;
7315           }
7316         for (rp=Methods; ; rp++)
7317         {
7318           if (rp >= EndOf(Methods))
7319             {
7320               ThrowPerlException(exception,OptionError,
7321                 "UnrecognizedPerlMagickMethod",attribute);
7322               goto PerlException;
7323             }
7324           if (strEQcase(attribute,rp->name))
7325             break;
7326         }
7327         ix=rp-Methods+1;
7328         base++;
7329       }
7330     if (image == (Image *) NULL)
7331       {
7332         ThrowPerlException(exception,OptionError,"NoImagesDefined",attribute);
7333         goto PerlException;
7334       }
7335     Zero(&argument_list,NumberOf(argument_list),struct ArgumentList);
7336     Zero(&attribute_flag,NumberOf(attribute_flag),char);
7337     for (i=base; (i < items) || ((i == items) && (base == items)); i+=2)
7338     {
7339       Arguments
7340         *pp,
7341         *qq;
7342
7343       ssize_t
7344         ssize_test;
7345
7346       struct ArgumentList
7347         *al;
7348
7349       SV
7350         *sv;
7351
7352       sv=NULL;
7353       ssize_test=0;
7354       pp=(Arguments *) NULL;
7355       qq=rp->arguments;
7356       if (i == items)
7357         {
7358           pp=rp->arguments,
7359           sv=ST(i-1);
7360         }
7361       else
7362         for (sv=ST(i), attribute=(char *) SvPV(ST(i-1),na); ; qq++)
7363         {
7364           if ((qq >= EndOf(rp->arguments)) || (qq->method == NULL))
7365             break;
7366           if (strEQcase(attribute,qq->method) > ssize_test)
7367             {
7368               pp=qq;
7369               ssize_test=strEQcase(attribute,qq->method);
7370             }
7371         }
7372       if (pp == (Arguments *) NULL)
7373         {
7374           ThrowPerlException(exception,OptionError,"UnrecognizedOption",
7375             attribute);
7376           goto continue_outer_loop;
7377         }
7378       al=(&argument_list[pp-rp->arguments]);
7379       switch (pp->type)
7380       {
7381         case ArrayReference:
7382         {
7383           if (SvTYPE(sv) != SVt_RV)
7384             {
7385               (void) FormatLocaleString(message,MaxTextExtent,
7386                 "invalid %.60s value",pp->method);
7387               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7388               goto continue_outer_loop;
7389             }
7390           al->array_reference=SvRV(sv);
7391           break;
7392         }
7393         case RealReference:
7394         {
7395           al->real_reference=SvNV(sv);
7396           break;
7397         }
7398         case FileReference:
7399         {
7400           al->file_reference=(FILE *) PerlIO_findFILE(IoIFP(sv_2io(sv)));
7401           break;
7402         }
7403         case ImageReference:
7404         {
7405           if (!sv_isobject(sv) ||
7406               !(al->image_reference=SetupList(aTHX_ SvRV(sv),
7407                 (struct PackageInfo **) NULL,(SV ***) NULL,exception)))
7408             {
7409               ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
7410                 PackageName);
7411               goto PerlException;
7412             }
7413           break;
7414         }
7415         case IntegerReference:
7416         {
7417           al->integer_reference=SvIV(sv);
7418           break;
7419         }
7420         case StringReference:
7421         {
7422           al->string_reference=(char *) SvPV(sv,al->length);
7423           if (sv_isobject(sv))
7424             al->image_reference=SetupList(aTHX_ SvRV(sv),
7425               (struct PackageInfo **) NULL,(SV ***) NULL,exception);
7426           break;
7427         }
7428         default:
7429         {
7430           /*
7431             Is a string; look up name.
7432           */
7433           if ((al->length > 1) && (*(char *) SvPV(sv,al->length) == '@'))
7434             {
7435               al->string_reference=(char *) SvPV(sv,al->length);
7436               al->integer_reference=(-1);
7437               break;
7438             }
7439           al->integer_reference=ParseCommandOption((CommandOption) pp->type,
7440             MagickFalse,SvPV(sv,na));
7441           if (pp->type == MagickChannelOptions)
7442             al->integer_reference=ParseChannelOption(SvPV(sv,na));
7443           if ((al->integer_reference < 0) && ((al->integer_reference=SvIV(sv)) <= 0))
7444             {
7445               (void) FormatLocaleString(message,MaxTextExtent,
7446                 "invalid %.60s value",pp->method);
7447               ThrowPerlException(exception,OptionError,message,SvPV(sv,na));
7448               goto continue_outer_loop;
7449             }
7450           break;
7451         }
7452       }
7453       attribute_flag[pp-rp->arguments]++;
7454       continue_outer_loop: ;
7455     }
7456     (void) ResetMagickMemory((char *) &fill_color,0,sizeof(fill_color));
7457     pv=reference_vector;
7458     SetGeometryInfo(&geometry_info);
7459     channel=DefaultChannels;
7460     for (next=image; next; next=next->next)
7461     {
7462       image=next;
7463       SetGeometry(image,&geometry);
7464       if ((region_info.width*region_info.height) != 0)
7465         {
7466           region_image=image;
7467           image=CropImage(image,&region_info,exception);
7468         }
7469       switch (ix)
7470       {
7471         default:
7472         {
7473           (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double) ix);
7474           ThrowPerlException(exception,OptionError,
7475             "UnrecognizedPerlMagickMethod",message);
7476           goto PerlException;
7477         }
7478         case 1:  /* Comment */
7479         {
7480           if (attribute_flag[0] == 0)
7481             argument_list[0].string_reference=(char *) NULL;
7482           (void) SetImageProperty(image,"comment",InterpretImageProperties(
7483             info ? info->image_info : (ImageInfo *) NULL,image,
7484             argument_list[0].string_reference));
7485           break;
7486         }
7487         case 2:  /* Label */
7488         {
7489           if (attribute_flag[0] == 0)
7490             argument_list[0].string_reference=(char *) NULL;
7491           (void) SetImageProperty(image,"label",InterpretImageProperties(
7492             info ? info->image_info : (ImageInfo *) NULL,image,
7493             argument_list[0].string_reference));
7494           break;
7495         }
7496         case 3:  /* AddNoise */
7497         {
7498           if (attribute_flag[0] == 0)
7499             argument_list[0].integer_reference=UniformNoise;
7500           if (attribute_flag[1] != 0)
7501             channel=(ChannelType) argument_list[1].integer_reference;
7502           image=AddNoiseImageChannel(image,channel,(NoiseType)
7503             argument_list[0].integer_reference,exception);
7504           break;
7505         }
7506         case 4:  /* Colorize */
7507         {
7508           PixelPacket
7509             target;
7510
7511           (void) GetOneVirtualPixel(image,0,0,&target,exception);
7512           if (attribute_flag[0] != 0)
7513             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
7514               exception);
7515           if (attribute_flag[1] == 0)
7516             argument_list[1].string_reference="100%";
7517           image=ColorizeImage(image,argument_list[1].string_reference,target,
7518             exception);
7519           break;
7520         }
7521         case 5:  /* Border */
7522         {
7523           geometry.width=0;
7524           geometry.height=0;
7525           if (attribute_flag[0] != 0)
7526             {
7527               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7528                 &geometry,exception);
7529               if ((flags & HeightValue) == 0)
7530                 geometry.height=geometry.width;
7531             }
7532           if (attribute_flag[1] != 0)
7533             geometry.width=argument_list[1].integer_reference;
7534           if (attribute_flag[2] != 0)
7535             geometry.height=argument_list[2].integer_reference;
7536           if (attribute_flag[3] != 0)
7537             QueryColorDatabase(argument_list[3].string_reference,
7538               &image->border_color,exception);
7539           if (attribute_flag[4] != 0)
7540             QueryColorDatabase(argument_list[4].string_reference,
7541               &image->border_color,exception);
7542           if (attribute_flag[5] != 0)
7543             QueryColorDatabase(argument_list[5].string_reference,
7544               &image->border_color,exception);
7545           if (attribute_flag[6] != 0)
7546             image->compose=(CompositeOperator) argument_list[6].integer_reference;
7547           image=BorderImage(image,&geometry,exception);
7548           break;
7549         }
7550         case 6:  /* Blur */
7551         {
7552           if (attribute_flag[0] != 0)
7553             {
7554               flags=ParseGeometry(argument_list[0].string_reference,
7555                 &geometry_info);
7556               if ((flags & SigmaValue) == 0)
7557                 geometry_info.sigma=1.0;
7558             }
7559           if (attribute_flag[1] != 0)
7560             geometry_info.rho=argument_list[1].real_reference;
7561           if (attribute_flag[2] != 0)
7562             geometry_info.sigma=argument_list[2].real_reference;
7563           if (attribute_flag[3] != 0)
7564             channel=(ChannelType) argument_list[3].integer_reference;
7565           image=BlurImageChannel(image,channel,geometry_info.rho,
7566             geometry_info.sigma,exception);
7567           break;
7568         }
7569         case 7:  /* Chop */
7570         {
7571           if (attribute_flag[0] != 0)
7572             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7573               &geometry,exception);
7574           if (attribute_flag[1] != 0)
7575             geometry.width=argument_list[1].integer_reference;
7576           if (attribute_flag[2] != 0)
7577             geometry.height=argument_list[2].integer_reference;
7578           if (attribute_flag[3] != 0)
7579             geometry.x=argument_list[3].integer_reference;
7580           if (attribute_flag[4] != 0)
7581             geometry.y=argument_list[4].integer_reference;
7582           image=ChopImage(image,&geometry,exception);
7583           break;
7584         }
7585         case 8:  /* Crop */
7586         {
7587           if (attribute_flag[6] != 0)
7588             image->gravity=(GravityType) argument_list[6].integer_reference;
7589           if (attribute_flag[0] != 0)
7590             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
7591               &geometry,exception);
7592           if (attribute_flag[1] != 0)
7593             geometry.width=argument_list[1].integer_reference;
7594           if (attribute_flag[2] != 0)
7595             geometry.height=argument_list[2].integer_reference;
7596           if (attribute_flag[3] != 0)
7597             geometry.x=argument_list[3].integer_reference;
7598           if (attribute_flag[4] != 0)
7599             geometry.y=argument_list[4].integer_reference;
7600           if (attribute_flag[5] != 0)
7601             image->fuzz=
7602               SiPrefixToDouble(argument_list[5].string_reference,QuantumRange);
7603           image=CropImage(image,&geometry,exception);
7604           break;
7605         }
7606         case 9:  /* Despeckle */
7607         {
7608           image=DespeckleImage(image,exception);
7609           break;
7610         }
7611         case 10:  /* Edge */
7612         {
7613           if (attribute_flag[0] != 0)
7614             geometry_info.rho=argument_list[0].real_reference;
7615           image=EdgeImage(image,geometry_info.rho,exception);
7616           break;
7617         }
7618         case 11:  /* Emboss */
7619         {
7620           if (attribute_flag[0] != 0)
7621             {
7622               flags=ParseGeometry(argument_list[0].string_reference,
7623                 &geometry_info);
7624               if ((flags & SigmaValue) == 0)
7625                 geometry_info.sigma=1.0;
7626             }
7627           if (attribute_flag[1] != 0)
7628             geometry_info.rho=argument_list[1].real_reference;
7629           if (attribute_flag[2] != 0)
7630             geometry_info.sigma=argument_list[2].real_reference;
7631           image=EmbossImage(image,geometry_info.rho,geometry_info.sigma,
7632             exception);
7633           break;
7634         }
7635         case 12:  /* Enhance */
7636         {
7637           image=EnhanceImage(image,exception);
7638           break;
7639         }
7640         case 13:  /* Flip */
7641         {
7642           image=FlipImage(image,exception);
7643           break;
7644         }
7645         case 14:  /* Flop */
7646         {
7647           image=FlopImage(image,exception);
7648           break;
7649         }
7650         case 15:  /* Frame */
7651         {
7652           FrameInfo
7653             frame_info;
7654
7655           if (attribute_flag[0] != 0)
7656             {
7657               flags=ParsePageGeometry(image,argument_list[0].string_reference,
7658                 &geometry,exception);
7659               if ((flags & HeightValue) == 0)
7660                 geometry.height=geometry.width;
7661               frame_info.width=geometry.width;
7662               frame_info.height=geometry.height;
7663               frame_info.outer_bevel=geometry.x;
7664               frame_info.inner_bevel=geometry.y;
7665             }
7666           if (attribute_flag[1] != 0)
7667             frame_info.width=argument_list[1].integer_reference;
7668           if (attribute_flag[2] != 0)
7669             frame_info.height=argument_list[2].integer_reference;
7670           if (attribute_flag[3] != 0)
7671             frame_info.inner_bevel=argument_list[3].integer_reference;
7672           if (attribute_flag[4] != 0)
7673             frame_info.outer_bevel=argument_list[4].integer_reference;
7674           if (attribute_flag[5] != 0)
7675             QueryColorDatabase(argument_list[5].string_reference,&fill_color,
7676               exception);
7677           if (attribute_flag[6] != 0)
7678             QueryColorDatabase(argument_list[6].string_reference,&fill_color,
7679               exception);
7680           frame_info.x=(ssize_t) frame_info.width;
7681           frame_info.y=(ssize_t) frame_info.height;
7682           frame_info.width=image->columns+2*frame_info.x;
7683           frame_info.height=image->rows+2*frame_info.y;
7684           if ((attribute_flag[5] != 0) || (attribute_flag[6] != 0))
7685             image->matte_color=fill_color;
7686           if (attribute_flag[7] != 0)
7687             image->compose=(CompositeOperator) argument_list[7].integer_reference;
7688           image=FrameImage(image,&frame_info,exception);
7689           break;
7690         }
7691         case 16:  /* Implode */
7692         {
7693           if (attribute_flag[0] == 0)
7694             argument_list[0].real_reference=0.5;
7695           if (attribute_flag[1] != 0)
7696             image->interpolate=(InterpolatePixelMethod)
7697               argument_list[1].integer_reference;
7698           image=ImplodeImage(image,argument_list[0].real_reference,
7699             exception);
7700           break;
7701         }
7702         case 17:  /* Magnify */
7703         {
7704           image=MagnifyImage(image,exception);
7705           break;
7706         }
7707         case 18:  /* MedianFilter */
7708         {
7709           if (attribute_flag[0] != 0)
7710             {
7711               flags=ParseGeometry(argument_list[0].string_reference,
7712                 &geometry_info);
7713               if ((flags & SigmaValue) == 0)
7714                 geometry_info.sigma=1.0;
7715             }
7716           if (attribute_flag[1] != 0)
7717             geometry_info.rho=argument_list[1].real_reference;
7718           if (attribute_flag[2] != 0)
7719             geometry_info.sigma=argument_list[2].real_reference;
7720           if (attribute_flag[3] != 0)
7721             channel=(ChannelType) argument_list[3].integer_reference;
7722           image=StatisticImageChannel(image,channel,MedianStatistic,
7723             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7724           break;
7725         }
7726         case 19:  /* Minify */
7727         {
7728           image=MinifyImage(image,exception);
7729           break;
7730         }
7731         case 20:  /* OilPaint */
7732         {
7733           if (attribute_flag[0] == 0)
7734             argument_list[0].real_reference=0.0;
7735           image=OilPaintImage(image,argument_list[0].real_reference,
7736             exception);
7737           break;
7738         }
7739         case 21:  /* ReduceNoise */
7740         {
7741           if (attribute_flag[0] != 0)
7742             {
7743               flags=ParseGeometry(argument_list[0].string_reference,
7744                 &geometry_info);
7745               if ((flags & SigmaValue) == 0)
7746                 geometry_info.sigma=1.0;
7747             }
7748           if (attribute_flag[1] != 0)
7749             geometry_info.rho=argument_list[1].real_reference;
7750           if (attribute_flag[2] != 0)
7751             geometry_info.sigma=argument_list[2].real_reference;
7752           if (attribute_flag[3] != 0)
7753             channel=(ChannelType) argument_list[3].integer_reference;
7754           image=StatisticImageChannel(image,channel,NonpeakStatistic,
7755             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
7756           break;
7757         }
7758         case 22:  /* Roll */
7759         {
7760           if (attribute_flag[0] != 0)
7761             flags=ParsePageGeometry(image,argument_list[0].string_reference,
7762               &geometry,exception);
7763           if (attribute_flag[1] != 0)
7764             geometry.x=argument_list[1].integer_reference;
7765           if (attribute_flag[2] != 0)
7766             geometry.y=argument_list[2].integer_reference;
7767           image=RollImage(image,geometry.x,geometry.y,exception);
7768           break;
7769         }
7770         case 23:  /* Rotate */
7771         {
7772           if (attribute_flag[0] == 0)
7773             argument_list[0].real_reference=90.0;
7774           if (attribute_flag[1] != 0)
7775             QueryColorDatabase(argument_list[1].string_reference,
7776               &image->background_color,exception);
7777           if (attribute_flag[2] != 0)
7778             QueryColorDatabase(argument_list[2].string_reference,
7779               &image->background_color,exception);
7780           if (attribute_flag[3] != 0)
7781             QueryColorDatabase(argument_list[3].string_reference,
7782               &image->background_color,exception);
7783           image=RotateImage(image,argument_list[0].real_reference,exception);
7784           break;
7785         }
7786         case 24:  /* Sample */
7787         {
7788           if (attribute_flag[0] != 0)
7789             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7790               &geometry,exception);
7791           if (attribute_flag[1] != 0)
7792             geometry.width=argument_list[1].integer_reference;
7793           if (attribute_flag[2] != 0)
7794             geometry.height=argument_list[2].integer_reference;
7795           image=SampleImage(image,geometry.width,geometry.height,exception);
7796           break;
7797         }
7798         case 25:  /* Scale */
7799         {
7800           if (attribute_flag[0] != 0)
7801             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7802               &geometry,exception);
7803           if (attribute_flag[1] != 0)
7804             geometry.width=argument_list[1].integer_reference;
7805           if (attribute_flag[2] != 0)
7806             geometry.height=argument_list[2].integer_reference;
7807           image=ScaleImage(image,geometry.width,geometry.height,exception);
7808           break;
7809         }
7810         case 26:  /* Shade */
7811         {
7812           if (attribute_flag[0] != 0)
7813             {
7814               flags=ParseGeometry(argument_list[0].string_reference,
7815                 &geometry_info);
7816               if ((flags & SigmaValue) == 0)
7817                 geometry_info.sigma=0.0;
7818             }
7819           if (attribute_flag[1] != 0)
7820             geometry_info.rho=argument_list[1].real_reference;
7821           if (attribute_flag[2] != 0)
7822             geometry_info.sigma=argument_list[2].real_reference;
7823           image=ShadeImage(image,
7824             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
7825             geometry_info.rho,geometry_info.sigma,exception);
7826           break;
7827         }
7828         case 27:  /* Sharpen */
7829         {
7830           if (attribute_flag[0] != 0)
7831             {
7832               flags=ParseGeometry(argument_list[0].string_reference,
7833                 &geometry_info);
7834               if ((flags & SigmaValue) == 0)
7835                 geometry_info.sigma=1.0;
7836             }
7837           if (attribute_flag[1] != 0)
7838             geometry_info.rho=argument_list[1].real_reference;
7839           if (attribute_flag[2] != 0)
7840             geometry_info.sigma=argument_list[2].real_reference;
7841           if (attribute_flag[3] != 0)
7842             channel=(ChannelType) argument_list[3].integer_reference;
7843           image=SharpenImageChannel(image,channel,geometry_info.rho,
7844             geometry_info.sigma,exception);
7845           break;
7846         }
7847         case 28:  /* Shear */
7848         {
7849           if (attribute_flag[0] != 0)
7850             {
7851               flags=ParseGeometry(argument_list[0].string_reference,
7852                 &geometry_info);
7853               if ((flags & SigmaValue) == 0)
7854                 geometry_info.sigma=geometry_info.rho;
7855             }
7856           if (attribute_flag[1] != 0)
7857             geometry_info.rho=argument_list[1].real_reference;
7858           if (attribute_flag[2] != 0)
7859             geometry_info.sigma=argument_list[2].real_reference;
7860           if (attribute_flag[3] != 0)
7861             QueryColorDatabase(argument_list[3].string_reference,
7862               &image->background_color,exception);
7863           if (attribute_flag[4] != 0)
7864             QueryColorDatabase(argument_list[4].string_reference,
7865               &image->background_color,exception);
7866           image=ShearImage(image,geometry_info.rho,geometry_info.sigma,
7867             exception);
7868           break;
7869         }
7870         case 29:  /* Spread */
7871         {
7872           if (attribute_flag[0] == 0)
7873             argument_list[0].real_reference=1.0;
7874           image=SpreadImage(image,argument_list[0].real_reference,exception);
7875           break;
7876         }
7877         case 30:  /* Swirl */
7878         {
7879           if (attribute_flag[0] == 0)
7880             argument_list[0].real_reference=50.0;
7881           if (attribute_flag[1] != 0)
7882             image->interpolate=(InterpolatePixelMethod)
7883               argument_list[1].integer_reference;
7884           image=SwirlImage(image,argument_list[0].real_reference,exception);
7885           break;
7886         }
7887         case 31:  /* Resize */
7888         case 32:  /* Zoom */
7889         {
7890           if (attribute_flag[0] != 0)
7891             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
7892               &geometry,exception);
7893           if (attribute_flag[1] != 0)
7894             geometry.width=argument_list[1].integer_reference;
7895           if (attribute_flag[2] != 0)
7896             geometry.height=argument_list[2].integer_reference;
7897           if (attribute_flag[3] == 0)
7898             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
7899           if (attribute_flag[4] != 0)
7900             SetImageArtifact(image,"filter:support",
7901               argument_list[4].string_reference);
7902           if (attribute_flag[5] == 0)
7903             argument_list[5].real_reference=1.0;
7904           image=ResizeImage(image,geometry.width,geometry.height,
7905             (FilterTypes) argument_list[3].integer_reference,
7906             argument_list[5].real_reference,exception);
7907           break;
7908         }
7909         case 33:  /* Annotate */
7910         {
7911           DrawInfo
7912             *draw_info;
7913
7914           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
7915             (DrawInfo *) NULL);
7916           if (attribute_flag[0] != 0)
7917             {
7918               char
7919                 *text;
7920
7921               text=InterpretImageProperties(info ? info->image_info :
7922                 (ImageInfo *) NULL,image,argument_list[0].string_reference);
7923               (void) CloneString(&draw_info->text,text);
7924               text=DestroyString(text);
7925             }
7926           if (attribute_flag[1] != 0)
7927             (void) CloneString(&draw_info->font,
7928               argument_list[1].string_reference);
7929           if (attribute_flag[2] != 0)
7930             draw_info->pointsize=argument_list[2].real_reference;
7931           if (attribute_flag[3] != 0)
7932             (void) CloneString(&draw_info->density,
7933               argument_list[3].string_reference);
7934           if (attribute_flag[4] != 0)
7935             (void) QueryColorDatabase(argument_list[4].string_reference,
7936               &draw_info->undercolor,exception);
7937           if (attribute_flag[5] != 0)
7938             {
7939               (void) QueryColorDatabase(argument_list[5].string_reference,
7940                 &draw_info->stroke,exception);
7941               if (argument_list[5].image_reference != (Image *) NULL)
7942                 draw_info->stroke_pattern=CloneImage(
7943                   argument_list[5].image_reference,0,0,MagickTrue,exception);
7944             }
7945           if (attribute_flag[6] != 0)
7946             {
7947               (void) QueryColorDatabase(argument_list[6].string_reference,
7948                 &draw_info->fill,exception);
7949               if (argument_list[6].image_reference != (Image *) NULL)
7950                 draw_info->fill_pattern=CloneImage(
7951                   argument_list[6].image_reference,0,0,MagickTrue,exception);
7952             }
7953           if (attribute_flag[7] != 0)
7954             {
7955               (void) CloneString(&draw_info->geometry,
7956                 argument_list[7].string_reference);
7957               flags=ParsePageGeometry(image,argument_list[7].string_reference,
7958                 &geometry,exception);
7959               if (((flags & SigmaValue) == 0) && ((flags & XiValue) != 0))
7960                 geometry_info.sigma=geometry_info.xi;
7961             }
7962           if (attribute_flag[8] != 0)
7963             (void) QueryColorDatabase(argument_list[8].string_reference,
7964               &draw_info->fill,exception);
7965           if (attribute_flag[11] != 0)
7966             draw_info->gravity=(GravityType) argument_list[11].integer_reference;
7967           if (attribute_flag[25] != 0)
7968             {
7969               AV
7970                 *av;
7971
7972               av=(AV *) argument_list[25].array_reference;
7973               if ((av_len(av) != 3) && (av_len(av) != 5))
7974                 {
7975                   ThrowPerlException(exception,OptionError,
7976                     "affine matrix must have 4 or 6 elements",PackageName);
7977                   goto PerlException;
7978                 }
7979               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
7980               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
7981               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
7982               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
7983               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
7984                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
7985                 {
7986                   ThrowPerlException(exception,OptionError,
7987                     "affine matrix is singular",PackageName);
7988                    goto PerlException;
7989                 }
7990               if (av_len(av) == 5)
7991                 {
7992                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
7993                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
7994                 }
7995             }
7996           for (j=12; j < 17; j++)
7997           {
7998             if (attribute_flag[j] == 0)
7999               continue;
8000             value=argument_list[j].string_reference;
8001             angle=argument_list[j].real_reference;
8002             current=draw_info->affine;
8003             GetAffineMatrix(&affine);
8004             switch (j)
8005             {
8006               case 12:
8007               {
8008                 /*
8009                   Translate.
8010                 */
8011                 flags=ParseGeometry(value,&geometry_info);
8012                 affine.tx=geometry_info.xi;
8013                 affine.ty=geometry_info.psi;
8014                 if ((flags & PsiValue) == 0)
8015                   affine.ty=affine.tx;
8016                 break;
8017               }
8018               case 13:
8019               {
8020                 /*
8021                   Scale.
8022                 */
8023                 flags=ParseGeometry(value,&geometry_info);
8024                 affine.sx=geometry_info.rho;
8025                 affine.sy=geometry_info.sigma;
8026                 if ((flags & SigmaValue) == 0)
8027                   affine.sy=affine.sx;
8028                 break;
8029               }
8030               case 14:
8031               {
8032                 /*
8033                   Rotate.
8034                 */
8035                 if (angle == 0.0)
8036                   break;
8037                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8038                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8039                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8040                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8041                 break;
8042               }
8043               case 15:
8044               {
8045                 /*
8046                   SkewX.
8047                 */
8048                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8049                 break;
8050               }
8051               case 16:
8052               {
8053                 /*
8054                   SkewY.
8055                 */
8056                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8057                 break;
8058               }
8059             }
8060             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8061             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8062             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8063             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8064             draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+
8065               current.tx;
8066             draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+
8067               current.ty;
8068           }
8069           if (attribute_flag[9] == 0)
8070             argument_list[9].real_reference=0.0;
8071           if (attribute_flag[10] == 0)
8072             argument_list[10].real_reference=0.0;
8073           if ((attribute_flag[9] != 0) || (attribute_flag[10] != 0))
8074             {
8075               char
8076                 geometry[MaxTextExtent];
8077
8078               (void) FormatLocaleString(geometry,MaxTextExtent,"%+f%+f",
8079                 (double) argument_list[9].real_reference+draw_info->affine.tx,
8080                 (double) argument_list[10].real_reference+draw_info->affine.ty);
8081               (void) CloneString(&draw_info->geometry,geometry);
8082             }
8083           if (attribute_flag[17] != 0)
8084             draw_info->stroke_width=argument_list[17].real_reference;
8085           if (attribute_flag[18] != 0)
8086             {
8087               draw_info->text_antialias=argument_list[18].integer_reference != 0 ?
8088                 MagickTrue : MagickFalse;
8089               draw_info->stroke_antialias=draw_info->text_antialias;
8090             }
8091           if (attribute_flag[19] != 0)
8092             (void) CloneString(&draw_info->family,
8093               argument_list[19].string_reference);
8094           if (attribute_flag[20] != 0)
8095             draw_info->style=(StyleType) argument_list[20].integer_reference;
8096           if (attribute_flag[21] != 0)
8097             draw_info->stretch=(StretchType) argument_list[21].integer_reference;
8098           if (attribute_flag[22] != 0)
8099             draw_info->weight=argument_list[22].integer_reference;
8100           if (attribute_flag[23] != 0)
8101             draw_info->align=(AlignType) argument_list[23].integer_reference;
8102           if (attribute_flag[24] != 0)
8103             (void) CloneString(&draw_info->encoding,
8104               argument_list[24].string_reference);
8105           if (attribute_flag[25] != 0)
8106             draw_info->fill_pattern=CloneImage(
8107               argument_list[25].image_reference,0,0,MagickTrue,exception);
8108           if (attribute_flag[26] != 0)
8109             draw_info->fill_pattern=CloneImage(
8110               argument_list[26].image_reference,0,0,MagickTrue,exception);
8111           if (attribute_flag[27] != 0)
8112             draw_info->stroke_pattern=CloneImage(
8113               argument_list[27].image_reference,0,0,MagickTrue,exception);
8114           if (attribute_flag[29] != 0)
8115             draw_info->kerning=argument_list[29].real_reference;
8116           if (attribute_flag[30] != 0)
8117             draw_info->interline_spacing=argument_list[30].real_reference;
8118           if (attribute_flag[31] != 0)
8119             draw_info->interword_spacing=argument_list[31].real_reference;
8120           if (attribute_flag[32] != 0)
8121             draw_info->direction=(DirectionType)
8122               argument_list[32].integer_reference;
8123           (void) AnnotateImage(image,draw_info);
8124           draw_info=DestroyDrawInfo(draw_info);
8125           break;
8126         }
8127         case 34:  /* ColorFloodfill */
8128         {
8129           DrawInfo
8130             *draw_info;
8131
8132           MagickBooleanType
8133             invert;
8134
8135           PixelInfo
8136             target;
8137
8138           draw_info=CloneDrawInfo(info ? info->image_info :
8139             (ImageInfo *) NULL,(DrawInfo *) NULL);
8140           if (attribute_flag[0] != 0)
8141             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8142               &geometry,exception);
8143           if (attribute_flag[1] != 0)
8144             geometry.x=argument_list[1].integer_reference;
8145           if (attribute_flag[2] != 0)
8146             geometry.y=argument_list[2].integer_reference;
8147           if (attribute_flag[3] != 0)
8148             (void) QueryColorDatabase(argument_list[3].string_reference,
8149               &draw_info->fill,exception);
8150           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8151             exception);
8152           invert=MagickFalse;
8153           if (attribute_flag[4] != 0)
8154             {
8155               QueryMagickColor(argument_list[4].string_reference,&target,
8156                 exception);
8157               invert=MagickTrue;
8158             }
8159           if (attribute_flag[5] != 0)
8160             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8161               QuantumRange);
8162           if (attribute_flag[6] != 0)
8163             invert=(MagickBooleanType) argument_list[6].integer_reference;
8164           (void) FloodfillPaintImage(image,DefaultChannels,draw_info,&target,
8165             geometry.x,geometry.y,invert);
8166           draw_info=DestroyDrawInfo(draw_info);
8167           break;
8168         }
8169         case 35:  /* Composite */
8170         {
8171           char
8172             composite_geometry[MaxTextExtent];
8173
8174           Image
8175             *composite_image,
8176             *rotate_image;
8177
8178           compose=OverCompositeOp;
8179           if (attribute_flag[0] != 0)
8180             composite_image=argument_list[0].image_reference;
8181           else
8182             {
8183               ThrowPerlException(exception,OptionError,
8184                 "CompositeImageRequired",PackageName);
8185               goto PerlException;
8186             }
8187           /*
8188             Parameter Handling used for BOTH normal and tiled composition.
8189           */
8190           if (attribute_flag[1] != 0) /* compose */
8191             compose=(CompositeOperator) argument_list[1].integer_reference;
8192           if (attribute_flag[6] != 0) /* opacity  */
8193             {
8194               if (compose != DissolveCompositeOp)
8195                 (void) SetImageOpacity(composite_image,(Quantum)
8196                   SiPrefixToDouble(argument_list[6].string_reference,
8197                   QuantumRange));
8198               else
8199                 {
8200                   CacheView
8201                     *composite_view;
8202
8203                   double
8204                     opacity;
8205
8206                   MagickBooleanType
8207                     sync;
8208
8209                   register ssize_t
8210                     x;
8211
8212                   register Quantum
8213                     *q;
8214
8215                   ssize_t
8216                     y;
8217
8218                   /*
8219                     Handle dissolve composite operator (patch by
8220                     Kevin A. McGrail).
8221                   */
8222                   (void) CloneString(&image->geometry,
8223                     argument_list[6].string_reference);
8224                   opacity=(Quantum) SiPrefixToDouble(
8225                     argument_list[6].string_reference,QuantumRange);
8226                   if (composite_image->matte != MagickTrue)
8227                     (void) SetImageOpacity(composite_image,OpaqueAlpha);
8228                   composite_view=AcquireCacheView(composite_image);
8229                   for (y=0; y < (ssize_t) composite_image->rows ; y++)
8230                   {
8231                     q=GetCacheViewAuthenticPixels(composite_view,0,y,(ssize_t)
8232                       composite_image->columns,1,exception);
8233                     for (x=0; x < (ssize_t) composite_image->columns; x++)
8234                     {
8235                       if (GetPixelAlpha(image,q) == OpaqueAlpha)
8236                         SetPixelAlpha(composite_image,ClampToQuantum(opacity),q);
8237                       q+=GetPixelChannels(composite_image);
8238                     }
8239                     sync=SyncCacheViewAuthenticPixels(composite_view,exception);
8240                     if (sync == MagickFalse)
8241                       break;
8242                   }
8243                   composite_view=DestroyCacheView(composite_view);
8244                 }
8245             }
8246           if (attribute_flag[9] != 0)    /* "color=>" */
8247             QueryColorDatabase(argument_list[9].string_reference,
8248               &composite_image->background_color,exception);
8249           if (attribute_flag[12] != 0) /* "interpolate=>" */
8250             image->interpolate=(InterpolatePixelMethod)
8251               argument_list[12].integer_reference;
8252           if (attribute_flag[13] != 0)   /* "args=>" */
8253             (void) SetImageArtifact(composite_image,"compose:args",
8254               argument_list[13].string_reference);
8255           if (attribute_flag[14] != 0)   /* "blend=>"  depreciated */
8256             (void) SetImageArtifact(composite_image,"compose:args",
8257               argument_list[14].string_reference);
8258           /*
8259             Tiling Composition (with orthogonal rotate).
8260           */
8261           rotate_image=(Image *) NULL;
8262           if (attribute_flag[8] != 0)   /* "rotate=>" */
8263             {
8264                /*
8265                  Rotate image.
8266                */
8267                rotate_image=RotateImage(composite_image,
8268                  argument_list[8].real_reference,exception);
8269                if (rotate_image == (Image *) NULL)
8270                  break;
8271             }
8272           if (attribute_flag[7] && argument_list[7].integer_reference) /* tile */
8273             {
8274               ssize_t
8275                 x,
8276                 y;
8277
8278               /*
8279                 Tile the composite image.
8280               */
8281              if (attribute_flag[8] != 0)   /* "tile=>" */
8282                (void) SetImageArtifact(rotate_image,"compose:outside-overlay",
8283                  "false");
8284              else
8285                (void) SetImageArtifact(composite_image,
8286                  "compose:outside-overlay","false");
8287              for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) composite_image->rows)
8288                 for (x=0; x < (ssize_t) image->columns; x+=(ssize_t) composite_image->columns)
8289                 {
8290                   if (attribute_flag[8] != 0) /* rotate */
8291                     (void) CompositeImage(image,compose,rotate_image,x,y);
8292                   else
8293                     (void) CompositeImage(image,compose,composite_image,x,y);
8294                 }
8295               if (attribute_flag[8] != 0) /* rotate */
8296                 rotate_image=DestroyImage(rotate_image);
8297               break;
8298             }
8299           /*
8300             Parameter Handling used used ONLY for normal composition.
8301           */
8302           if (attribute_flag[5] != 0) /* gravity */
8303             image->gravity=(GravityType) argument_list[5].integer_reference;
8304           if (attribute_flag[2] != 0) /* geometry offset */
8305             {
8306               SetGeometry(image,&geometry);
8307               (void) ParseAbsoluteGeometry(argument_list[2].string_reference,
8308                 &geometry);
8309               GravityAdjustGeometry(image->columns,image->rows,image->gravity,
8310                 &geometry);
8311             }
8312           if (attribute_flag[3] != 0) /* x offset */
8313             geometry.x=argument_list[3].integer_reference;
8314           if (attribute_flag[4] != 0) /* y offset */
8315             geometry.y=argument_list[4].integer_reference;
8316           if (attribute_flag[10] != 0) /* mask */
8317             {
8318               if ((image->compose == DisplaceCompositeOp) ||
8319                   (image->compose == DistortCompositeOp))
8320                 {
8321                   /*
8322                     Merge Y displacement into X displacement image.
8323                   */
8324                   composite_image=CloneImage(composite_image,0,0,MagickTrue,
8325                     &image->exception);
8326                   (void) CompositeImage(composite_image,CopyGreenCompositeOp,
8327                     argument_list[10].image_reference,0,0);
8328                 }
8329               else
8330                 {
8331                   /*
8332                     Set a blending mask for the composition.
8333                   */
8334                   image->mask=CloneImage(argument_list[10].image_reference,0,0,
8335                     MagickTrue,&image->exception);
8336                   (void) NegateImage(image->mask,MagickFalse);
8337                 }
8338             }
8339           if (attribute_flag[11] != 0) /* channel */
8340             channel=(ChannelType) argument_list[11].integer_reference;
8341           /*
8342             Composite two images (normal composition).
8343           */
8344           (void) FormatLocaleString(composite_geometry,MaxTextExtent,
8345             "%.20gx%.20g%+.20g%+.20g",(double) composite_image->columns,
8346             (double) composite_image->rows,(double) geometry.x,(double)
8347             geometry.y);
8348           flags=ParseGravityGeometry(image,composite_geometry,&geometry,
8349             exception);
8350           if (attribute_flag[8] == 0) /* no rotate */
8351             CompositeImageChannel(image,channel,compose,composite_image,
8352               geometry.x,geometry.y);
8353           else
8354             {
8355               /*
8356                 Position adjust rotated image then composite.
8357               */
8358               geometry.x-=(ssize_t) (rotate_image->columns-
8359                 composite_image->columns)/2;
8360               geometry.y-=(ssize_t) (rotate_image->rows-
8361                 composite_image->rows)/2;
8362               CompositeImageChannel(image,channel,compose,rotate_image,
8363                 geometry.x,geometry.y);
8364               rotate_image=DestroyImage(rotate_image);
8365             }
8366           if (attribute_flag[10] != 0) /* mask */
8367             {
8368               if ((image->compose == DisplaceCompositeOp) ||
8369                   (image->compose == DistortCompositeOp))
8370                 composite_image=DestroyImage(composite_image);
8371               else
8372                 image->mask=DestroyImage(image->mask);
8373             }
8374           break;
8375         }
8376         case 36:  /* Contrast */
8377         {
8378           if (attribute_flag[0] == 0)
8379             argument_list[0].integer_reference=0;
8380           (void) ContrastImage(image,argument_list[0].integer_reference != 0 ?
8381             MagickTrue : MagickFalse);
8382           break;
8383         }
8384         case 37:  /* CycleColormap */
8385         {
8386           if (attribute_flag[0] == 0)
8387             argument_list[0].integer_reference=6;
8388           (void) CycleColormapImage(image,argument_list[0].integer_reference);
8389           break;
8390         }
8391         case 38:  /* Draw */
8392         {
8393           DrawInfo
8394             *draw_info;
8395
8396           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8397             (DrawInfo *) NULL);
8398           (void) CloneString(&draw_info->primitive,"point");
8399           if (attribute_flag[0] != 0)
8400             {
8401               if (argument_list[0].integer_reference < 0)
8402                 (void) CloneString(&draw_info->primitive,
8403                   argument_list[0].string_reference);
8404               else
8405                 (void) CloneString(&draw_info->primitive,CommandOptionToMnemonic(
8406                   MagickPrimitiveOptions,argument_list[0].integer_reference));
8407             }
8408           if (attribute_flag[1] != 0)
8409             {
8410               if (LocaleCompare(draw_info->primitive,"path") == 0)
8411                 {
8412                   (void) ConcatenateString(&draw_info->primitive," '");
8413                   ConcatenateString(&draw_info->primitive,
8414                     argument_list[1].string_reference);
8415                   (void) ConcatenateString(&draw_info->primitive,"'");
8416                 }
8417               else
8418                 {
8419                   (void) ConcatenateString(&draw_info->primitive," ");
8420                   ConcatenateString(&draw_info->primitive,
8421                     argument_list[1].string_reference);
8422                 }
8423             }
8424           if (attribute_flag[2] != 0)
8425             {
8426               (void) ConcatenateString(&draw_info->primitive," ");
8427               (void) ConcatenateString(&draw_info->primitive,
8428                 CommandOptionToMnemonic(MagickMethodOptions,
8429                 argument_list[2].integer_reference));
8430             }
8431           if (attribute_flag[3] != 0)
8432             {
8433               (void) QueryColorDatabase(argument_list[3].string_reference,
8434                 &draw_info->stroke,exception);
8435               if (argument_list[3].image_reference != (Image *) NULL)
8436                 draw_info->stroke_pattern=CloneImage(
8437                   argument_list[3].image_reference,0,0,MagickTrue,exception);
8438             }
8439           if (attribute_flag[4] != 0)
8440             {
8441               (void) QueryColorDatabase(argument_list[4].string_reference,
8442                 &draw_info->fill,exception);
8443               if (argument_list[4].image_reference != (Image *) NULL)
8444                 draw_info->fill_pattern=CloneImage(
8445                   argument_list[4].image_reference,0,0,MagickTrue,exception);
8446             }
8447           if (attribute_flag[5] != 0)
8448             draw_info->stroke_width=argument_list[5].real_reference;
8449           if (attribute_flag[6] != 0)
8450             (void) CloneString(&draw_info->font,
8451               argument_list[6].string_reference);
8452           if (attribute_flag[7] != 0)
8453             (void) QueryColorDatabase(argument_list[7].string_reference,
8454               &draw_info->border_color,exception);
8455           if (attribute_flag[8] != 0)
8456             draw_info->affine.tx=argument_list[8].real_reference;
8457           if (attribute_flag[9] != 0)
8458             draw_info->affine.ty=argument_list[9].real_reference;
8459           if (attribute_flag[20] != 0)
8460             {
8461               AV
8462                 *av;
8463
8464               av=(AV *) argument_list[20].array_reference;
8465               if ((av_len(av) != 3) && (av_len(av) != 5))
8466                 {
8467                   ThrowPerlException(exception,OptionError,
8468                     "affine matrix must have 4 or 6 elements",PackageName);
8469                   goto PerlException;
8470                 }
8471               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
8472               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
8473               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
8474               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
8475               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
8476                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
8477                 {
8478                   ThrowPerlException(exception,OptionError,
8479                     "affine matrix is singular",PackageName);
8480                    goto PerlException;
8481                 }
8482               if (av_len(av) == 5)
8483                 {
8484                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
8485                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
8486                 }
8487             }
8488           for (j=10; j < 15; j++)
8489           {
8490             if (attribute_flag[j] == 0)
8491               continue;
8492             value=argument_list[j].string_reference;
8493             angle=argument_list[j].real_reference;
8494             current=draw_info->affine;
8495             GetAffineMatrix(&affine);
8496             switch (j)
8497             {
8498               case 10:
8499               {
8500                 /*
8501                   Translate.
8502                 */
8503                 flags=ParseGeometry(value,&geometry_info);
8504                 affine.tx=geometry_info.xi;
8505                 affine.ty=geometry_info.psi;
8506                 if ((flags & PsiValue) == 0)
8507                   affine.ty=affine.tx;
8508                 break;
8509               }
8510               case 11:
8511               {
8512                 /*
8513                   Scale.
8514                 */
8515                 flags=ParseGeometry(value,&geometry_info);
8516                 affine.sx=geometry_info.rho;
8517                 affine.sy=geometry_info.sigma;
8518                 if ((flags & SigmaValue) == 0)
8519                   affine.sy=affine.sx;
8520                 break;
8521               }
8522               case 12:
8523               {
8524                 /*
8525                   Rotate.
8526                 */
8527                 if (angle == 0.0)
8528                   break;
8529                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
8530                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
8531                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
8532                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
8533                 break;
8534               }
8535               case 13:
8536               {
8537                 /*
8538                   SkewX.
8539                 */
8540                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
8541                 break;
8542               }
8543               case 14:
8544               {
8545                 /*
8546                   SkewY.
8547                 */
8548                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
8549                 break;
8550               }
8551             }
8552             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
8553             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
8554             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
8555             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
8556             draw_info->affine.tx=
8557               current.sx*affine.tx+current.ry*affine.ty+current.tx;
8558             draw_info->affine.ty=
8559               current.rx*affine.tx+current.sy*affine.ty+current.ty;
8560           }
8561           if (attribute_flag[15] != 0)
8562             draw_info->fill_pattern=CloneImage(
8563               argument_list[15].image_reference,0,0,MagickTrue,exception);
8564           if (attribute_flag[16] != 0)
8565             draw_info->pointsize=argument_list[16].real_reference;
8566           if (attribute_flag[17] != 0)
8567             {
8568               draw_info->stroke_antialias=argument_list[17].integer_reference != 0
8569                 ? MagickTrue : MagickFalse;
8570               draw_info->text_antialias=draw_info->stroke_antialias;
8571             }
8572           if (attribute_flag[18] != 0)
8573             (void) CloneString(&draw_info->density,
8574               argument_list[18].string_reference);
8575           if (attribute_flag[19] != 0)
8576             draw_info->stroke_width=argument_list[19].real_reference;
8577           if (attribute_flag[21] != 0)
8578             draw_info->dash_offset=argument_list[21].real_reference;
8579           if (attribute_flag[22] != 0)
8580             {
8581               AV
8582                 *av;
8583
8584               av=(AV *) argument_list[22].array_reference;
8585               draw_info->dash_pattern=(double *) AcquireQuantumMemory(
8586                 av_len(av)+2UL,sizeof(*draw_info->dash_pattern));
8587               if (draw_info->dash_pattern != (double *) NULL)
8588                 {
8589                   for (i=0; i <= av_len(av); i++)
8590                     draw_info->dash_pattern[i]=(double)
8591                       SvNV(*(av_fetch(av,i,0)));
8592                   draw_info->dash_pattern[i]=0.0;
8593                 }
8594             }
8595           if (attribute_flag[23] != 0)
8596             image->interpolate=(InterpolatePixelMethod)
8597               argument_list[23].integer_reference;
8598           if ((attribute_flag[24] != 0) &&
8599               (draw_info->fill_pattern != (Image *) NULL))
8600             flags=ParsePageGeometry(draw_info->fill_pattern,
8601               argument_list[24].string_reference,
8602               &draw_info->fill_pattern->tile_offset,exception);
8603           if (attribute_flag[25] != 0)
8604             {
8605               (void) ConcatenateString(&draw_info->primitive," '");
8606               (void) ConcatenateString(&draw_info->primitive,
8607                 argument_list[25].string_reference);
8608               (void) ConcatenateString(&draw_info->primitive,"'");
8609             }
8610           if (attribute_flag[26] != 0)
8611             draw_info->fill_pattern=CloneImage(
8612               argument_list[26].image_reference,0,0,MagickTrue,exception);
8613           if (attribute_flag[27] != 0)
8614             draw_info->stroke_pattern=CloneImage(
8615               argument_list[27].image_reference,0,0,MagickTrue,exception);
8616           if (attribute_flag[28] != 0)
8617             (void) CloneString(&draw_info->primitive,
8618               argument_list[28].string_reference);
8619           if (attribute_flag[29] != 0)
8620             draw_info->kerning=argument_list[29].real_reference;
8621           if (attribute_flag[30] != 0)
8622             draw_info->interline_spacing=argument_list[30].real_reference;
8623           if (attribute_flag[31] != 0)
8624             draw_info->interword_spacing=argument_list[31].real_reference;
8625           if (attribute_flag[32] != 0)
8626             draw_info->direction=(DirectionType)
8627               argument_list[32].integer_reference;
8628           DrawImage(image,draw_info);
8629           draw_info=DestroyDrawInfo(draw_info);
8630           break;
8631         }
8632         case 39:  /* Equalize */
8633         {
8634           if (attribute_flag[0] != 0)
8635             channel=(ChannelType) argument_list[0].integer_reference;
8636           EqualizeImageChannel(image,channel);
8637           break;
8638         }
8639         case 40:  /* Gamma */
8640         {
8641           if (attribute_flag[1] != 0)
8642             channel=(ChannelType) argument_list[1].integer_reference;
8643           if (attribute_flag[2] == 0)
8644             argument_list[2].real_reference=1.0;
8645           if (attribute_flag[3] == 0)
8646             argument_list[3].real_reference=1.0;
8647           if (attribute_flag[4] == 0)
8648             argument_list[4].real_reference=1.0;
8649           if (attribute_flag[0] == 0)
8650             {
8651               (void) FormatLocaleString(message,MaxTextExtent,
8652                 "%.15g,%.15g,%.15g",(double) argument_list[2].real_reference,
8653                 (double) argument_list[3].real_reference,
8654                 (double) argument_list[4].real_reference);
8655               argument_list[0].string_reference=message;
8656             }
8657           if (strchr(argument_list[0].string_reference,',') != (char *) NULL)
8658             (void) GammaImage(image,argument_list[0].string_reference);
8659           else
8660             (void) GammaImageChannel(image,channel,InterpretLocaleValue(
8661               argument_list[0].string_reference,(char **) NULL));
8662           break;
8663         }
8664         case 41:  /* Map */
8665         {
8666           QuantizeInfo
8667             *quantize_info;
8668
8669           if (attribute_flag[0] == 0)
8670             {
8671               ThrowPerlException(exception,OptionError,"MapImageRequired",
8672                 PackageName);
8673               goto PerlException;
8674             }
8675           quantize_info=AcquireQuantizeInfo(info->image_info);
8676           if (attribute_flag[1] != 0)
8677             quantize_info->dither=(MagickBooleanType)
8678               argument_list[1].integer_reference;
8679           if (attribute_flag[2] != 0)
8680             quantize_info->dither_method=(DitherMethod)
8681               argument_list[2].integer_reference;
8682           (void) RemapImages(quantize_info,image,
8683             argument_list[0].image_reference);
8684           quantize_info=DestroyQuantizeInfo(quantize_info);
8685           break;
8686         }
8687         case 42:  /* MatteFloodfill */
8688         {
8689           DrawInfo
8690             *draw_info;
8691
8692           MagickBooleanType
8693             invert;
8694
8695           PixelInfo
8696             target;
8697
8698           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
8699             (DrawInfo *) NULL);
8700           if (attribute_flag[0] != 0)
8701           if (attribute_flag[0] != 0)
8702             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8703               &geometry,exception);
8704           if (attribute_flag[1] != 0)
8705             geometry.x=argument_list[1].integer_reference;
8706           if (attribute_flag[2] != 0)
8707             geometry.y=argument_list[2].integer_reference;
8708           if (image->matte == MagickFalse)
8709             (void) SetImageOpacity(image,OpaqueAlpha);
8710           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
8711             exception);
8712           if (attribute_flag[4] != 0)
8713             QueryMagickColor(argument_list[4].string_reference,&target,
8714               exception);
8715           if (attribute_flag[3] != 0)
8716             target.alpha=SiPrefixToDouble(argument_list[3].string_reference,
8717               QuantumRange);
8718           if (attribute_flag[5] != 0)
8719             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
8720               QuantumRange);
8721           invert=MagickFalse;
8722           if (attribute_flag[6] != 0)
8723             invert=(MagickBooleanType) argument_list[6].integer_reference;
8724           (void) FloodfillPaintImage(image,AlphaChannel,draw_info,&target,
8725             geometry.x,geometry.y,invert);
8726           draw_info=DestroyDrawInfo(draw_info);
8727           break;
8728         }
8729         case 43:  /* Modulate */
8730         {
8731           char
8732             modulate[MaxTextExtent];
8733
8734           geometry_info.rho=100.0;
8735           geometry_info.sigma=100.0;
8736           geometry_info.xi=100.0;
8737           if (attribute_flag[0] != 0)
8738             (void)ParseGeometry(argument_list[0].string_reference,
8739               &geometry_info);
8740           if (attribute_flag[1] != 0)
8741             geometry_info.xi=argument_list[1].real_reference;
8742           if (attribute_flag[2] != 0)
8743             geometry_info.sigma=argument_list[2].real_reference;
8744           if (attribute_flag[3] != 0)
8745             {
8746               geometry_info.sigma=argument_list[3].real_reference;
8747               SetImageArtifact(image,"modulate:colorspace","HWB");
8748             }
8749           if (attribute_flag[4] != 0)
8750             {
8751               geometry_info.rho=argument_list[4].real_reference;
8752               SetImageArtifact(image,"modulate:colorspace","HSB");
8753             }
8754           if (attribute_flag[5] != 0)
8755             {
8756               geometry_info.sigma=argument_list[5].real_reference;
8757               SetImageArtifact(image,"modulate:colorspace","HSL");
8758             }
8759           if (attribute_flag[6] != 0)
8760             {
8761               geometry_info.rho=argument_list[6].real_reference;
8762               SetImageArtifact(image,"modulate:colorspace","HWB");
8763             }
8764           (void) FormatLocaleString(modulate,MaxTextExtent,"%.15g,%.15g,%.15g",
8765             geometry_info.rho,geometry_info.sigma,geometry_info.xi);
8766           (void) ModulateImage(image,modulate);
8767           break;
8768         }
8769         case 44:  /* Negate */
8770         {
8771           if (attribute_flag[0] == 0)
8772             argument_list[0].integer_reference=0;
8773           if (attribute_flag[1] != 0)
8774             channel=(ChannelType) argument_list[1].integer_reference;
8775           (void) NegateImageChannel(image,channel,
8776             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse);
8777           break;
8778         }
8779         case 45:  /* Normalize */
8780         {
8781           if (attribute_flag[0] != 0)
8782             channel=(ChannelType) argument_list[0].integer_reference;
8783           NormalizeImageChannel(image,channel);
8784           break;
8785         }
8786         case 46:  /* NumberColors */
8787           break;
8788         case 47:  /* Opaque */
8789         {
8790           MagickBooleanType
8791             invert;
8792
8793           PixelInfo
8794             fill_color,
8795             target;
8796
8797           (void) QueryMagickColor("none",&target,exception);
8798           (void) QueryMagickColor("none",&fill_color,exception);
8799           if (attribute_flag[0] != 0)
8800             (void) QueryMagickColor(argument_list[0].string_reference,
8801               &target,exception);
8802           if (attribute_flag[1] != 0)
8803             (void) QueryMagickColor(argument_list[1].string_reference,
8804               &fill_color,exception);
8805           if (attribute_flag[2] != 0)
8806             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8807               QuantumRange);
8808           if (attribute_flag[3] != 0)
8809             channel=(ChannelType) argument_list[3].integer_reference;
8810           invert=MagickFalse;
8811           if (attribute_flag[4] != 0)
8812             invert=(MagickBooleanType) argument_list[4].integer_reference;
8813           (void) OpaquePaintImageChannel(image,channel,&target,&fill_color,
8814             invert);
8815           break;
8816         }
8817         case 48:  /* Quantize */
8818         {
8819           QuantizeInfo
8820             *quantize_info;
8821
8822           quantize_info=AcquireQuantizeInfo(info->image_info);
8823           if (attribute_flag[0] != 0)
8824             quantize_info->number_colors=(size_t)
8825               argument_list[0].integer_reference;
8826           if (attribute_flag[1] != 0)
8827             quantize_info->tree_depth=(size_t)
8828               argument_list[1].integer_reference;
8829           if (attribute_flag[2] != 0)
8830             quantize_info->colorspace=(ColorspaceType)
8831               argument_list[2].integer_reference;
8832           if (attribute_flag[3] != 0)
8833             quantize_info->dither=argument_list[3].integer_reference != 0 ?
8834               MagickTrue : MagickFalse;
8835           if (attribute_flag[4] != 0)
8836             quantize_info->measure_error=
8837               argument_list[4].integer_reference != 0 ? MagickTrue : MagickFalse;
8838           if (attribute_flag[5] != 0)
8839             (void) QueryColorDatabase(argument_list[5].string_reference,
8840               &image->transparent_color,exception);
8841           if (attribute_flag[5] && argument_list[5].integer_reference)
8842             {
8843               (void) QuantizeImages(quantize_info,image);
8844               goto PerlException;
8845             }
8846           if (attribute_flag[6] != 0)
8847             quantize_info->dither_method=(DitherMethod)
8848               argument_list[6].integer_reference;
8849           if ((image->storage_class == DirectClass) ||
8850               (image->colors > quantize_info->number_colors) ||
8851               (quantize_info->colorspace == GRAYColorspace))
8852             (void) QuantizeImage(quantize_info,image);
8853           else
8854             CompressImageColormap(image);
8855           quantize_info=DestroyQuantizeInfo(quantize_info);
8856           break;
8857         }
8858         case 49:  /* Raise */
8859         {
8860           if (attribute_flag[0] != 0)
8861             flags=ParsePageGeometry(image,argument_list[0].string_reference,
8862               &geometry,exception);
8863           if (attribute_flag[1] != 0)
8864             geometry.width=argument_list[1].integer_reference;
8865           if (attribute_flag[2] != 0)
8866             geometry.height=argument_list[2].integer_reference;
8867           if (attribute_flag[3] == 0)
8868             argument_list[3].integer_reference=1;
8869           (void) RaiseImage(image,&geometry,argument_list[3].integer_reference !=
8870             0 ? MagickTrue : MagickFalse);
8871           break;
8872         }
8873         case 50:  /* Segment */
8874         {
8875           ColorspaceType
8876             colorspace;
8877
8878           double
8879             cluster_threshold,
8880             smoothing_threshold;
8881
8882           MagickBooleanType
8883             verbose;
8884
8885           cluster_threshold=1.0;
8886           smoothing_threshold=1.5;
8887           colorspace=RGBColorspace;
8888           verbose=MagickFalse;
8889           if (attribute_flag[0] != 0)
8890             {
8891               flags=ParseGeometry(argument_list[0].string_reference,
8892                 &geometry_info);
8893               cluster_threshold=geometry_info.rho;
8894               if (flags & SigmaValue)
8895                 smoothing_threshold=geometry_info.sigma;
8896             }
8897           if (attribute_flag[1] != 0)
8898             cluster_threshold=argument_list[1].real_reference;
8899           if (attribute_flag[2] != 0)
8900             smoothing_threshold=argument_list[2].real_reference;
8901           if (attribute_flag[3] != 0)
8902             colorspace=(ColorspaceType) argument_list[3].integer_reference;
8903           if (attribute_flag[4] != 0)
8904             verbose=argument_list[4].integer_reference != 0 ?
8905               MagickTrue : MagickFalse;
8906           (void) SegmentImage(image,colorspace,verbose,cluster_threshold,
8907             smoothing_threshold);
8908           break;
8909         }
8910         case 51:  /* Signature */
8911         {
8912           (void) SignatureImage(image);
8913           break;
8914         }
8915         case 52:  /* Solarize */
8916         {
8917           geometry_info.rho=QuantumRange/2.0;
8918           if (attribute_flag[0] != 0)
8919             flags=ParseGeometry(argument_list[0].string_reference,
8920               &geometry_info);
8921           if (attribute_flag[1] != 0)
8922             geometry_info.rho=SiPrefixToDouble(argument_list[1].string_reference,
8923              QuantumRange);
8924           (void) SolarizeImage(image,geometry_info.rho);
8925           break;
8926         }
8927         case 53:  /* Sync */
8928         {
8929           (void) SyncImage(image);
8930           break;
8931         }
8932         case 54:  /* Texture */
8933         {
8934           if (attribute_flag[0] == 0)
8935             break;
8936           TextureImage(image,argument_list[0].image_reference);
8937           break;
8938         }
8939         case 55:  /* Evalute */
8940         {
8941           MagickEvaluateOperator
8942             op;
8943
8944           op=SetEvaluateOperator;
8945           if (attribute_flag[0] == MagickFalse)
8946             argument_list[0].real_reference=0.0;
8947           if (attribute_flag[1] != MagickFalse)
8948             op=(MagickEvaluateOperator) argument_list[1].integer_reference;
8949           if (attribute_flag[2] != MagickFalse)
8950             channel=(ChannelType) argument_list[2].integer_reference;
8951           (void) EvaluateImageChannel(image,channel,op,
8952             argument_list[0].real_reference,exception);
8953           break;
8954         }
8955         case 56:  /* Transparent */
8956         {
8957           double
8958             opacity;
8959
8960           MagickBooleanType
8961             invert;
8962
8963           PixelInfo
8964             target;
8965
8966           (void) QueryMagickColor("none",&target,exception);
8967           if (attribute_flag[0] != 0)
8968             (void) QueryMagickColor(argument_list[0].string_reference,&target,
8969               exception);
8970           opacity=TransparentAlpha;
8971           if (attribute_flag[1] != 0)
8972             opacity=SiPrefixToDouble(argument_list[1].string_reference,
8973               QuantumRange);
8974           if (attribute_flag[2] != 0)
8975             image->fuzz=SiPrefixToDouble(argument_list[2].string_reference,
8976               QuantumRange);
8977           if (attribute_flag[3] == 0)
8978             argument_list[3].integer_reference=0;
8979           invert=MagickFalse;
8980           if (attribute_flag[3] != 0)
8981             invert=(MagickBooleanType) argument_list[3].integer_reference;
8982           (void) TransparentPaintImage(image,&target,ClampToQuantum(opacity),
8983             invert);
8984           break;
8985         }
8986         case 57:  /* Threshold */
8987         {
8988           double
8989             threshold;
8990
8991           if (attribute_flag[0] == 0)
8992             argument_list[0].string_reference="50%";
8993           if (attribute_flag[1] != 0)
8994             channel=(ChannelType) argument_list[1].integer_reference;
8995           threshold=SiPrefixToDouble(argument_list[0].string_reference,
8996             QuantumRange);
8997           (void) BilevelImageChannel(image,channel,threshold);
8998           break;
8999         }
9000         case 58:  /* Charcoal */
9001         {
9002           if (attribute_flag[0] != 0)
9003             {
9004               flags=ParseGeometry(argument_list[0].string_reference,
9005                 &geometry_info);
9006               if ((flags & SigmaValue) == 0)
9007                 geometry_info.sigma=1.0;
9008             }
9009           if (attribute_flag[1] != 0)
9010             geometry_info.rho=argument_list[1].real_reference;
9011           if (attribute_flag[2] != 0)
9012             geometry_info.sigma=argument_list[2].real_reference;
9013           image=CharcoalImage(image,geometry_info.rho,geometry_info.sigma,
9014             exception);
9015           break;
9016         }
9017         case 59:  /* Trim */
9018         {
9019           if (attribute_flag[0] != 0)
9020             image->fuzz=SiPrefixToDouble(argument_list[0].string_reference,
9021               QuantumRange);
9022           image=TrimImage(image,exception);
9023           break;
9024         }
9025         case 60:  /* Wave */
9026         {
9027           if (attribute_flag[0] != 0)
9028             {
9029               flags=ParseGeometry(argument_list[0].string_reference,
9030                 &geometry_info);
9031               if ((flags & SigmaValue) == 0)
9032                 geometry_info.sigma=1.0;
9033             }
9034           if (attribute_flag[1] != 0)
9035             geometry_info.rho=argument_list[1].real_reference;
9036           if (attribute_flag[2] != 0)
9037             geometry_info.sigma=argument_list[2].real_reference;
9038           if (attribute_flag[3] != 0)
9039             image->interpolate=(InterpolatePixelMethod)
9040               argument_list[3].integer_reference;
9041           image=WaveImage(image,geometry_info.rho,geometry_info.sigma,
9042             exception);
9043           break;
9044         }
9045         case 61:  /* Separate */
9046         {
9047           if (attribute_flag[0] != 0)
9048             channel=(ChannelType) argument_list[0].integer_reference;
9049           (void) SeparateImageChannel(image,channel);
9050           break;
9051         }
9052         case 63:  /* Stereo */
9053         {
9054           if (attribute_flag[0] == 0)
9055             {
9056               ThrowPerlException(exception,OptionError,"StereoImageRequired",
9057                 PackageName);
9058               goto PerlException;
9059             }
9060           if (attribute_flag[1] != 0)
9061             geometry.x=argument_list[1].integer_reference;
9062           if (attribute_flag[2] != 0)
9063             geometry.y=argument_list[2].integer_reference;
9064           image=StereoAnaglyphImage(image,argument_list[0].image_reference,
9065             geometry.x,geometry.y,exception);
9066           break;
9067         }
9068         case 64:  /* Stegano */
9069         {
9070           if (attribute_flag[0] == 0)
9071             {
9072               ThrowPerlException(exception,OptionError,"SteganoImageRequired",
9073                 PackageName);
9074               goto PerlException;
9075             }
9076           if (attribute_flag[1] == 0)
9077             argument_list[1].integer_reference=0;
9078           image->offset=argument_list[1].integer_reference;
9079           image=SteganoImage(image,argument_list[0].image_reference,exception);
9080           break;
9081         }
9082         case 65:  /* Deconstruct */
9083         {
9084           image=CompareImageLayers(image,CompareAnyLayer,exception);
9085           break;
9086         }
9087         case 66:  /* GaussianBlur */
9088         {
9089           if (attribute_flag[0] != 0)
9090             {
9091               flags=ParseGeometry(argument_list[0].string_reference,
9092                 &geometry_info);
9093               if ((flags & SigmaValue) == 0)
9094                 geometry_info.sigma=1.0;
9095             }
9096           if (attribute_flag[1] != 0)
9097             geometry_info.rho=argument_list[1].real_reference;
9098           if (attribute_flag[2] != 0)
9099             geometry_info.sigma=argument_list[2].real_reference;
9100           if (attribute_flag[3] != 0)
9101             channel=(ChannelType) argument_list[3].integer_reference;
9102           image=GaussianBlurImageChannel(image,channel,geometry_info.rho,
9103             geometry_info.sigma,exception);
9104           break;
9105         }
9106         case 67:  /* Convolve */
9107         {
9108           AV
9109             *av;
9110
9111           double
9112             *kernel;
9113
9114           size_t
9115             order;
9116
9117           if (attribute_flag[0] == 0)
9118             break;
9119           if (attribute_flag[1] != 0)
9120             channel=(ChannelType) argument_list[1].integer_reference;
9121           if (attribute_flag[2] != 0)
9122             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
9123               QuantumRange);
9124           av=(AV *) argument_list[0].array_reference;
9125           order=(size_t) sqrt(av_len(av)+1);
9126           kernel=(double *) AcquireQuantumMemory(order,order*sizeof(*kernel));
9127           if (kernel == (double *) NULL)
9128             {
9129               ThrowPerlException(exception,ResourceLimitFatalError,
9130                 "MemoryAllocationFailed",PackageName);
9131               goto PerlException;
9132             }
9133           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
9134             kernel[j]=(double) SvNV(*(av_fetch(av,j,0)));
9135           for ( ; j < (ssize_t) (order*order); j++)
9136             kernel[j]=0.0;
9137           image=ConvolveImageChannel(image,channel,order,kernel,exception);
9138           kernel=(double *) RelinquishMagickMemory(kernel);
9139           break;
9140         }
9141         case 68:  /* Profile */
9142         {
9143           const char
9144             *name;
9145
9146           Image
9147             *profile_image;
9148
9149           ImageInfo
9150             *profile_info;
9151
9152           StringInfo
9153             *profile;
9154
9155           name="*";
9156           if (attribute_flag[0] != 0)
9157             name=argument_list[0].string_reference;
9158           if (attribute_flag[2] != 0)
9159             image->rendering_intent=(RenderingIntent)
9160               argument_list[2].integer_reference;
9161           if (attribute_flag[3] != 0)
9162             image->black_point_compensation=
9163               argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse;
9164           if (attribute_flag[1] != 0)
9165             {
9166               if (argument_list[1].length == 0)
9167                 {
9168                   /*
9169                     Remove a profile from the image.
9170                   */
9171                   (void) ProfileImage(image,name,(const unsigned char *) NULL,0,
9172                     MagickTrue);
9173                   break;
9174                 }
9175               /*
9176                 Associate user supplied profile with the image.
9177               */
9178               profile=AcquireStringInfo(argument_list[1].length);
9179               SetStringInfoDatum(profile,(const unsigned char *)
9180                 argument_list[1].string_reference);
9181               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9182                 (size_t) GetStringInfoLength(profile),MagickFalse);
9183               profile=DestroyStringInfo(profile);
9184               break;
9185             }
9186           /*
9187             Associate a profile with the image.
9188           */
9189           profile_info=
9190             CloneImageInfo(info ? info->image_info : (ImageInfo *) NULL);
9191           (void) CopyMagickString(profile_info->filename,name,MaxTextExtent);
9192           profile_image=ReadImages(profile_info,&image->exception);
9193           if (profile_image == (Image *) NULL)
9194             break;
9195           ResetImageProfileIterator(profile_image);
9196           name=GetNextImageProfile(profile_image);
9197           while (name != (const char *) NULL)
9198           {
9199             const StringInfo
9200               *profile;
9201
9202             profile=GetImageProfile(profile_image,name);
9203             if (profile != (const StringInfo *) NULL)
9204               (void) ProfileImage(image,name,GetStringInfoDatum(profile),
9205                 (size_t) GetStringInfoLength(profile),MagickFalse);
9206             name=GetNextImageProfile(profile_image);
9207           }
9208           profile_image=DestroyImage(profile_image);
9209           profile_info=DestroyImageInfo(profile_info);
9210           break;
9211         }
9212         case 69:  /* UnsharpMask */
9213         {
9214           if (attribute_flag[0] != 0)
9215             {
9216               flags=ParseGeometry(argument_list[0].string_reference,
9217                 &geometry_info);
9218               if ((flags & SigmaValue) == 0)
9219                 geometry_info.sigma=1.0;
9220               if ((flags & XiValue) == 0)
9221                 geometry_info.xi=1.0;
9222               if ((flags & PsiValue) == 0)
9223                 geometry_info.psi=0.5;
9224             }
9225           if (attribute_flag[1] != 0)
9226             geometry_info.rho=argument_list[1].real_reference;
9227           if (attribute_flag[2] != 0)
9228             geometry_info.sigma=argument_list[2].real_reference;
9229           if (attribute_flag[3] != 0)
9230             geometry_info.xi=argument_list[3].real_reference;
9231           if (attribute_flag[4] != 0)
9232             geometry_info.psi=argument_list[4].real_reference;
9233           if (attribute_flag[5] != 0)
9234             channel=(ChannelType) argument_list[5].integer_reference;
9235           image=UnsharpMaskImageChannel(image,channel,geometry_info.rho,
9236             geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
9237           break;
9238         }
9239         case 70:  /* MotionBlur */
9240         {
9241           if (attribute_flag[0] != 0)
9242             {
9243               flags=ParseGeometry(argument_list[0].string_reference,
9244                 &geometry_info);
9245               if ((flags & SigmaValue) == 0)
9246                 geometry_info.sigma=1.0;
9247               if ((flags & XiValue) == 0)
9248                 geometry_info.xi=1.0;
9249             }
9250           if (attribute_flag[1] != 0)
9251             geometry_info.rho=argument_list[1].real_reference;
9252           if (attribute_flag[2] != 0)
9253             geometry_info.sigma=argument_list[2].real_reference;
9254           if (attribute_flag[3] != 0)
9255             geometry_info.xi=argument_list[3].real_reference;
9256           if (attribute_flag[4] != 0)
9257             channel=(ChannelType) argument_list[4].integer_reference;
9258           image=MotionBlurImageChannel(image,channel,geometry_info.rho,
9259             geometry_info.sigma,geometry_info.xi,exception);
9260           break;
9261         }
9262         case 71:  /* OrderedDither */
9263         {
9264           if (attribute_flag[0] == 0)
9265             argument_list[0].string_reference="o8x8";
9266           if (attribute_flag[1] != 0)
9267             channel=(ChannelType) argument_list[1].integer_reference;
9268           (void) OrderedPosterizeImageChannel(image,channel,
9269             argument_list[0].string_reference,exception);
9270           break;
9271         }
9272         case 72:  /* Shave */
9273         {
9274           if (attribute_flag[0] != 0)
9275             flags=ParsePageGeometry(image,argument_list[0].string_reference,
9276               &geometry,exception);
9277           if (attribute_flag[1] != 0)
9278             geometry.width=argument_list[1].integer_reference;
9279           if (attribute_flag[2] != 0)
9280             geometry.height=argument_list[2].integer_reference;
9281           image=ShaveImage(image,&geometry,exception);
9282           break;
9283         }
9284         case 73:  /* Level */
9285         {
9286           double
9287             black_point,
9288             gamma,
9289             white_point;
9290
9291           black_point=0.0;
9292           white_point=(MagickRealType) image->columns*image->rows;
9293           gamma=1.0;
9294           if (attribute_flag[0] != 0)
9295             {
9296               flags=ParseGeometry(argument_list[0].string_reference,
9297                 &geometry_info);
9298               black_point=geometry_info.rho;
9299               if ((flags & SigmaValue) != 0)
9300                 white_point=geometry_info.sigma;
9301               if ((flags & XiValue) != 0)
9302                 gamma=geometry_info.xi;
9303               if ((flags & PercentValue) != 0)
9304                 {
9305                   black_point*=(double) (QuantumRange/100.0);
9306                   white_point*=(double) (QuantumRange/100.0);
9307                 }
9308               if ((flags & SigmaValue) == 0)
9309                 white_point=(double) QuantumRange-black_point;
9310             }
9311           if (attribute_flag[1] != 0)
9312             black_point=argument_list[1].real_reference;
9313           if (attribute_flag[2] != 0)
9314             white_point=argument_list[2].real_reference;
9315           if (attribute_flag[3] != 0)
9316             gamma=argument_list[3].real_reference;
9317           if (attribute_flag[4] != 0)
9318             channel=(ChannelType) argument_list[4].integer_reference;
9319           if (attribute_flag[5] != 0)
9320             {
9321               argument_list[0].real_reference=argument_list[5].real_reference;
9322               attribute_flag[0]=attribute_flag[5];
9323             }
9324           (void) LevelImageChannel(image,channel,black_point,white_point,gamma);
9325           break;
9326         }
9327         case 74:  /* Clip */
9328         {
9329           if (attribute_flag[0] == 0)
9330             argument_list[0].string_reference="#1";
9331           if (attribute_flag[1] == 0)
9332             argument_list[1].integer_reference=MagickTrue;
9333           (void) ClipImagePath(image,argument_list[0].string_reference,
9334             argument_list[1].integer_reference != 0 ? MagickTrue : MagickFalse);
9335           break;
9336         }
9337         case 75:  /* AffineTransform */
9338         {
9339           DrawInfo
9340             *draw_info;
9341
9342           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
9343             (DrawInfo *) NULL);
9344           if (attribute_flag[0] != 0)
9345             {
9346               AV
9347                 *av;
9348
9349               av=(AV *) argument_list[0].array_reference;
9350               if ((av_len(av) != 3) && (av_len(av) != 5))
9351                 {
9352                   ThrowPerlException(exception,OptionError,
9353                     "affine matrix must have 4 or 6 elements",PackageName);
9354                   goto PerlException;
9355                 }
9356               draw_info->affine.sx=(double) SvNV(*(av_fetch(av,0,0)));
9357               draw_info->affine.rx=(double) SvNV(*(av_fetch(av,1,0)));
9358               draw_info->affine.ry=(double) SvNV(*(av_fetch(av,2,0)));
9359               draw_info->affine.sy=(double) SvNV(*(av_fetch(av,3,0)));
9360               if (fabs(draw_info->affine.sx*draw_info->affine.sy-
9361                   draw_info->affine.rx*draw_info->affine.ry) < MagickEpsilon)
9362                 {
9363                   ThrowPerlException(exception,OptionError,
9364                     "affine matrix is singular",PackageName);
9365                    goto PerlException;
9366                 }
9367               if (av_len(av) == 5)
9368                 {
9369                   draw_info->affine.tx=(double) SvNV(*(av_fetch(av,4,0)));
9370                   draw_info->affine.ty=(double) SvNV(*(av_fetch(av,5,0)));
9371                 }
9372             }
9373           for (j=1; j < 6; j++)
9374           {
9375             if (attribute_flag[j] == 0)
9376               continue;
9377             value=argument_list[j].string_reference;
9378             angle=argument_list[j].real_reference;
9379             current=draw_info->affine;
9380             GetAffineMatrix(&affine);
9381             switch (j)
9382             {
9383               case 1:
9384               {
9385                 /*
9386                   Translate.
9387                 */
9388                 flags=ParseGeometry(value,&geometry_info);
9389                 affine.tx=geometry_info.xi;
9390                 affine.ty=geometry_info.psi;
9391                 if ((flags & PsiValue) == 0)
9392                   affine.ty=affine.tx;
9393                 break;
9394               }
9395               case 2:
9396               {
9397                 /*
9398                   Scale.
9399                 */
9400                 flags=ParseGeometry(value,&geometry_info);
9401                 affine.sx=geometry_info.rho;
9402                 affine.sy=geometry_info.sigma;
9403                 if ((flags & SigmaValue) == 0)
9404                   affine.sy=affine.sx;
9405                 break;
9406               }
9407               case 3:
9408               {
9409                 /*
9410                   Rotate.
9411                 */
9412                 if (angle == 0.0)
9413                   break;
9414                 affine.sx=cos(DegreesToRadians(fmod(angle,360.0)));
9415                 affine.rx=sin(DegreesToRadians(fmod(angle,360.0)));
9416                 affine.ry=(-sin(DegreesToRadians(fmod(angle,360.0))));
9417                 affine.sy=cos(DegreesToRadians(fmod(angle,360.0)));
9418                 break;
9419               }
9420               case 4:
9421               {
9422                 /*
9423                   SkewX.
9424                 */
9425                 affine.ry=tan(DegreesToRadians(fmod(angle,360.0)));
9426                 break;
9427               }
9428               case 5:
9429               {
9430                 /*
9431                   SkewY.
9432                 */
9433                 affine.rx=tan(DegreesToRadians(fmod(angle,360.0)));
9434                 break;
9435               }
9436             }
9437             draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
9438             draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
9439             draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
9440             draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
9441             draw_info->affine.tx=
9442               current.sx*affine.tx+current.ry*affine.ty+current.tx;
9443             draw_info->affine.ty=
9444               current.rx*affine.tx+current.sy*affine.ty+current.ty;
9445           }
9446           if (attribute_flag[6] != 0)
9447             image->interpolate=(InterpolatePixelMethod)
9448               argument_list[6].integer_reference;
9449           if (attribute_flag[7] != 0)
9450             QueryColorDatabase(argument_list[7].string_reference,
9451               &image->background_color,exception);
9452           image=AffineTransformImage(image,&draw_info->affine,exception);
9453           draw_info=DestroyDrawInfo(draw_info);
9454           break;
9455         }
9456         case 76:  /* Difference */
9457         {
9458           if (attribute_flag[0] == 0)
9459             {
9460               ThrowPerlException(exception,OptionError,
9461                 "ReferenceImageRequired",PackageName);
9462               goto PerlException;
9463             }
9464           if (attribute_flag[1] != 0)
9465             image->fuzz=SiPrefixToDouble(argument_list[1].string_reference,
9466               QuantumRange);
9467           (void) IsImagesEqual(image,argument_list[0].image_reference);
9468           break;
9469         }
9470         case 77:  /* AdaptiveThreshold */
9471         {
9472           if (attribute_flag[0] != 0)
9473             {
9474               flags=ParseGeometry(argument_list[0].string_reference,
9475                 &geometry_info);
9476               if ((flags & PercentValue) != 0)
9477                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
9478             }
9479           if (attribute_flag[1] != 0)
9480             geometry_info.rho=argument_list[1].integer_reference;
9481           if (attribute_flag[2] != 0)
9482             geometry_info.sigma=argument_list[2].integer_reference;
9483           if (attribute_flag[3] != 0)
9484             geometry_info.xi=argument_list[3].integer_reference;;
9485           image=AdaptiveThresholdImage(image,(size_t) geometry_info.rho,
9486             (size_t) geometry_info.sigma,(ssize_t) geometry_info.xi,
9487             exception);
9488           break;
9489         }
9490         case 78:  /* Resample */
9491         {
9492           size_t
9493             height,
9494             width;
9495
9496           if (attribute_flag[0] != 0)
9497             {
9498               flags=ParseGeometry(argument_list[0].string_reference,
9499                 &geometry_info);
9500               if ((flags & SigmaValue) == 0)
9501                 geometry_info.sigma=geometry_info.rho;
9502             }
9503           if (attribute_flag[1] != 0)
9504             geometry_info.rho=argument_list[1].real_reference;
9505           if (attribute_flag[2] != 0)
9506             geometry_info.sigma=argument_list[2].real_reference;
9507           if (attribute_flag[3] == 0)
9508             argument_list[3].integer_reference=(ssize_t) UndefinedFilter;
9509           if (attribute_flag[4] == 0)
9510             SetImageArtifact(image,"filter:support",
9511               argument_list[4].string_reference);
9512           if (attribute_flag[5] != 0)
9513             argument_list[5].real_reference=1.0;
9514           width=(size_t) (geometry_info.rho*image->columns/
9515             (image->x_resolution == 0.0 ? 72.0 : image->x_resolution)+0.5);
9516           height=(size_t) (geometry_info.sigma*image->rows/
9517             (image->y_resolution == 0.0 ? 72.0 : image->y_resolution)+0.5);
9518           image=ResizeImage(image,width,height,(FilterTypes)
9519             argument_list[3].integer_reference,argument_list[5].real_reference,
9520             exception);
9521           if (image != (Image *) NULL)
9522             {
9523               image->x_resolution=geometry_info.rho;
9524               image->y_resolution=geometry_info.sigma;
9525             }
9526           break;
9527         }
9528         case 79:  /* Describe */
9529         {
9530           if (attribute_flag[0] == 0)
9531             argument_list[0].file_reference=(FILE *) NULL;
9532           if (attribute_flag[1] != 0)
9533             (void) SetImageArtifact(image,"identify:features",
9534               argument_list[1].string_reference);
9535           (void) IdentifyImage(image,argument_list[0].file_reference,
9536             MagickTrue);
9537           break;
9538         }
9539         case 80:  /* BlackThreshold */
9540         {
9541           if (attribute_flag[0] == 0)
9542             argument_list[0].string_reference="50%";
9543           if (attribute_flag[2] != 0)
9544             channel=(ChannelType) argument_list[2].integer_reference;
9545           BlackThresholdImageChannel(image,channel,
9546             argument_list[0].string_reference,exception);
9547           break;
9548         }
9549         case 81:  /* WhiteThreshold */
9550         {
9551           if (attribute_flag[0] == 0)
9552             argument_list[0].string_reference="50%";
9553           if (attribute_flag[2] != 0)
9554             channel=(ChannelType) argument_list[2].integer_reference;
9555           WhiteThresholdImageChannel(image,channel,
9556             argument_list[0].string_reference,exception);
9557           break;
9558         }
9559         case 82:  /* RadialBlur */
9560         {
9561           if (attribute_flag[0] != 0)
9562             {
9563               flags=ParseGeometry(argument_list[0].string_reference,
9564                 &geometry_info);
9565               if ((flags & SigmaValue) == 0)
9566                 geometry_info.sigma=1.0;
9567             }
9568           if (attribute_flag[1] != 0)
9569             geometry_info.rho=argument_list[1].real_reference;
9570           if (attribute_flag[2] != 0)
9571             channel=(ChannelType) argument_list[2].integer_reference;
9572           image=RadialBlurImageChannel(image,channel,geometry_info.rho,
9573             exception);
9574           break;
9575         }
9576         case 83:  /* Thumbnail */
9577         {
9578           if (attribute_flag[0] != 0)
9579             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9580               &geometry,exception);
9581           if (attribute_flag[1] != 0)
9582             geometry.width=argument_list[1].integer_reference;
9583           if (attribute_flag[2] != 0)
9584             geometry.height=argument_list[2].integer_reference;
9585           image=ThumbnailImage(image,geometry.width,geometry.height,exception);
9586           break;
9587         }
9588         case 84:  /* Strip */
9589         {
9590           (void) StripImage(image);
9591           break;
9592         }
9593         case 85:  /* Tint */
9594         {
9595           PixelPacket
9596             target;
9597
9598           (void) GetOneVirtualPixel(image,0,0,&target,exception);
9599           if (attribute_flag[0] != 0)
9600             (void) QueryColorDatabase(argument_list[0].string_reference,&target,
9601               exception);
9602           if (attribute_flag[1] == 0)
9603             argument_list[1].string_reference="100";
9604           image=TintImage(image,argument_list[1].string_reference,target,
9605             exception);
9606           break;
9607         }
9608         case 86:  /* Channel */
9609         {
9610           if (attribute_flag[0] != 0)
9611             channel=(ChannelType) argument_list[0].integer_reference;
9612           (void) SeparateImageChannel(image,channel);
9613           break;
9614         }
9615         case 87:  /* Splice */
9616         {
9617           if (attribute_flag[0] != 0)
9618             flags=ParseGravityGeometry(image,argument_list[0].string_reference,
9619               &geometry,exception);
9620           if (attribute_flag[1] != 0)
9621             geometry.width=argument_list[1].integer_reference;
9622           if (attribute_flag[2] != 0)
9623             geometry.height=argument_list[2].integer_reference;
9624           if (attribute_flag[3] != 0)
9625             geometry.x=argument_list[3].integer_reference;
9626           if (attribute_flag[4] != 0)
9627             geometry.y=argument_list[4].integer_reference;
9628           if (attribute_flag[5] != 0)
9629             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9630               QuantumRange);
9631           if (attribute_flag[6] != 0)
9632             (void) QueryColorDatabase(argument_list[6].string_reference,
9633               &image->background_color,exception);
9634           if (attribute_flag[7] != 0)
9635             image->gravity=(GravityType) argument_list[7].integer_reference;
9636           image=SpliceImage(image,&geometry,exception);
9637           break;
9638         }
9639         case 88:  /* Posterize */
9640         {
9641           if (attribute_flag[0] == 0)
9642             argument_list[0].integer_reference=3;
9643           if (attribute_flag[1] == 0)
9644             argument_list[1].integer_reference=0;
9645           (void) PosterizeImage(image,argument_list[0].integer_reference,
9646             argument_list[1].integer_reference ? MagickTrue : MagickFalse);
9647           break;
9648         }
9649         case 89:  /* Shadow */
9650         {
9651           if (attribute_flag[0] != 0)
9652             {
9653               flags=ParseGeometry(argument_list[0].string_reference,
9654                 &geometry_info);
9655               if ((flags & SigmaValue) == 0)
9656                 geometry_info.sigma=1.0;
9657               if ((flags & XiValue) == 0)
9658                 geometry_info.xi=4.0;
9659               if ((flags & PsiValue) == 0)
9660                 geometry_info.psi=4.0;
9661             }
9662           if (attribute_flag[1] != 0)
9663             geometry_info.rho=argument_list[1].real_reference;
9664           if (attribute_flag[2] != 0)
9665             geometry_info.sigma=argument_list[2].real_reference;
9666           if (attribute_flag[3] != 0)
9667             geometry_info.xi=argument_list[3].integer_reference;
9668           if (attribute_flag[4] != 0)
9669             geometry_info.psi=argument_list[4].integer_reference;
9670           image=ShadowImage(image,geometry_info.rho,geometry_info.sigma,
9671             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9672             0.5),exception);
9673           break;
9674         }
9675         case 90:  /* Identify */
9676         {
9677           if (attribute_flag[0] == 0)
9678             argument_list[0].file_reference=(FILE *) NULL;
9679           if (attribute_flag[1] != 0)
9680             (void) SetImageArtifact(image,"identify:features",
9681               argument_list[1].string_reference);
9682           if ((attribute_flag[2] != 0) &&
9683               (argument_list[2].integer_reference != 0))
9684             (void) SetImageArtifact(image,"identify:unique","true");
9685           (void) IdentifyImage(image,argument_list[0].file_reference,
9686             MagickTrue);
9687           break;
9688         }
9689         case 91:  /* SepiaTone */
9690         {
9691           if (attribute_flag[0] == 0)
9692             argument_list[0].real_reference=80.0*QuantumRange/100.0;
9693           image=SepiaToneImage(image,argument_list[0].real_reference,
9694             exception);
9695           break;
9696         }
9697         case 92:  /* SigmoidalContrast */
9698         {
9699           MagickBooleanType
9700             sharpen;
9701
9702           if (attribute_flag[0] != 0)
9703             {
9704               flags=ParseGeometry(argument_list[0].string_reference,
9705                 &geometry_info);
9706               if ((flags & SigmaValue) == 0)
9707                 geometry_info.sigma=QuantumRange/2.0;
9708               if ((flags & PercentValue) != 0)
9709                 geometry_info.sigma=QuantumRange*geometry_info.sigma/100.0;
9710             }
9711           if (attribute_flag[1] != 0)
9712             geometry_info.rho=argument_list[1].real_reference;
9713           if (attribute_flag[2] != 0)
9714             geometry_info.sigma=argument_list[2].real_reference;
9715           if (attribute_flag[3] != 0)
9716             channel=(ChannelType) argument_list[3].integer_reference;
9717           sharpen=MagickTrue;
9718           if (attribute_flag[4] != 0)
9719             sharpen=argument_list[4].integer_reference != 0 ? MagickTrue :
9720               MagickFalse;
9721           (void) SigmoidalContrastImageChannel(image,channel,sharpen,
9722             geometry_info.rho,geometry_info.sigma);
9723           break;
9724         }
9725         case 93:  /* Extent */
9726         {
9727           if (attribute_flag[7] != 0)
9728             image->gravity=(GravityType) argument_list[7].integer_reference;
9729           if (attribute_flag[0] != 0)
9730             {
9731               int
9732                 flags;
9733
9734               flags=ParseGravityGeometry(image,
9735                 argument_list[0].string_reference,&geometry,exception);
9736               (void) flags;
9737               if (geometry.width == 0)
9738                 geometry.width=image->columns;
9739               if (geometry.height == 0)
9740                 geometry.height=image->rows;
9741             }
9742           if (attribute_flag[1] != 0)
9743             geometry.width=argument_list[1].integer_reference;
9744           if (attribute_flag[2] != 0)
9745             geometry.height=argument_list[2].integer_reference;
9746           if (attribute_flag[3] != 0)
9747             geometry.x=argument_list[3].integer_reference;
9748           if (attribute_flag[4] != 0)
9749             geometry.y=argument_list[4].integer_reference;
9750           if (attribute_flag[5] != 0)
9751             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
9752               QuantumRange);
9753           if (attribute_flag[6] != 0)
9754             (void) QueryColorDatabase(argument_list[6].string_reference,
9755               &image->background_color,exception);
9756           image=ExtentImage(image,&geometry,exception);
9757           break;
9758         }
9759         case 94:  /* Vignette */
9760         {
9761           if (attribute_flag[0] != 0)
9762             {
9763               flags=ParseGeometry(argument_list[0].string_reference,
9764                 &geometry_info);
9765               if ((flags & SigmaValue) == 0)
9766                 geometry_info.sigma=1.0;
9767               if ((flags & XiValue) == 0)
9768                 geometry_info.xi=0.1*image->columns;
9769               if ((flags & PsiValue) == 0)
9770                 geometry_info.psi=0.1*image->rows;
9771             }
9772           if (attribute_flag[1] != 0)
9773             geometry_info.rho=argument_list[1].real_reference;
9774           if (attribute_flag[2] != 0)
9775             geometry_info.sigma=argument_list[2].real_reference;
9776           if (attribute_flag[3] != 0)
9777             geometry_info.xi=argument_list[3].integer_reference;
9778           if (attribute_flag[4] != 0)
9779             geometry_info.psi=argument_list[4].integer_reference;
9780           if (attribute_flag[5] != 0)
9781             (void) QueryColorDatabase(argument_list[5].string_reference,
9782               &image->background_color,exception);
9783           image=VignetteImage(image,geometry_info.rho,geometry_info.sigma,
9784             (ssize_t) ceil(geometry_info.xi-0.5),(ssize_t) ceil(geometry_info.psi-
9785             0.5),exception);
9786           break;
9787         }
9788         case 95:  /* ContrastStretch */
9789         {
9790           double
9791             black_point,
9792             white_point;
9793
9794           black_point=0.0;
9795           white_point=(MagickRealType) image->columns*image->rows;
9796           if (attribute_flag[0] != 0)
9797             {
9798               flags=ParseGeometry(argument_list[0].string_reference,
9799                 &geometry_info);
9800               black_point=geometry_info.rho;
9801               white_point=(flags & SigmaValue) != 0 ? geometry_info.sigma :
9802                 black_point;
9803               if ((flags & PercentValue) != 0)
9804                 {
9805                   black_point*=(double) image->columns*image->rows/100.0;
9806                   white_point*=(double) image->columns*image->rows/100.0;
9807                 }
9808               white_point=(MagickRealType) image->columns*image->rows-
9809                 white_point;
9810             }
9811           if (attribute_flag[1] != 0)
9812             black_point=argument_list[1].real_reference;
9813           if (attribute_flag[2] != 0)
9814             white_point=argument_list[2].real_reference;
9815           if (attribute_flag[4] != 0)
9816             channel=(ChannelType) argument_list[4].integer_reference;
9817           (void) ContrastStretchImageChannel(image,channel,black_point,
9818             white_point);
9819           break;
9820         }
9821         case 96:  /* Sans0 */
9822         {
9823           break;
9824         }
9825         case 97:  /* Sans1 */
9826         {
9827           break;
9828         }
9829         case 98:  /* AdaptiveSharpen */
9830         {
9831           if (attribute_flag[0] != 0)
9832             {
9833               flags=ParseGeometry(argument_list[0].string_reference,
9834                 &geometry_info);
9835               if ((flags & SigmaValue) == 0)
9836                 geometry_info.sigma=1.0;
9837             }
9838           if (attribute_flag[1] != 0)
9839             geometry_info.rho=argument_list[1].real_reference;
9840           if (attribute_flag[2] != 0)
9841             geometry_info.sigma=argument_list[2].real_reference;
9842           if (attribute_flag[3] != 0)
9843             channel=(ChannelType) argument_list[3].integer_reference;
9844           image=AdaptiveSharpenImageChannel(image,channel,geometry_info.rho,
9845             geometry_info.sigma,exception);
9846           break;
9847         }
9848         case 99:  /* Transpose */
9849         {
9850           image=TransposeImage(image,exception);
9851           break;
9852         }
9853         case 100:  /* Tranverse */
9854         {
9855           image=TransverseImage(image,exception);
9856           break;
9857         }
9858         case 101:  /* AutoOrient */
9859         {
9860           switch (image->orientation)
9861           {
9862             case TopRightOrientation:
9863             {
9864               image=FlopImage(image,exception);
9865               break;
9866             }
9867             case BottomRightOrientation:
9868             {
9869               image=RotateImage(image,180.0,exception);
9870               break;
9871             }
9872             case BottomLeftOrientation:
9873             {
9874               image=FlipImage(image,exception);
9875               break;
9876             }
9877             case LeftTopOrientation:
9878             {
9879               image=TransposeImage(image,exception);
9880               break;
9881             }
9882             case RightTopOrientation:
9883             {
9884               image=RotateImage(image,90.0,exception);
9885               break;
9886             }
9887             case RightBottomOrientation:
9888             {
9889               image=TransverseImage(image,exception);
9890               break;
9891             }
9892             case LeftBottomOrientation:
9893             {
9894               image=RotateImage(image,270.0,exception);
9895               break;
9896             }
9897             default:
9898               break;
9899           }
9900           break;
9901         }
9902         case 102:  /* AdaptiveBlur */
9903         {
9904           if (attribute_flag[0] != 0)
9905             {
9906               flags=ParseGeometry(argument_list[0].string_reference,
9907                 &geometry_info);
9908               if ((flags & SigmaValue) == 0)
9909                 geometry_info.sigma=1.0;
9910             }
9911           if (attribute_flag[1] != 0)
9912             geometry_info.rho=argument_list[1].real_reference;
9913           if (attribute_flag[2] != 0)
9914             geometry_info.sigma=argument_list[2].real_reference;
9915           if (attribute_flag[3] != 0)
9916             channel=(ChannelType) argument_list[3].integer_reference;
9917           image=AdaptiveBlurImageChannel(image,channel,geometry_info.rho,
9918             geometry_info.sigma,exception);
9919           break;
9920         }
9921         case 103:  /* Sketch */
9922         {
9923           if (attribute_flag[0] != 0)
9924             {
9925               flags=ParseGeometry(argument_list[0].string_reference,
9926                 &geometry_info);
9927               if ((flags & SigmaValue) == 0)
9928                 geometry_info.sigma=1.0;
9929               if ((flags & XiValue) == 0)
9930                 geometry_info.xi=1.0;
9931             }
9932           if (attribute_flag[1] != 0)
9933             geometry_info.rho=argument_list[1].real_reference;
9934           if (attribute_flag[2] != 0)
9935             geometry_info.sigma=argument_list[2].real_reference;
9936           if (attribute_flag[3] != 0)
9937             geometry_info.xi=argument_list[3].real_reference;
9938           image=SketchImage(image,geometry_info.rho,geometry_info.sigma,
9939             geometry_info.xi,exception);
9940           break;
9941         }
9942         case 104:  /* UniqueColors */
9943         {
9944           image=UniqueImageColors(image,exception);
9945           break;
9946         }
9947         case 105:  /* AdaptiveResize */
9948         {
9949           if (attribute_flag[0] != 0)
9950             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
9951               &geometry,exception);
9952           if (attribute_flag[1] != 0)
9953             geometry.width=argument_list[1].integer_reference;
9954           if (attribute_flag[2] != 0)
9955             geometry.height=argument_list[2].integer_reference;
9956           if (attribute_flag[3] != 0)
9957             image->filter=(FilterTypes) argument_list[4].integer_reference;
9958           if (attribute_flag[4] != 0)
9959             SetImageArtifact(image,"filter:support",
9960               argument_list[4].string_reference);
9961           if (attribute_flag[5] != 0)
9962             image->blur=argument_list[5].real_reference;
9963           image=AdaptiveResizeImage(image,geometry.width,geometry.height,
9964             exception);
9965           break;
9966         }
9967         case 106:  /* ClipMask */
9968         {
9969           if (attribute_flag[0] == 0)
9970             {
9971               ThrowPerlException(exception,OptionError,"MaskImageRequired",
9972                 PackageName);
9973               goto PerlException;
9974             }
9975           image->clip_mask=CloneImage(argument_list[0].image_reference,0,0,
9976             MagickTrue,exception);
9977           (void) NegateImage(image->clip_mask,MagickFalse);
9978           break;
9979         }
9980         case 107:  /* LinearStretch */
9981         {
9982            double
9983              black_point,
9984              white_point;
9985
9986            black_point=0.0;
9987            white_point=(MagickRealType) image->columns*image->rows;
9988            if (attribute_flag[0] != 0)
9989              {
9990                flags=ParseGeometry(argument_list[0].string_reference,
9991                  &geometry_info);
9992                if ((flags & SigmaValue) != 0)
9993                   white_point=geometry_info.sigma;
9994                if ((flags & PercentValue) != 0)
9995                  {
9996                    black_point*=(double) image->columns*image->rows/100.0;
9997                    white_point*=(double) image->columns*image->rows/100.0;
9998                  }
9999                if ((flags & SigmaValue) == 0)
10000                  white_point=(double) image->columns*image->rows-black_point;
10001              }
10002           if (attribute_flag[1] != 0)
10003             black_point=argument_list[1].real_reference;
10004           if (attribute_flag[2] != 0)
10005             white_point=argument_list[2].real_reference;
10006           (void) LinearStretchImage(image,black_point,white_point);
10007           break;
10008         }
10009         case 109:  /* Mask */
10010         {
10011           if (attribute_flag[0] == 0)
10012             {
10013               ThrowPerlException(exception,OptionError,"MaskImageRequired",
10014                 PackageName);
10015               goto PerlException;
10016             }
10017           image->mask=CloneImage(argument_list[0].image_reference,0,0,
10018             MagickTrue,exception);
10019           (void) NegateImage(image->mask,MagickFalse);
10020           break;
10021         }
10022         case 110:  /* Polaroid */
10023         {
10024           DrawInfo
10025             *draw_info;
10026
10027           double
10028             angle;
10029
10030           draw_info=CloneDrawInfo(info ? info->image_info : (ImageInfo *) NULL,
10031             (DrawInfo *) NULL);
10032           if (attribute_flag[0] != 0)
10033             (void) SetImageProperty(image,"caption",InterpretImageProperties(
10034               info ? info->image_info : (ImageInfo *) NULL,image,
10035               argument_list[0].string_reference));
10036           angle=0.0;
10037           if (attribute_flag[1] != 0)
10038             angle=argument_list[1].real_reference;
10039           if (attribute_flag[2] != 0)
10040             (void) CloneString(&draw_info->font,
10041               argument_list[2].string_reference);
10042           if (attribute_flag[3] != 0)
10043             (void) QueryColorDatabase(argument_list[3].string_reference,
10044               &draw_info->stroke,exception);
10045           if (attribute_flag[4] != 0)
10046             (void) QueryColorDatabase(argument_list[4].string_reference,
10047               &draw_info->fill,exception);
10048           if (attribute_flag[5] != 0)
10049             draw_info->stroke_width=argument_list[5].real_reference;
10050           if (attribute_flag[6] != 0)
10051             draw_info->pointsize=argument_list[6].real_reference;
10052           if (attribute_flag[7] != 0)
10053             draw_info->gravity=(GravityType) argument_list[7].integer_reference;
10054           if (attribute_flag[8] != 0)
10055             (void) QueryColorDatabase(argument_list[8].string_reference,
10056               &image->background_color,exception);
10057           image=PolaroidImage(image,draw_info,angle,exception);
10058           draw_info=DestroyDrawInfo(draw_info);
10059           break;
10060         }
10061         case 111:  /* FloodfillPaint */
10062         {
10063           DrawInfo
10064             *draw_info;
10065
10066           MagickBooleanType
10067             invert;
10068
10069           PixelInfo
10070             target;
10071
10072           draw_info=CloneDrawInfo(info ? info->image_info :
10073             (ImageInfo *) NULL,(DrawInfo *) NULL);
10074           if (attribute_flag[0] != 0)
10075             flags=ParsePageGeometry(image,argument_list[0].string_reference,
10076               &geometry,exception);
10077           if (attribute_flag[1] != 0)
10078             geometry.x=argument_list[1].integer_reference;
10079           if (attribute_flag[2] != 0)
10080             geometry.y=argument_list[2].integer_reference;
10081           if (attribute_flag[3] != 0)
10082             (void) QueryColorDatabase(argument_list[3].string_reference,
10083               &draw_info->fill,exception);
10084           (void) GetOneVirtualMagickPixel(image,geometry.x,geometry.y,&target,
10085             exception);
10086           if (attribute_flag[4] != 0)
10087             QueryMagickColor(argument_list[4].string_reference,&target,
10088               exception);
10089           if (attribute_flag[5] != 0)
10090             image->fuzz=SiPrefixToDouble(argument_list[5].string_reference,
10091               QuantumRange);
10092           if (attribute_flag[6] != 0)
10093             channel=(ChannelType) argument_list[6].integer_reference;
10094           invert=MagickFalse;
10095           if (attribute_flag[7] != 0)
10096             invert=(MagickBooleanType) argument_list[7].integer_reference;
10097           (void) FloodfillPaintImage(image,channel,draw_info,&target,geometry.x,
10098             geometry.y,invert);
10099           draw_info=DestroyDrawInfo(draw_info);
10100           break;
10101         }
10102         case 112:  /* Distort */
10103         {
10104           AV
10105             *av;
10106
10107           double
10108             *coordinates;
10109
10110           DistortImageMethod
10111             method;
10112
10113           size_t
10114             number_coordinates;
10115
10116           VirtualPixelMethod
10117             virtual_pixel;
10118
10119           if (attribute_flag[0] == 0)
10120             break;
10121           method=UndefinedDistortion;
10122           if (attribute_flag[1] != 0)
10123             method=(DistortImageMethod) argument_list[1].integer_reference;
10124           av=(AV *) argument_list[0].array_reference;
10125           number_coordinates=(size_t) av_len(av)+1;
10126           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10127             sizeof(*coordinates));
10128           if (coordinates == (double *) NULL)
10129             {
10130               ThrowPerlException(exception,ResourceLimitFatalError,
10131                 "MemoryAllocationFailed",PackageName);
10132               goto PerlException;
10133             }
10134           for (j=0; j < (ssize_t) number_coordinates; j++)
10135             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10136           virtual_pixel=UndefinedVirtualPixelMethod;
10137           if (attribute_flag[2] != 0)
10138             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10139               argument_list[2].integer_reference);
10140           image=DistortImage(image,method,number_coordinates,coordinates,
10141             argument_list[3].integer_reference != 0 ? MagickTrue : MagickFalse,
10142             exception);
10143           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10144             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10145           coordinates=(double *) RelinquishMagickMemory(coordinates);
10146           break;
10147         }
10148         case 113:  /* Clut */
10149         {
10150           if (attribute_flag[0] == 0)
10151             {
10152               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10153                 PackageName);
10154               goto PerlException;
10155             }
10156           if (attribute_flag[1] != 0)
10157             channel=(ChannelType) argument_list[1].integer_reference;
10158           (void) ClutImageChannel(image,channel,
10159             argument_list[0].image_reference);
10160           break;
10161         }
10162         case 114:  /* LiquidRescale */
10163         {
10164           if (attribute_flag[0] != 0)
10165             flags=ParseRegionGeometry(image,argument_list[0].string_reference,
10166               &geometry,exception);
10167           if (attribute_flag[1] != 0)
10168             geometry.width=argument_list[1].integer_reference;
10169           if (attribute_flag[2] != 0)
10170             geometry.height=argument_list[2].integer_reference;
10171           if (attribute_flag[3] == 0)
10172             argument_list[3].real_reference=1.0;
10173           if (attribute_flag[4] == 0)
10174             argument_list[4].real_reference=0.0;
10175           image=LiquidRescaleImage(image,geometry.width,geometry.height,
10176             argument_list[3].real_reference,argument_list[4].real_reference,
10177             exception);
10178           break;
10179         }
10180         case 115:  /* EncipherImage */
10181         {
10182           (void) EncipherImage(image,argument_list[0].string_reference,
10183             exception);
10184           break;
10185         }
10186         case 116:  /* DecipherImage */
10187         {
10188           (void) DecipherImage(image,argument_list[0].string_reference,
10189             exception);
10190           break;
10191         }
10192         case 117:  /* Deskew */
10193         {
10194           geometry_info.rho=QuantumRange/2.0;
10195           if (attribute_flag[0] != 0)
10196             flags=ParseGeometry(argument_list[0].string_reference,
10197               &geometry_info);
10198           if (attribute_flag[1] != 0)
10199             geometry_info.rho=SiPrefixToDouble(
10200               argument_list[1].string_reference,QuantumRange);
10201           image=DeskewImage(image,geometry_info.rho,exception);
10202           break;
10203         }
10204         case 118:  /* Remap */
10205         {
10206           QuantizeInfo
10207             *quantize_info;
10208
10209           if (attribute_flag[0] == 0)
10210             {
10211               ThrowPerlException(exception,OptionError,"RemapImageRequired",
10212                 PackageName);
10213               goto PerlException;
10214             }
10215           quantize_info=AcquireQuantizeInfo(info->image_info);
10216           if (attribute_flag[1] != 0)
10217             quantize_info->dither=(MagickBooleanType)
10218               argument_list[1].integer_reference;
10219           if (attribute_flag[2] != 0)
10220             quantize_info->dither_method=(DitherMethod)
10221               argument_list[2].integer_reference;
10222           (void) RemapImages(quantize_info,image,
10223             argument_list[0].image_reference);
10224           quantize_info=DestroyQuantizeInfo(quantize_info);
10225           break;
10226         }
10227         case 119:  /* SparseColor */
10228         {
10229           AV
10230             *av;
10231
10232           double
10233             *coordinates;
10234
10235           SparseColorMethod
10236             method;
10237
10238           size_t
10239             number_coordinates;
10240
10241           VirtualPixelMethod
10242             virtual_pixel;
10243
10244           if (attribute_flag[0] == 0)
10245             break;
10246           method=UndefinedColorInterpolate;
10247           if (attribute_flag[1] != 0)
10248             method=(SparseColorMethod) argument_list[1].integer_reference;
10249           av=(AV *) argument_list[0].array_reference;
10250           number_coordinates=(size_t) av_len(av)+1;
10251           coordinates=(double *) AcquireQuantumMemory(number_coordinates,
10252             sizeof(*coordinates));
10253           if (coordinates == (double *) NULL)
10254             {
10255               ThrowPerlException(exception,ResourceLimitFatalError,
10256                 "MemoryAllocationFailed",PackageName);
10257               goto PerlException;
10258             }
10259           for (j=0; j < (ssize_t) number_coordinates; j++)
10260             coordinates[j]=(double) SvNV(*(av_fetch(av,j,0)));
10261           virtual_pixel=UndefinedVirtualPixelMethod;
10262           if (attribute_flag[2] != 0)
10263             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10264               argument_list[2].integer_reference);
10265           if (attribute_flag[3] != 0)
10266             channel=(ChannelType) argument_list[3].integer_reference;
10267           image=SparseColorImage(image,channel,method,number_coordinates,
10268             coordinates,exception);
10269           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10270             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10271           coordinates=(double *) RelinquishMagickMemory(coordinates);
10272           break;
10273         }
10274         case 120:  /* Function */
10275         {
10276           AV
10277             *av;
10278
10279           double
10280             *parameters;
10281
10282           MagickFunction
10283             function;
10284
10285           size_t
10286             number_parameters;
10287
10288           VirtualPixelMethod
10289             virtual_pixel;
10290
10291           if (attribute_flag[0] == 0)
10292             break;
10293           function=UndefinedFunction;
10294           if (attribute_flag[1] != 0)
10295             function=(MagickFunction) argument_list[1].integer_reference;
10296           av=(AV *) argument_list[0].array_reference;
10297           number_parameters=(size_t) av_len(av)+1;
10298           parameters=(double *) AcquireQuantumMemory(number_parameters,
10299             sizeof(*parameters));
10300           if (parameters == (double *) NULL)
10301             {
10302               ThrowPerlException(exception,ResourceLimitFatalError,
10303                 "MemoryAllocationFailed",PackageName);
10304               goto PerlException;
10305             }
10306           for (j=0; j < (ssize_t) number_parameters; j++)
10307             parameters[j]=(double) SvNV(*(av_fetch(av,j,0)));
10308           virtual_pixel=UndefinedVirtualPixelMethod;
10309           if (attribute_flag[2] != 0)
10310             virtual_pixel=SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
10311               argument_list[2].integer_reference);
10312           (void) FunctionImage(image,function,number_parameters,parameters,
10313             exception);
10314           if ((attribute_flag[2] != 0) && (image != (Image *) NULL))
10315             virtual_pixel=SetImageVirtualPixelMethod(image,virtual_pixel);
10316           parameters=(double *) RelinquishMagickMemory(parameters);
10317           break;
10318         }
10319         case 121:  /* SelectiveBlur */
10320         {
10321           if (attribute_flag[0] != 0)
10322             {
10323               flags=ParseGeometry(argument_list[0].string_reference,
10324                 &geometry_info);
10325               if ((flags & SigmaValue) == 0)
10326                 geometry_info.sigma=1.0;
10327               if ((flags & PercentValue) != 0)
10328                 geometry_info.xi=QuantumRange*geometry_info.xi/100.0;
10329             }
10330           if (attribute_flag[1] != 0)
10331             geometry_info.rho=argument_list[1].real_reference;
10332           if (attribute_flag[2] != 0)
10333             geometry_info.sigma=argument_list[2].real_reference;
10334           if (attribute_flag[3] != 0)
10335             geometry_info.xi=argument_list[3].integer_reference;;
10336           if (attribute_flag[4] != 0)
10337             channel=(ChannelType) argument_list[4].integer_reference;
10338           image=SelectiveBlurImageChannel(image,channel,geometry_info.rho,
10339             geometry_info.sigma,geometry_info.xi,exception);
10340           break;
10341         }
10342         case 122:  /* HaldClut */
10343         {
10344           if (attribute_flag[0] == 0)
10345             {
10346               ThrowPerlException(exception,OptionError,"ClutImageRequired",
10347                 PackageName);
10348               goto PerlException;
10349             }
10350           if (attribute_flag[1] != 0)
10351             channel=(ChannelType) argument_list[1].integer_reference;
10352           (void) HaldClutImageChannel(image,channel,
10353             argument_list[0].image_reference);
10354           break;
10355         }
10356         case 123:  /* BlueShift */
10357         {
10358           if (attribute_flag[0] != 0)
10359             (void) ParseGeometry(argument_list[0].string_reference,
10360               &geometry_info);
10361           image=BlueShiftImage(image,geometry_info.rho,exception);
10362           break;
10363         }
10364         case 124:  /* ForwardFourierTransformImage */
10365         {
10366           image=ForwardFourierTransformImage(image,
10367             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10368             exception);
10369           break;
10370         }
10371         case 125:  /* InverseFourierTransformImage */
10372         {
10373           image=InverseFourierTransformImage(image,image->next,
10374             argument_list[0].integer_reference != 0 ? MagickTrue : MagickFalse,
10375             exception);
10376           break;
10377         }
10378         case 126:  /* ColorDecisionList */
10379         {
10380           if (attribute_flag[0] == 0)
10381             argument_list[0].string_reference=(char *) NULL;
10382           (void) ColorDecisionListImage(image,
10383             argument_list[0].string_reference);
10384           break;
10385         }
10386         case 127:  /* AutoGamma */
10387         {
10388           if (attribute_flag[0] != 0)
10389             channel=(ChannelType) argument_list[0].integer_reference;
10390           (void) AutoGammaImageChannel(image,channel);
10391           break;
10392         }
10393         case 128:  /* AutoLevel */
10394         {
10395           if (attribute_flag[0] != 0)
10396             channel=(ChannelType) argument_list[0].integer_reference;
10397           (void) AutoLevelImageChannel(image,channel);
10398           break;
10399         }
10400         case 129:  /* LevelColors */
10401         {
10402           PixelInfo
10403             black_point,
10404             white_point;
10405
10406           (void) QueryMagickColor("#000000",&black_point,exception);
10407           (void) QueryMagickColor("#ffffff",&white_point,exception);
10408           if (attribute_flag[1] != 0)
10409              (void) QueryMagickColor(argument_list[1].string_reference,
10410                &black_point,exception);
10411           if (attribute_flag[2] != 0)
10412              (void) QueryMagickColor(argument_list[2].string_reference,
10413                &white_point,exception);
10414           if (attribute_flag[3] != 0)
10415             channel=(ChannelType) argument_list[3].integer_reference;
10416           (void) LevelColorsImageChannel(image,channel,&black_point,
10417             &white_point,argument_list[0].integer_reference != 0 ? MagickTrue :
10418             MagickFalse);
10419           break;
10420         }
10421         case 130:  /* Clamp */
10422         {
10423           if (attribute_flag[0] != 0)
10424             channel=(ChannelType) argument_list[0].integer_reference;
10425           (void) ClampImageChannel(image,channel);
10426           break;
10427         }
10428         case 131:  /* Filter */
10429         {
10430           KernelInfo
10431             *kernel;
10432
10433           if (attribute_flag[0] == 0)
10434             break;
10435           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10436           if (kernel == (KernelInfo *) NULL)
10437             break;
10438           if (attribute_flag[1] != 0)
10439             channel=(ChannelType) argument_list[1].integer_reference;
10440           if (attribute_flag[2] != 0)
10441             image->bias=SiPrefixToDouble(argument_list[2].string_reference,
10442               QuantumRange);
10443           image=FilterImageChannel(image,channel,kernel,exception);
10444           kernel=DestroyKernelInfo(kernel);
10445           break;
10446         }
10447         case 132:  /* BrightnessContrast */
10448         {
10449           double
10450             brightness,
10451             contrast;
10452
10453           brightness=0.0;
10454           contrast=0.0;
10455           if (attribute_flag[0] != 0)
10456             {
10457               flags=ParseGeometry(argument_list[0].string_reference,
10458                 &geometry_info);
10459               brightness=geometry_info.rho;
10460               if ((flags & SigmaValue) == 0)
10461                 contrast=geometry_info.sigma;
10462             }
10463           if (attribute_flag[1] != 0)
10464             brightness=argument_list[1].real_reference;
10465           if (attribute_flag[2] != 0)
10466             contrast=argument_list[2].real_reference;
10467           if (attribute_flag[4] != 0)
10468             channel=(ChannelType) argument_list[4].integer_reference;
10469           (void) BrightnessContrastImageChannel(image,channel,brightness,
10470             contrast);
10471           break;
10472         }
10473         case 133:  /* Morphology */
10474         {
10475           KernelInfo
10476             *kernel;
10477
10478           MorphologyMethod
10479             method;
10480
10481           ssize_t
10482             iterations;
10483
10484           if (attribute_flag[0] == 0)
10485             break;
10486           kernel=AcquireKernelInfo(argument_list[0].string_reference);
10487           if (kernel == (KernelInfo *) NULL)
10488             break;
10489           if (attribute_flag[1] != 0)
10490             channel=(ChannelType) argument_list[1].integer_reference;
10491           method=UndefinedMorphology;
10492           if (attribute_flag[2] != 0)
10493             method=argument_list[2].integer_reference;
10494           iterations=1;
10495           if (attribute_flag[3] != 0)
10496             iterations=argument_list[4].integer_reference;
10497           image=MorphologyImageChannel(image,channel,method,iterations,kernel,
10498             exception);
10499           kernel=DestroyKernelInfo(kernel);
10500           break;
10501         }
10502         case 108:  /* Recolor */
10503         case 134:  /* ColorMatrix */
10504         {
10505           AV
10506             *av;
10507
10508           double
10509             *color_matrix;
10510
10511           KernelInfo
10512             *kernel_info;
10513
10514           size_t
10515             order;
10516
10517           if (attribute_flag[0] == 0)
10518             break;
10519           av=(AV *) argument_list[0].array_reference;
10520           order=(size_t) sqrt(av_len(av)+1);
10521           color_matrix=(double *) AcquireQuantumMemory(order,order*
10522             sizeof(*color_matrix));
10523           if (color_matrix == (double *) NULL)
10524             {
10525               ThrowPerlException(exception,ResourceLimitFatalError,
10526                 "MemoryAllocationFailed",PackageName);
10527               goto PerlException;
10528            }
10529           for (j=0; (j < (ssize_t) (order*order)) && (j < (av_len(av)+1)); j++)
10530             color_matrix[j]=(double) SvNV(*(av_fetch(av,j,0)));
10531           for ( ; j < (ssize_t) (order*order); j++)
10532             color_matrix[j]=0.0;
10533           kernel_info=AcquireKernelInfo("1");
10534           if (kernel_info == (KernelInfo *) NULL)
10535             break;
10536           kernel_info->width=order;
10537           kernel_info->height=order;
10538           kernel_info->values=color_matrix;
10539           image=ColorMatrixImage(image,kernel_info,exception);
10540           kernel_info->values=(double *) NULL;
10541           kernel_info=DestroyKernelInfo(kernel_info);
10542           color_matrix=(double *) RelinquishMagickMemory(color_matrix);
10543           break;
10544         }
10545         case 135:  /* Color */
10546         {
10547           PixelInfo
10548             color;
10549
10550           (void) QueryMagickColor("none",&color,exception);
10551           if (attribute_flag[0] != 0)
10552             (void) QueryMagickColor(argument_list[0].string_reference,
10553               &color,exception);
10554           (void) SetImageColor(image,&color);
10555           break;
10556         }
10557         case 136:  /* Mode */
10558         {
10559           if (attribute_flag[0] != 0)
10560             {
10561               flags=ParseGeometry(argument_list[0].string_reference,
10562                 &geometry_info);
10563               if ((flags & SigmaValue) == 0)
10564                 geometry_info.sigma=1.0;
10565             }
10566           if (attribute_flag[1] != 0)
10567             geometry_info.rho=argument_list[1].real_reference;
10568           if (attribute_flag[2] != 0)
10569             geometry_info.sigma=argument_list[2].real_reference;
10570           if (attribute_flag[3] != 0)
10571             channel=(ChannelType) argument_list[3].integer_reference;
10572           image=StatisticImageChannel(image,channel,ModeStatistic,
10573             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10574           break;
10575         }
10576         case 137:  /* Statistic */
10577         {
10578           StatisticType
10579             statistic;
10580
10581           statistic=UndefinedStatistic;
10582           if (attribute_flag[0] != 0)
10583             {
10584               flags=ParseGeometry(argument_list[0].string_reference,
10585                 &geometry_info);
10586               if ((flags & SigmaValue) == 0)
10587                 geometry_info.sigma=1.0;
10588             }
10589           if (attribute_flag[1] != 0)
10590             geometry_info.rho=argument_list[1].real_reference;
10591           if (attribute_flag[2] != 0)
10592             geometry_info.sigma=argument_list[2].real_reference;
10593           if (attribute_flag[3] != 0)
10594             channel=(ChannelType) argument_list[3].integer_reference;
10595           if (attribute_flag[4] != 0)
10596             statistic=(StatisticType) argument_list[4].integer_reference;
10597           image=StatisticImageChannel(image,channel,statistic,
10598             (size_t) geometry_info.rho,(size_t) geometry_info.sigma,exception);
10599           break;
10600         }
10601       }
10602       if (next != (Image *) NULL)
10603         (void) CatchImageException(next);
10604       if (region_image != (Image *) NULL)
10605         {
10606           /*
10607             Composite region.
10608           */
10609           status=CompositeImage(region_image,CopyCompositeOp,image,
10610             region_info.x,region_info.y);
10611           (void) status;
10612           (void) CatchImageException(region_image);
10613           image=DestroyImage(image);
10614           image=region_image;
10615         }
10616       if (image != (Image *) NULL)
10617         {
10618           number_images++;
10619           if (next && (next != image))
10620             {
10621               image->next=next->next;
10622               DeleteImageFromRegistry(*pv,next);
10623             }
10624           sv_setiv(*pv,(IV) image);
10625           next=image;
10626         }
10627       if (*pv)
10628         pv++;
10629     }
10630
10631   PerlException:
10632     if (reference_vector)
10633       reference_vector=(SV **) RelinquishMagickMemory(reference_vector);
10634     InheritPerlException(exception,perl_exception);
10635     exception=DestroyExceptionInfo(exception);
10636     sv_setiv(perl_exception,(IV) number_images);
10637     SvPOK_on(perl_exception);
10638     ST(0)=sv_2mortal(perl_exception);
10639     XSRETURN(1);
10640   }
10641 \f
10642 #
10643 ###############################################################################
10644 #                                                                             #
10645 #                                                                             #
10646 #                                                                             #
10647 #   M o n t a g e                                                             #
10648 #                                                                             #
10649 #                                                                             #
10650 #                                                                             #
10651 ###############################################################################
10652 #
10653 #
10654 void
10655 Montage(ref,...)
10656   Image::Magick ref=NO_INIT
10657   ALIAS:
10658     MontageImage  = 1
10659     montage       = 2
10660     montageimage  = 3
10661   PPCODE:
10662   {
10663     AV
10664       *av;
10665
10666     char
10667       *attribute;
10668
10669     ExceptionInfo
10670       *exception;
10671
10672     HV
10673       *hv;
10674
10675     Image
10676       *image,
10677       *next;
10678
10679     PixelInfo
10680       transparent_color;
10681
10682     MontageInfo
10683       *montage_info;
10684
10685     register ssize_t
10686       i;
10687
10688     ssize_t
10689       sp;
10690
10691     struct PackageInfo
10692       *info;
10693
10694     SV
10695       *av_reference,
10696       *perl_exception,
10697       *reference,
10698       *rv,
10699       *sv;
10700
10701     PERL_UNUSED_VAR(ref);
10702     PERL_UNUSED_VAR(ix);
10703     exception=AcquireExceptionInfo();
10704     perl_exception=newSVpv("",0);
10705     sv=NULL;
10706     attribute=NULL;
10707     if (sv_isobject(ST(0)) == 0)
10708       {
10709         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
10710           PackageName);
10711         goto PerlException;
10712       }
10713     reference=SvRV(ST(0));
10714     hv=SvSTASH(reference);
10715     av=newAV();
10716     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
10717     SvREFCNT_dec(av);
10718     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
10719     if (image == (Image *) NULL)
10720       {
10721         ThrowPerlException(exception,OptionError,"NoImagesDefined",
10722           PackageName);
10723         goto PerlException;
10724       }
10725     /*
10726       Get options.
10727     */
10728     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
10729     montage_info=CloneMontageInfo(info->image_info,(MontageInfo *) NULL);
10730     (void) QueryMagickColor("none",&transparent_color,exception);
10731     for (i=2; i < items; i+=2)
10732     {
10733       attribute=(char *) SvPV(ST(i-1),na);
10734       switch (*attribute)
10735       {
10736         case 'B':
10737         case 'b':
10738         {
10739           if (LocaleCompare(attribute,"background") == 0)
10740             {
10741               (void) QueryColorDatabase(SvPV(ST(i),na),
10742                 &montage_info->background_color,exception);
10743               for (next=image; next; next=next->next)
10744                 next->background_color=montage_info->background_color;
10745               break;
10746             }
10747           if (LocaleCompare(attribute,"border") == 0)
10748             {
10749               montage_info->border_width=SvIV(ST(i));
10750               break;
10751             }
10752           if (LocaleCompare(attribute,"bordercolor") == 0)
10753             {
10754               (void) QueryColorDatabase(SvPV(ST(i),na),
10755                 &montage_info->border_color,exception);
10756               for (next=image; next; next=next->next)
10757                 next->border_color=montage_info->border_color;
10758               break;
10759             }
10760           if (LocaleCompare(attribute,"borderwidth") == 0)
10761             {
10762               montage_info->border_width=SvIV(ST(i));
10763               break;
10764             }
10765           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10766             attribute);
10767           break;
10768         }
10769         case 'C':
10770         case 'c':
10771         {
10772           if (LocaleCompare(attribute,"compose") == 0)
10773             {
10774               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10775                 MagickComposeOptions,MagickFalse,SvPV(ST(i),na));
10776               if (sp < 0)
10777                 {
10778                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10779                     SvPV(ST(i),na));
10780                   break;
10781                 }
10782               for (next=image; next; next=next->next)
10783                 next->compose=(CompositeOperator) sp;
10784               break;
10785             }
10786           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10787             attribute);
10788           break;
10789         }
10790         case 'F':
10791         case 'f':
10792         {
10793           if (LocaleCompare(attribute,"fill") == 0)
10794             {
10795               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->fill,
10796                 exception);
10797               break;
10798             }
10799           if (LocaleCompare(attribute,"font") == 0)
10800             {
10801               (void) CloneString(&montage_info->font,SvPV(ST(i),na));
10802               break;
10803             }
10804           if (LocaleCompare(attribute,"frame") == 0)
10805             {
10806               char
10807                 *p;
10808
10809               p=SvPV(ST(i),na);
10810               if (IsGeometry(p) == MagickFalse)
10811                 {
10812                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10813                     p);
10814                   break;
10815                 }
10816               (void) CloneString(&montage_info->frame,p);
10817               if (*p == '\0')
10818                 montage_info->frame=(char *) NULL;
10819               break;
10820             }
10821           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10822             attribute);
10823           break;
10824         }
10825         case 'G':
10826         case 'g':
10827         {
10828           if (LocaleCompare(attribute,"geometry") == 0)
10829             {
10830               char
10831                 *p;
10832
10833               p=SvPV(ST(i),na);
10834               if (IsGeometry(p) == MagickFalse)
10835                 {
10836                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10837                     p);
10838                   break;
10839                 }
10840              (void) CloneString(&montage_info->geometry,p);
10841              if (*p == '\0')
10842                montage_info->geometry=(char *) NULL;
10843              break;
10844            }
10845          if (LocaleCompare(attribute,"gravity") == 0)
10846            {
10847              ssize_t
10848                in;
10849
10850              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10851                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
10852              if (in < 0)
10853                {
10854                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
10855                    SvPV(ST(i),na));
10856                  return;
10857                }
10858              montage_info->gravity=(GravityType) in;
10859              for (next=image; next; next=next->next)
10860                next->gravity=(GravityType) in;
10861              break;
10862            }
10863           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10864             attribute);
10865           break;
10866         }
10867         case 'L':
10868         case 'l':
10869         {
10870           if (LocaleCompare(attribute,"label") == 0)
10871             {
10872               for (next=image; next; next=next->next)
10873                 (void) SetImageProperty(next,"label",InterpretImageProperties(
10874                   info ? info->image_info : (ImageInfo *) NULL,next,
10875                   SvPV(ST(i),na)));
10876               break;
10877             }
10878           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10879             attribute);
10880           break;
10881         }
10882         case 'M':
10883         case 'm':
10884         {
10885           if (LocaleCompare(attribute,"mattecolor") == 0)
10886             {
10887               (void) QueryColorDatabase(SvPV(ST(i),na),
10888                 &montage_info->matte_color,exception);
10889               for (next=image; next; next=next->next)
10890                 next->matte_color=montage_info->matte_color;
10891               break;
10892             }
10893           if (LocaleCompare(attribute,"mode") == 0)
10894             {
10895               ssize_t
10896                 in;
10897
10898               in=!SvPOK(ST(i)) ? SvIV(ST(i)) :
10899                 ParseCommandOption(MagickModeOptions,MagickFalse,SvPV(ST(i),na));
10900               switch (in)
10901               {
10902                 default:
10903                 {
10904                   ThrowPerlException(exception,OptionError,
10905                     "UnrecognizedModeType",SvPV(ST(i),na));
10906                   break;
10907                 }
10908                 case FrameMode:
10909                 {
10910                   (void) CloneString(&montage_info->frame,"15x15+3+3");
10911                   montage_info->shadow=MagickTrue;
10912                   break;
10913                 }
10914                 case UnframeMode:
10915                 {
10916                   montage_info->frame=(char *) NULL;
10917                   montage_info->shadow=MagickFalse;
10918                   montage_info->border_width=0;
10919                   break;
10920                 }
10921                 case ConcatenateMode:
10922                 {
10923                   montage_info->frame=(char *) NULL;
10924                   montage_info->shadow=MagickFalse;
10925                   (void) CloneString(&montage_info->geometry,"+0+0");
10926                   montage_info->border_width=0;
10927                 }
10928               }
10929               break;
10930             }
10931           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10932             attribute);
10933           break;
10934         }
10935         case 'P':
10936         case 'p':
10937         {
10938           if (LocaleCompare(attribute,"pointsize") == 0)
10939             {
10940               montage_info->pointsize=SvIV(ST(i));
10941               break;
10942             }
10943           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10944             attribute);
10945           break;
10946         }
10947         case 'S':
10948         case 's':
10949         {
10950           if (LocaleCompare(attribute,"shadow") == 0)
10951             {
10952               sp=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
10953                 MagickBooleanOptions,MagickFalse,SvPV(ST(i),na));
10954               if (sp < 0)
10955                 {
10956                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
10957                     SvPV(ST(i),na));
10958                   break;
10959                 }
10960              montage_info->shadow=sp != 0 ? MagickTrue : MagickFalse;
10961              break;
10962             }
10963           if (LocaleCompare(attribute,"stroke") == 0)
10964             {
10965               (void) QueryColorDatabase(SvPV(ST(i),na),&montage_info->stroke,
10966                 exception);
10967               break;
10968             }
10969           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
10970             attribute);
10971           break;
10972         }
10973         case 'T':
10974         case 't':
10975         {
10976           if (LocaleCompare(attribute,"texture") == 0)
10977             {
10978               (void) CloneString(&montage_info->texture,SvPV(ST(i),na));
10979               break;
10980             }
10981           if (LocaleCompare(attribute,"tile") == 0)
10982             {
10983               char *p=SvPV(ST(i),na);
10984               if (IsGeometry(p) == MagickFalse)
10985                 {
10986                   ThrowPerlException(exception,OptionError,"MissingGeometry",
10987                     p);
10988                   break;
10989                 }
10990               (void) CloneString(&montage_info->tile,p);
10991               if (*p == '\0')
10992                 montage_info->tile=(char *) NULL;
10993               break;
10994             }
10995           if (LocaleCompare(attribute,"title") == 0)
10996             {
10997               (void) CloneString(&montage_info->title,SvPV(ST(i),na));
10998               break;
10999             }
11000           if (LocaleCompare(attribute,"transparent") == 0)
11001             {
11002               PixelInfo
11003                 transparent_color;
11004
11005               QueryMagickColor(SvPV(ST(i),na),&transparent_color,exception);
11006               for (next=image; next; next=next->next)
11007                 (void) TransparentPaintImage(next,&transparent_color,
11008                   TransparentAlpha,MagickFalse);
11009               break;
11010             }
11011           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11012             attribute);
11013           break;
11014         }
11015         default:
11016         {
11017           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11018             attribute);
11019           break;
11020         }
11021       }
11022     }
11023     image=MontageImageList(info->image_info,montage_info,image,exception);
11024     montage_info=DestroyMontageInfo(montage_info);
11025     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11026       goto PerlException;
11027     if (transparent_color.alpha != TransparentAlpha)
11028       for (next=image; next; next=next->next)
11029         (void) TransparentPaintImage(next,&transparent_color,
11030           TransparentAlpha,MagickFalse);
11031     for (  ; image; image=image->next)
11032     {
11033       AddImageToRegistry(sv,image);
11034       rv=newRV(sv);
11035       av_push(av,sv_bless(rv,hv));
11036       SvREFCNT_dec(sv);
11037     }
11038     exception=DestroyExceptionInfo(exception);
11039     ST(0)=av_reference;
11040     SvREFCNT_dec(perl_exception);
11041     XSRETURN(1);
11042
11043   PerlException:
11044     InheritPerlException(exception,perl_exception);
11045     exception=DestroyExceptionInfo(exception);
11046     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11047     SvPOK_on(perl_exception);
11048     ST(0)=sv_2mortal(perl_exception);
11049     XSRETURN(1);
11050   }
11051 \f
11052 #
11053 ###############################################################################
11054 #                                                                             #
11055 #                                                                             #
11056 #                                                                             #
11057 #   M o r p h                                                                 #
11058 #                                                                             #
11059 #                                                                             #
11060 #                                                                             #
11061 ###############################################################################
11062 #
11063 #
11064 void
11065 Morph(ref,...)
11066   Image::Magick ref=NO_INIT
11067   ALIAS:
11068     MorphImage  = 1
11069     morph       = 2
11070     morphimage  = 3
11071   PPCODE:
11072   {
11073     AV
11074       *av;
11075
11076     char
11077       *attribute;
11078
11079     ExceptionInfo
11080       *exception;
11081
11082     HV
11083       *hv;
11084
11085     Image
11086       *image;
11087
11088     register ssize_t
11089       i;
11090
11091     ssize_t
11092       number_frames;
11093
11094     struct PackageInfo
11095       *info;
11096
11097     SV
11098       *av_reference,
11099       *perl_exception,
11100       *reference,
11101       *rv,
11102       *sv;
11103
11104     PERL_UNUSED_VAR(ref);
11105     PERL_UNUSED_VAR(ix);
11106     exception=AcquireExceptionInfo();
11107     perl_exception=newSVpv("",0);
11108     sv=NULL;
11109     av=NULL;
11110     attribute=NULL;
11111     if (sv_isobject(ST(0)) == 0)
11112       {
11113         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11114           PackageName);
11115         goto PerlException;
11116       }
11117     reference=SvRV(ST(0));
11118     hv=SvSTASH(reference);
11119     av=newAV();
11120     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11121     SvREFCNT_dec(av);
11122     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11123     if (image == (Image *) NULL)
11124       {
11125         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11126           PackageName);
11127         goto PerlException;
11128       }
11129     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11130     /*
11131       Get attribute.
11132     */
11133     number_frames=30;
11134     for (i=2; i < items; i+=2)
11135     {
11136       attribute=(char *) SvPV(ST(i-1),na);
11137       switch (*attribute)
11138       {
11139         case 'F':
11140         case 'f':
11141         {
11142           if (LocaleCompare(attribute,"frames") == 0)
11143             {
11144               number_frames=SvIV(ST(i));
11145               break;
11146             }
11147           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11148             attribute);
11149           break;
11150         }
11151         default:
11152         {
11153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11154             attribute);
11155           break;
11156         }
11157       }
11158     }
11159     image=MorphImages(image,number_frames,exception);
11160     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11161       goto PerlException;
11162     for ( ; image; image=image->next)
11163     {
11164       AddImageToRegistry(sv,image);
11165       rv=newRV(sv);
11166       av_push(av,sv_bless(rv,hv));
11167       SvREFCNT_dec(sv);
11168     }
11169     exception=DestroyExceptionInfo(exception);
11170     ST(0)=av_reference;
11171     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11172     XSRETURN(1);
11173
11174   PerlException:
11175     InheritPerlException(exception,perl_exception);
11176     exception=DestroyExceptionInfo(exception);
11177     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11178     SvPOK_on(perl_exception);
11179     ST(0)=sv_2mortal(perl_exception);
11180     XSRETURN(1);
11181   }
11182 \f
11183 #
11184 ###############################################################################
11185 #                                                                             #
11186 #                                                                             #
11187 #                                                                             #
11188 #   M o s a i c                                                               #
11189 #                                                                             #
11190 #                                                                             #
11191 #                                                                             #
11192 ###############################################################################
11193 #
11194 #
11195 void
11196 Mosaic(ref)
11197   Image::Magick ref=NO_INIT
11198   ALIAS:
11199     MosaicImage   = 1
11200     mosaic        = 2
11201     mosaicimage   = 3
11202   PPCODE:
11203   {
11204     AV
11205       *av;
11206
11207     ExceptionInfo
11208       *exception;
11209
11210     HV
11211       *hv;
11212
11213     Image
11214       *image;
11215
11216     struct PackageInfo
11217       *info;
11218
11219     SV
11220       *perl_exception,
11221       *reference,
11222       *rv,
11223       *sv;
11224
11225     PERL_UNUSED_VAR(ref);
11226     PERL_UNUSED_VAR(ix);
11227     exception=AcquireExceptionInfo();
11228     perl_exception=newSVpv("",0);
11229     sv=NULL;
11230     if (sv_isobject(ST(0)) == 0)
11231       {
11232         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11233           PackageName);
11234         goto PerlException;
11235       }
11236     reference=SvRV(ST(0));
11237     hv=SvSTASH(reference);
11238     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11239     if (image == (Image *) NULL)
11240       {
11241         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11242           PackageName);
11243         goto PerlException;
11244       }
11245     image=MergeImageLayers(image,MosaicLayer,exception);
11246     /*
11247       Create blessed Perl array for the returned image.
11248     */
11249     av=newAV();
11250     ST(0)=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11251     SvREFCNT_dec(av);
11252     AddImageToRegistry(sv,image);
11253     rv=newRV(sv);
11254     av_push(av,sv_bless(rv,hv));
11255     SvREFCNT_dec(sv);
11256     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11257     (void) CopyMagickString(image->filename,info->image_info->filename,
11258       MaxTextExtent);
11259     SetImageInfo(info->image_info,0,&image->exception);
11260     exception=DestroyExceptionInfo(exception);
11261     SvREFCNT_dec(perl_exception);
11262     XSRETURN(1);
11263
11264   PerlException:
11265     InheritPerlException(exception,perl_exception);
11266     exception=DestroyExceptionInfo(exception);
11267     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11268     SvPOK_on(perl_exception);  /* return messages in string context */
11269     ST(0)=sv_2mortal(perl_exception);
11270     XSRETURN(1);
11271   }
11272 \f
11273 #
11274 ###############################################################################
11275 #                                                                             #
11276 #                                                                             #
11277 #                                                                             #
11278 #   P i n g                                                                   #
11279 #                                                                             #
11280 #                                                                             #
11281 #                                                                             #
11282 ###############################################################################
11283 #
11284 #
11285 void
11286 Ping(ref,...)
11287   Image::Magick ref=NO_INIT
11288   ALIAS:
11289     PingImage  = 1
11290     ping       = 2
11291     pingimage  = 3
11292   PPCODE:
11293   {
11294     AV
11295       *av;
11296
11297     char
11298       **keep,
11299       **list;
11300
11301     ExceptionInfo
11302       *exception;
11303
11304     Image
11305       *image,
11306       *next;
11307
11308     int
11309       n;
11310
11311     MagickBooleanType
11312       status;
11313
11314     register char
11315       **p;
11316
11317     register ssize_t
11318       i;
11319
11320     ssize_t
11321       ac;
11322
11323     STRLEN
11324       *length;
11325
11326     struct PackageInfo
11327       *info,
11328       *package_info;
11329
11330     SV
11331       *perl_exception,
11332       *reference;
11333
11334     size_t
11335       count;
11336
11337     PERL_UNUSED_VAR(ref);
11338     PERL_UNUSED_VAR(ix);
11339     exception=AcquireExceptionInfo();
11340     perl_exception=newSVpv("",0);
11341     package_info=(struct PackageInfo *) NULL;
11342     ac=(items < 2) ? 1 : items-1;
11343     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
11344     keep=list;
11345     length=(STRLEN *) NULL;
11346     if (list == (char **) NULL)
11347       {
11348         ThrowPerlException(exception,ResourceLimitError,
11349           "MemoryAllocationFailed",PackageName);
11350         goto PerlException;
11351       }
11352     keep=list;
11353     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
11354     if (length == (STRLEN *) NULL)
11355       {
11356         ThrowPerlException(exception,ResourceLimitError,
11357           "MemoryAllocationFailed",PackageName);
11358         goto PerlException;
11359       }
11360     if (sv_isobject(ST(0)) == 0)
11361       {
11362         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11363           PackageName);
11364         goto PerlException;
11365       }
11366     reference=SvRV(ST(0));
11367     if (SvTYPE(reference) != SVt_PVAV)
11368       {
11369         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11370           PackageName);
11371         goto PerlException;
11372       }
11373     av=(AV *) reference;
11374     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11375       exception);
11376     package_info=ClonePackageInfo(info,exception);
11377     n=1;
11378     if (items <= 1)
11379       *list=(char *) (*package_info->image_info->filename ?
11380         package_info->image_info->filename : "XC:black");
11381     else
11382       for (n=0, i=0; i < ac; i++)
11383       {
11384         list[n]=(char *) SvPV(ST(i+1),length[n]);
11385         if ((items >= 3) && strEQcase(list[n],"blob"))
11386           {
11387             void
11388               *blob;
11389
11390             i++;
11391             blob=(void *) (SvPV(ST(i+1),length[n]));
11392             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
11393           }
11394         if ((items >= 3) && strEQcase(list[n],"filename"))
11395           continue;
11396         if ((items >= 3) && strEQcase(list[n],"file"))
11397           {
11398             FILE
11399               *file;
11400
11401             PerlIO
11402               *io_info;
11403
11404             i++;
11405             io_info=IoIFP(sv_2io(ST(i+1)));
11406             if (io_info == (PerlIO *) NULL)
11407               {
11408                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11409                   PackageName);
11410                 continue;
11411               }
11412             file=PerlIO_findFILE(io_info);
11413             if (file == (FILE *) NULL)
11414               {
11415                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
11416                   PackageName);
11417                 continue;
11418               }
11419             SetImageInfoFile(package_info->image_info,file);
11420           }
11421         if ((items >= 3) && strEQcase(list[n],"magick"))
11422           continue;
11423         n++;
11424       }
11425     list[n]=(char *) NULL;
11426     keep=list;
11427     status=ExpandFilenames(&n,&list);
11428     if (status == MagickFalse)
11429       {
11430         ThrowPerlException(exception,ResourceLimitError,
11431           "MemoryAllocationFailed",PackageName);
11432         goto PerlException;
11433       }
11434     count=0;
11435     for (i=0; i < n; i++)
11436     {
11437       (void) CopyMagickString(package_info->image_info->filename,list[i],
11438         MaxTextExtent);
11439       image=PingImage(package_info->image_info,exception);
11440       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
11441         break;
11442       if ((package_info->image_info->file != (FILE *) NULL) ||
11443           (package_info->image_info->blob != (void *) NULL))
11444         DisassociateImageStream(image);
11445       count+=GetImageListLength(image);
11446       EXTEND(sp,4*count);
11447       for (next=image; next; next=next->next)
11448       {
11449         PUSHs(sv_2mortal(newSViv(next->columns)));
11450         PUSHs(sv_2mortal(newSViv(next->rows)));
11451         PUSHs(sv_2mortal(newSViv((size_t) GetBlobSize(next))));
11452         PUSHs(sv_2mortal(newSVpv(next->magick,0)));
11453       }
11454       image=DestroyImageList(image);
11455     }
11456     /*
11457       Free resources.
11458     */
11459     for (i=0; i < n; i++)
11460       if (list[i] != (char *) NULL)
11461         for (p=keep; list[i] != *p++; )
11462           if (*p == NULL)
11463             {
11464               list[i]=(char *) RelinquishMagickMemory(list[i]);
11465               break;
11466             }
11467
11468   PerlException:
11469     if (package_info != (struct PackageInfo *) NULL)
11470       DestroyPackageInfo(package_info);
11471     if (list && (list != keep))
11472       list=(char **) RelinquishMagickMemory(list);
11473     if (keep)
11474       keep=(char **) RelinquishMagickMemory(keep);
11475     if (length)
11476       length=(STRLEN *) RelinquishMagickMemory(length);
11477     InheritPerlException(exception,perl_exception);
11478     exception=DestroyExceptionInfo(exception);
11479     SvREFCNT_dec(perl_exception);  /* throw away all errors */
11480   }
11481 \f
11482 #
11483 ###############################################################################
11484 #                                                                             #
11485 #                                                                             #
11486 #                                                                             #
11487 #   P r e v i e w                                                             #
11488 #                                                                             #
11489 #                                                                             #
11490 #                                                                             #
11491 ###############################################################################
11492 #
11493 #
11494 void
11495 Preview(ref,...)
11496   Image::Magick ref=NO_INIT
11497   ALIAS:
11498     PreviewImage = 1
11499     preview      = 2
11500     previewimage = 3
11501   PPCODE:
11502   {
11503     AV
11504       *av;
11505
11506     ExceptionInfo
11507       *exception;
11508
11509     HV
11510       *hv;
11511
11512     Image
11513       *image,
11514       *preview_image;
11515
11516     PreviewType
11517       preview_type;
11518
11519     struct PackageInfo
11520       *info;
11521
11522     SV
11523       *av_reference,
11524       *perl_exception,
11525       *reference,
11526       *rv,
11527       *sv;
11528
11529     PERL_UNUSED_VAR(ref);
11530     PERL_UNUSED_VAR(ix);
11531     exception=AcquireExceptionInfo();
11532     perl_exception=newSVpv("",0);
11533     sv=NULL;
11534     av=NULL;
11535     if (sv_isobject(ST(0)) == 0)
11536       {
11537         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
11538           PackageName);
11539         goto PerlException;
11540       }
11541     reference=SvRV(ST(0));
11542     hv=SvSTASH(reference);
11543     av=newAV();
11544     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
11545     SvREFCNT_dec(av);
11546     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11547     if (image == (Image *) NULL)
11548       {
11549         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11550           PackageName);
11551         goto PerlException;
11552       }
11553     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
11554     preview_type=GammaPreview;
11555     if (items > 1)
11556       preview_type=(PreviewType)
11557         ParseCommandOption(MagickPreviewOptions,MagickFalse,SvPV(ST(1),na));
11558     for ( ; image; image=image->next)
11559     {
11560       preview_image=PreviewImage(image,preview_type,exception);
11561       if (preview_image == (Image *) NULL)
11562         goto PerlException;
11563       AddImageToRegistry(sv,preview_image);
11564       rv=newRV(sv);
11565       av_push(av,sv_bless(rv,hv));
11566       SvREFCNT_dec(sv);
11567     }
11568     exception=DestroyExceptionInfo(exception);
11569     ST(0)=av_reference;
11570     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
11571     XSRETURN(1);
11572
11573   PerlException:
11574     InheritPerlException(exception,perl_exception);
11575     exception=DestroyExceptionInfo(exception);
11576     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
11577     SvPOK_on(perl_exception);
11578     ST(0)=sv_2mortal(perl_exception);
11579     XSRETURN(1);
11580   }
11581 \f
11582 #
11583 ###############################################################################
11584 #                                                                             #
11585 #                                                                             #
11586 #                                                                             #
11587 #   Q u e r y C o l o r                                                       #
11588 #                                                                             #
11589 #                                                                             #
11590 #                                                                             #
11591 ###############################################################################
11592 #
11593 #
11594 void
11595 QueryColor(ref,...)
11596   Image::Magick ref=NO_INIT
11597   ALIAS:
11598     querycolor = 1
11599   PPCODE:
11600   {
11601     char
11602       *name;
11603
11604     ExceptionInfo
11605       *exception;
11606
11607     PixelInfo
11608       color;
11609
11610     register ssize_t
11611       i;
11612
11613     SV
11614       *perl_exception;
11615
11616     PERL_UNUSED_VAR(ref);
11617     PERL_UNUSED_VAR(ix);
11618     exception=AcquireExceptionInfo();
11619     perl_exception=newSVpv("",0);
11620     if (items == 1)
11621       {
11622         const ColorInfo
11623           **colorlist;
11624
11625         size_t
11626           colors;
11627
11628         colorlist=GetColorInfoList("*",&colors,exception);
11629         EXTEND(sp,colors);
11630         for (i=0; i < (ssize_t) colors; i++)
11631         {
11632           PUSHs(sv_2mortal(newSVpv(colorlist[i]->name,0)));
11633         }
11634         colorlist=(const ColorInfo **)
11635           RelinquishMagickMemory((ColorInfo **) colorlist);
11636         goto PerlException;
11637       }
11638     EXTEND(sp,5*items);
11639     for (i=1; i < items; i++)
11640     {
11641       name=(char *) SvPV(ST(i),na);
11642       if (QueryMagickColor(name,&color,exception) == MagickFalse)
11643         {
11644           PUSHs(&sv_undef);
11645           continue;
11646         }
11647       PUSHs(sv_2mortal(newSViv((size_t) floor(color.red+0.5))));
11648       PUSHs(sv_2mortal(newSViv((size_t) floor(color.green+0.5))));
11649       PUSHs(sv_2mortal(newSViv((size_t) floor(color.blue+0.5))));
11650       if (color.colorspace == CMYKColorspace)
11651         PUSHs(sv_2mortal(newSViv((size_t) floor(color.black+0.5))));
11652       if (color.matte != MagickFalse)
11653         PUSHs(sv_2mortal(newSViv((size_t) floor(color.alpha+0.5))));
11654     }
11655
11656   PerlException:
11657     InheritPerlException(exception,perl_exception);
11658     exception=DestroyExceptionInfo(exception);
11659     SvREFCNT_dec(perl_exception);
11660   }
11661 \f
11662 #
11663 ###############################################################################
11664 #                                                                             #
11665 #                                                                             #
11666 #                                                                             #
11667 #   Q u e r y C o l o r N a m e                                               #
11668 #                                                                             #
11669 #                                                                             #
11670 #                                                                             #
11671 ###############################################################################
11672 #
11673 #
11674 void
11675 QueryColorname(ref,...)
11676   Image::Magick ref=NO_INIT
11677   ALIAS:
11678     querycolorname = 1
11679   PPCODE:
11680   {
11681     AV
11682       *av;
11683
11684     char
11685       message[MaxTextExtent];
11686
11687     ExceptionInfo
11688       *exception;
11689
11690     Image
11691       *image;
11692
11693     PixelPacket
11694       target_color;
11695
11696     register ssize_t
11697       i;
11698
11699     struct PackageInfo
11700       *info;
11701
11702     SV
11703       *perl_exception,
11704       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11705
11706     PERL_UNUSED_VAR(ref);
11707     PERL_UNUSED_VAR(ix);
11708     exception=AcquireExceptionInfo();
11709     perl_exception=newSVpv("",0);
11710     reference=SvRV(ST(0));
11711     av=(AV *) reference;
11712     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11713       exception);
11714     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11715     if (image == (Image *) NULL)
11716       {
11717         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11718           PackageName);
11719         goto PerlException;
11720       }
11721     EXTEND(sp,items);
11722     for (i=1; i < items; i++)
11723     {
11724       (void) QueryColorDatabase(SvPV(ST(i),na),&target_color,exception);
11725       (void) QueryColorname(image,&target_color,SVGCompliance,message,
11726         exception);
11727       PUSHs(sv_2mortal(newSVpv(message,0)));
11728     }
11729
11730   PerlException:
11731     InheritPerlException(exception,perl_exception);
11732     exception=DestroyExceptionInfo(exception);
11733     SvREFCNT_dec(perl_exception);
11734   }
11735 \f
11736 #
11737 ###############################################################################
11738 #                                                                             #
11739 #                                                                             #
11740 #                                                                             #
11741 #   Q u e r y F o n t                                                         #
11742 #                                                                             #
11743 #                                                                             #
11744 #                                                                             #
11745 ###############################################################################
11746 #
11747 #
11748 void
11749 QueryFont(ref,...)
11750   Image::Magick ref=NO_INIT
11751   ALIAS:
11752     queryfont = 1
11753   PPCODE:
11754   {
11755     char
11756       *name,
11757       message[MaxTextExtent];
11758
11759     ExceptionInfo
11760       *exception;
11761
11762     register ssize_t
11763       i;
11764
11765     SV
11766       *perl_exception;
11767
11768     volatile const TypeInfo
11769       *type_info;
11770
11771     PERL_UNUSED_VAR(ref);
11772     PERL_UNUSED_VAR(ix);
11773     exception=AcquireExceptionInfo();
11774     perl_exception=newSVpv("",0);
11775     if (items == 1)
11776       {
11777         const TypeInfo
11778           **typelist;
11779
11780         size_t
11781           types;
11782
11783         typelist=GetTypeInfoList("*",&types,exception);
11784         EXTEND(sp,types);
11785         for (i=0; i < (ssize_t) types; i++)
11786         {
11787           PUSHs(sv_2mortal(newSVpv(typelist[i]->name,0)));
11788         }
11789         typelist=(const TypeInfo **) RelinquishMagickMemory((TypeInfo **)
11790           typelist);
11791         goto PerlException;
11792       }
11793     EXTEND(sp,10*items);
11794     for (i=1; i < items; i++)
11795     {
11796       name=(char *) SvPV(ST(i),na);
11797       type_info=GetTypeInfo(name,exception);
11798       if (type_info == (TypeInfo *) NULL)
11799         {
11800           PUSHs(&sv_undef);
11801           continue;
11802         }
11803       if (type_info->name == (char *) NULL)
11804         PUSHs(&sv_undef);
11805       else
11806         PUSHs(sv_2mortal(newSVpv(type_info->name,0)));
11807       if (type_info->description == (char *) NULL)
11808         PUSHs(&sv_undef);
11809       else
11810         PUSHs(sv_2mortal(newSVpv(type_info->description,0)));
11811       if (type_info->family == (char *) NULL)
11812         PUSHs(&sv_undef);
11813       else
11814         PUSHs(sv_2mortal(newSVpv(type_info->family,0)));
11815       if (type_info->style == UndefinedStyle)
11816         PUSHs(&sv_undef);
11817       else
11818         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStyleOptions,
11819           type_info->style),0)));
11820       if (type_info->stretch == UndefinedStretch)
11821         PUSHs(&sv_undef);
11822       else
11823         PUSHs(sv_2mortal(newSVpv(CommandOptionToMnemonic(MagickStretchOptions,
11824           type_info->stretch),0)));
11825       (void) FormatLocaleString(message,MaxTextExtent,"%.20g",(double)
11826         type_info->weight);
11827       PUSHs(sv_2mortal(newSVpv(message,0)));
11828       if (type_info->encoding == (char *) NULL)
11829         PUSHs(&sv_undef);
11830       else
11831         PUSHs(sv_2mortal(newSVpv(type_info->encoding,0)));
11832       if (type_info->foundry == (char *) NULL)
11833         PUSHs(&sv_undef);
11834       else
11835         PUSHs(sv_2mortal(newSVpv(type_info->foundry,0)));
11836       if (type_info->format == (char *) NULL)
11837         PUSHs(&sv_undef);
11838       else
11839         PUSHs(sv_2mortal(newSVpv(type_info->format,0)));
11840       if (type_info->metrics == (char *) NULL)
11841         PUSHs(&sv_undef);
11842       else
11843         PUSHs(sv_2mortal(newSVpv(type_info->metrics,0)));
11844       if (type_info->glyphs == (char *) NULL)
11845         PUSHs(&sv_undef);
11846       else
11847         PUSHs(sv_2mortal(newSVpv(type_info->glyphs,0)));
11848     }
11849
11850   PerlException:
11851     InheritPerlException(exception,perl_exception);
11852     exception=DestroyExceptionInfo(exception);
11853     SvREFCNT_dec(perl_exception);
11854   }
11855 \f
11856 #
11857 ###############################################################################
11858 #                                                                             #
11859 #                                                                             #
11860 #                                                                             #
11861 #   Q u e r y F o n t M e t r i c s                                           #
11862 #                                                                             #
11863 #                                                                             #
11864 #                                                                             #
11865 ###############################################################################
11866 #
11867 #
11868 void
11869 QueryFontMetrics(ref,...)
11870   Image::Magick ref=NO_INIT
11871   ALIAS:
11872     queryfontmetrics = 1
11873   PPCODE:
11874   {
11875     AffineMatrix
11876       affine,
11877       current;
11878
11879     AV
11880       *av;
11881
11882     char
11883       *attribute;
11884
11885     double
11886       x,
11887       y;
11888
11889     DrawInfo
11890       *draw_info;
11891
11892     ExceptionInfo
11893       *exception;
11894
11895     GeometryInfo
11896       geometry_info;
11897
11898     Image
11899       *image;
11900
11901     MagickBooleanType
11902       status;
11903
11904     MagickStatusType
11905       flags;
11906
11907     register ssize_t
11908       i;
11909
11910     ssize_t
11911       type;
11912
11913     struct PackageInfo
11914       *info,
11915       *package_info;
11916
11917     SV
11918       *perl_exception,
11919       *reference;  /* reference is the SV* of ref=SvIV(reference) */
11920
11921     TypeMetric
11922       metrics;
11923
11924     PERL_UNUSED_VAR(ref);
11925     PERL_UNUSED_VAR(ix);
11926     exception=AcquireExceptionInfo();
11927     package_info=(struct PackageInfo *) NULL;
11928     perl_exception=newSVpv("",0);
11929     reference=SvRV(ST(0));
11930     av=(AV *) reference;
11931     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
11932       exception);
11933     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
11934     if (image == (Image *) NULL)
11935       {
11936         ThrowPerlException(exception,OptionError,"NoImagesDefined",
11937           PackageName);
11938         goto PerlException;
11939       }
11940     package_info=ClonePackageInfo(info,exception);
11941     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
11942     CloneString(&draw_info->text,"");
11943     current=draw_info->affine;
11944     GetAffineMatrix(&affine);
11945     x=0.0;
11946     y=0.0;
11947     EXTEND(sp,7*items);
11948     for (i=2; i < items; i+=2)
11949     {
11950       attribute=(char *) SvPV(ST(i-1),na);
11951       switch (*attribute)
11952       {
11953         case 'A':
11954         case 'a':
11955         {
11956           if (LocaleCompare(attribute,"antialias") == 0)
11957             {
11958               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
11959                 SvPV(ST(i),na));
11960               if (type < 0)
11961                 {
11962                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
11963                     SvPV(ST(i),na));
11964                   break;
11965                 }
11966               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
11967               break;
11968             }
11969           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11970             attribute);
11971           break;
11972         }
11973         case 'd':
11974         case 'D':
11975         {
11976           if (LocaleCompare(attribute,"density") == 0)
11977             {
11978               CloneString(&draw_info->density,SvPV(ST(i),na));
11979               break;
11980             }
11981           if (LocaleCompare(attribute,"direction") == 0)
11982             {
11983               draw_info->direction=(DirectionType) ParseCommandOption(
11984                 MagickDirectionOptions,MagickFalse,SvPV(ST(i),na));
11985               break;
11986             }
11987           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
11988             attribute);
11989           break;
11990         }
11991         case 'e':
11992         case 'E':
11993         {
11994           if (LocaleCompare(attribute,"encoding") == 0)
11995             {
11996               CloneString(&draw_info->encoding,SvPV(ST(i),na));
11997               break;
11998             }
11999           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12000             attribute);
12001           break;
12002         }
12003         case 'f':
12004         case 'F':
12005         {
12006           if (LocaleCompare(attribute,"family") == 0)
12007             {
12008               CloneString(&draw_info->family,SvPV(ST(i),na));
12009               break;
12010             }
12011           if (LocaleCompare(attribute,"fill") == 0)
12012             {
12013               if (info)
12014                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12015                   &image->exception);
12016               break;
12017             }
12018           if (LocaleCompare(attribute,"font") == 0)
12019             {
12020               CloneString(&draw_info->font,SvPV(ST(i),na));
12021               break;
12022             }
12023           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12024             attribute);
12025           break;
12026         }
12027         case 'g':
12028         case 'G':
12029         {
12030           if (LocaleCompare(attribute,"geometry") == 0)
12031             {
12032               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12033               break;
12034             }
12035           if (LocaleCompare(attribute,"gravity") == 0)
12036             {
12037               draw_info->gravity=(GravityType) ParseCommandOption(
12038                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12039               break;
12040             }
12041           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12042             attribute);
12043           break;
12044         }
12045         case 'i':
12046         case 'I':
12047         {
12048           if (LocaleCompare(attribute,"interline-spacing") == 0)
12049             {
12050               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12051               draw_info->interline_spacing=geometry_info.rho;
12052               break;
12053             }
12054           if (LocaleCompare(attribute,"interword-spacing") == 0)
12055             {
12056               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12057               draw_info->interword_spacing=geometry_info.rho;
12058               break;
12059             }
12060           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12061             attribute);
12062           break;
12063         }
12064         case 'k':
12065         case 'K':
12066         {
12067           if (LocaleCompare(attribute,"kerning") == 0)
12068             {
12069               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12070               draw_info->kerning=geometry_info.rho;
12071               break;
12072             }
12073           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12074             attribute);
12075           break;
12076         }
12077         case 'p':
12078         case 'P':
12079         {
12080           if (LocaleCompare(attribute,"pointsize") == 0)
12081             {
12082               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12083               draw_info->pointsize=geometry_info.rho;
12084               break;
12085             }
12086           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12087             attribute);
12088           break;
12089         }
12090         case 'r':
12091         case 'R':
12092         {
12093           if (LocaleCompare(attribute,"rotate") == 0)
12094             {
12095               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12096               affine.rx=geometry_info.rho;
12097               affine.ry=geometry_info.sigma;
12098               if ((flags & SigmaValue) == 0)
12099                 affine.ry=affine.rx;
12100               break;
12101             }
12102           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12103             attribute);
12104           break;
12105         }
12106         case 's':
12107         case 'S':
12108         {
12109           if (LocaleCompare(attribute,"scale") == 0)
12110             {
12111               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12112               affine.sx=geometry_info.rho;
12113               affine.sy=geometry_info.sigma;
12114               if ((flags & SigmaValue) == 0)
12115                 affine.sy=affine.sx;
12116               break;
12117             }
12118           if (LocaleCompare(attribute,"skew") == 0)
12119             {
12120               double
12121                 x_angle,
12122                 y_angle;
12123
12124               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12125               x_angle=geometry_info.rho;
12126               y_angle=geometry_info.sigma;
12127               if ((flags & SigmaValue) == 0)
12128                 y_angle=x_angle;
12129               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12130               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12131               break;
12132             }
12133           if (LocaleCompare(attribute,"stroke") == 0)
12134             {
12135               if (info)
12136                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12137                   &image->exception);
12138               break;
12139             }
12140           if (LocaleCompare(attribute,"style") == 0)
12141             {
12142               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12143                 SvPV(ST(i),na));
12144               if (type < 0)
12145                 {
12146                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12147                     SvPV(ST(i),na));
12148                   break;
12149                 }
12150               draw_info->style=(StyleType) type;
12151               break;
12152             }
12153           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12154             attribute);
12155           break;
12156         }
12157         case 't':
12158         case 'T':
12159         {
12160           if (LocaleCompare(attribute,"text") == 0)
12161             {
12162               CloneString(&draw_info->text,SvPV(ST(i),na));
12163               break;
12164             }
12165           if (LocaleCompare(attribute,"translate") == 0)
12166             {
12167               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12168               affine.tx=geometry_info.rho;
12169               affine.ty=geometry_info.sigma;
12170               if ((flags & SigmaValue) == 0)
12171                 affine.ty=affine.tx;
12172               break;
12173             }
12174           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12175             attribute);
12176           break;
12177         }
12178         case 'w':
12179         case 'W':
12180         {
12181           if (LocaleCompare(attribute,"weight") == 0)
12182             {
12183               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12184               draw_info->weight=(size_t) geometry_info.rho;
12185               break;
12186             }
12187           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12188             attribute);
12189           break;
12190         }
12191         case 'x':
12192         case 'X':
12193         {
12194           if (LocaleCompare(attribute,"x") == 0)
12195             {
12196               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12197               x=geometry_info.rho;
12198               break;
12199             }
12200           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12201             attribute);
12202           break;
12203         }
12204         case 'y':
12205         case 'Y':
12206         {
12207           if (LocaleCompare(attribute,"y") == 0)
12208             {
12209               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12210               y=geometry_info.rho;
12211               break;
12212             }
12213           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12214             attribute);
12215           break;
12216         }
12217         default:
12218         {
12219           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12220             attribute);
12221           break;
12222         }
12223       }
12224     }
12225     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12226     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12227     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12228     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12229     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12230     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12231     if (draw_info->geometry == (char *) NULL)
12232       {
12233         draw_info->geometry=AcquireString((char *) NULL);
12234         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12235           "%.15g,%.15g",x,y);
12236       }
12237     status=GetTypeMetrics(image,draw_info,&metrics);
12238     (void) CatchImageException(image);
12239     if (status == MagickFalse)
12240       PUSHs(&sv_undef);
12241     else
12242       {
12243         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12244         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12245         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12246         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12247         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12248         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12249         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12250         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12251         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12252         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12253         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12254         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12255         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12256       }
12257     draw_info=DestroyDrawInfo(draw_info);
12258
12259   PerlException:
12260     if (package_info != (struct PackageInfo *) NULL)
12261       DestroyPackageInfo(package_info);
12262     InheritPerlException(exception,perl_exception);
12263     exception=DestroyExceptionInfo(exception);
12264     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12265   }
12266 \f
12267 #
12268 ###############################################################################
12269 #                                                                             #
12270 #                                                                             #
12271 #                                                                             #
12272 #   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                         #
12273 #                                                                             #
12274 #                                                                             #
12275 #                                                                             #
12276 ###############################################################################
12277 #
12278 #
12279 void
12280 QueryMultilineFontMetrics(ref,...)
12281   Image::Magick ref=NO_INIT
12282   ALIAS:
12283     querymultilinefontmetrics = 1
12284   PPCODE:
12285   {
12286     AffineMatrix
12287       affine,
12288       current;
12289
12290     AV
12291       *av;
12292
12293     char
12294       *attribute;
12295
12296     double
12297       x,
12298       y;
12299
12300     DrawInfo
12301       *draw_info;
12302
12303     ExceptionInfo
12304       *exception;
12305
12306     GeometryInfo
12307       geometry_info;
12308
12309     Image
12310       *image;
12311
12312     MagickBooleanType
12313       status;
12314
12315     MagickStatusType
12316       flags;
12317
12318     register ssize_t
12319       i;
12320
12321     ssize_t
12322       type;
12323
12324     struct PackageInfo
12325       *info,
12326       *package_info;
12327
12328     SV
12329       *perl_exception,
12330       *reference;  /* reference is the SV* of ref=SvIV(reference) */
12331
12332     TypeMetric
12333       metrics;
12334
12335     PERL_UNUSED_VAR(ref);
12336     PERL_UNUSED_VAR(ix);
12337     exception=AcquireExceptionInfo();
12338     package_info=(struct PackageInfo *) NULL;
12339     perl_exception=newSVpv("",0);
12340     reference=SvRV(ST(0));
12341     av=(AV *) reference;
12342     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12343       exception);
12344     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
12345     if (image == (Image *) NULL)
12346       {
12347         ThrowPerlException(exception,OptionError,"NoImagesDefined",
12348           PackageName);
12349         goto PerlException;
12350       }
12351     package_info=ClonePackageInfo(info,exception);
12352     draw_info=CloneDrawInfo(package_info->image_info,(DrawInfo *) NULL);
12353     CloneString(&draw_info->text,"");
12354     current=draw_info->affine;
12355     GetAffineMatrix(&affine);
12356     x=0.0;
12357     y=0.0;
12358     EXTEND(sp,7*items);
12359     for (i=2; i < items; i+=2)
12360     {
12361       attribute=(char *) SvPV(ST(i-1),na);
12362       switch (*attribute)
12363       {
12364         case 'A':
12365         case 'a':
12366         {
12367           if (LocaleCompare(attribute,"antialias") == 0)
12368             {
12369               type=ParseCommandOption(MagickBooleanOptions,MagickFalse,
12370                 SvPV(ST(i),na));
12371               if (type < 0)
12372                 {
12373                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12374                     SvPV(ST(i),na));
12375                   break;
12376                 }
12377               draw_info->text_antialias=type != 0 ? MagickTrue : MagickFalse;
12378               break;
12379             }
12380           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12381             attribute);
12382           break;
12383         }
12384         case 'd':
12385         case 'D':
12386         {
12387           if (LocaleCompare(attribute,"density") == 0)
12388             {
12389               CloneString(&draw_info->density,SvPV(ST(i),na));
12390               break;
12391             }
12392           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12393             attribute);
12394           break;
12395         }
12396         case 'e':
12397         case 'E':
12398         {
12399           if (LocaleCompare(attribute,"encoding") == 0)
12400             {
12401               CloneString(&draw_info->encoding,SvPV(ST(i),na));
12402               break;
12403             }
12404           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12405             attribute);
12406           break;
12407         }
12408         case 'f':
12409         case 'F':
12410         {
12411           if (LocaleCompare(attribute,"family") == 0)
12412             {
12413               CloneString(&draw_info->family,SvPV(ST(i),na));
12414               break;
12415             }
12416           if (LocaleCompare(attribute,"fill") == 0)
12417             {
12418               if (info)
12419                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->fill,
12420                   &image->exception);
12421               break;
12422             }
12423           if (LocaleCompare(attribute,"font") == 0)
12424             {
12425               CloneString(&draw_info->font,SvPV(ST(i),na));
12426               break;
12427             }
12428           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12429             attribute);
12430           break;
12431         }
12432         case 'g':
12433         case 'G':
12434         {
12435           if (LocaleCompare(attribute,"geometry") == 0)
12436             {
12437               CloneString(&draw_info->geometry,SvPV(ST(i),na));
12438               break;
12439             }
12440           if (LocaleCompare(attribute,"gravity") == 0)
12441             {
12442               draw_info->gravity=(GravityType) ParseCommandOption(
12443                 MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
12444               break;
12445             }
12446           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12447             attribute);
12448           break;
12449         }
12450         case 'p':
12451         case 'P':
12452         {
12453           if (LocaleCompare(attribute,"pointsize") == 0)
12454             {
12455               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12456               draw_info->pointsize=geometry_info.rho;
12457               break;
12458             }
12459           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12460             attribute);
12461           break;
12462         }
12463         case 'r':
12464         case 'R':
12465         {
12466           if (LocaleCompare(attribute,"rotate") == 0)
12467             {
12468               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12469               affine.rx=geometry_info.rho;
12470               affine.ry=geometry_info.sigma;
12471               if ((flags & SigmaValue) == 0)
12472                 affine.ry=affine.rx;
12473               break;
12474             }
12475           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12476             attribute);
12477           break;
12478         }
12479         case 's':
12480         case 'S':
12481         {
12482           if (LocaleCompare(attribute,"scale") == 0)
12483             {
12484               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12485               affine.sx=geometry_info.rho;
12486               affine.sy=geometry_info.sigma;
12487               if ((flags & SigmaValue) == 0)
12488                 affine.sy=affine.sx;
12489               break;
12490             }
12491           if (LocaleCompare(attribute,"skew") == 0)
12492             {
12493               double
12494                 x_angle,
12495                 y_angle;
12496
12497               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12498               x_angle=geometry_info.rho;
12499               y_angle=geometry_info.sigma;
12500               if ((flags & SigmaValue) == 0)
12501                 y_angle=x_angle;
12502               affine.ry=tan(DegreesToRadians(fmod(x_angle,360.0)));
12503               affine.rx=tan(DegreesToRadians(fmod(y_angle,360.0)));
12504               break;
12505             }
12506           if (LocaleCompare(attribute,"stroke") == 0)
12507             {
12508               if (info)
12509                 (void) QueryColorDatabase(SvPV(ST(i),na),&draw_info->stroke,
12510                   &image->exception);
12511               break;
12512             }
12513           if (LocaleCompare(attribute,"style") == 0)
12514             {
12515               type=ParseCommandOption(MagickStyleOptions,MagickFalse,
12516                 SvPV(ST(i),na));
12517               if (type < 0)
12518                 {
12519                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
12520                     SvPV(ST(i),na));
12521                   break;
12522                 }
12523               draw_info->style=(StyleType) type;
12524               break;
12525             }
12526           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12527             attribute);
12528           break;
12529         }
12530         case 't':
12531         case 'T':
12532         {
12533           if (LocaleCompare(attribute,"text") == 0)
12534             {
12535               CloneString(&draw_info->text,SvPV(ST(i),na));
12536               break;
12537             }
12538           if (LocaleCompare(attribute,"translate") == 0)
12539             {
12540               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12541               affine.tx=geometry_info.rho;
12542               affine.ty=geometry_info.sigma;
12543               if ((flags & SigmaValue) == 0)
12544                 affine.ty=affine.tx;
12545               break;
12546             }
12547           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12548             attribute);
12549           break;
12550         }
12551         case 'w':
12552         case 'W':
12553         {
12554           if (LocaleCompare(attribute,"weight") == 0)
12555             {
12556               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12557               draw_info->weight=(size_t) geometry_info.rho;
12558               break;
12559             }
12560           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12561             attribute);
12562           break;
12563         }
12564         case 'x':
12565         case 'X':
12566         {
12567           if (LocaleCompare(attribute,"x") == 0)
12568             {
12569               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12570               x=geometry_info.rho;
12571               break;
12572             }
12573           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12574             attribute);
12575           break;
12576         }
12577         case 'y':
12578         case 'Y':
12579         {
12580           if (LocaleCompare(attribute,"y") == 0)
12581             {
12582               flags=ParseGeometry(SvPV(ST(i),na),&geometry_info);
12583               y=geometry_info.rho;
12584               break;
12585             }
12586           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12587             attribute);
12588           break;
12589         }
12590         default:
12591         {
12592           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
12593             attribute);
12594           break;
12595         }
12596       }
12597     }
12598     draw_info->affine.sx=current.sx*affine.sx+current.ry*affine.rx;
12599     draw_info->affine.rx=current.rx*affine.sx+current.sy*affine.rx;
12600     draw_info->affine.ry=current.sx*affine.ry+current.ry*affine.sy;
12601     draw_info->affine.sy=current.rx*affine.ry+current.sy*affine.sy;
12602     draw_info->affine.tx=current.sx*affine.tx+current.ry*affine.ty+current.tx;
12603     draw_info->affine.ty=current.rx*affine.tx+current.sy*affine.ty+current.ty;
12604     if (draw_info->geometry == (char *) NULL)
12605       {
12606         draw_info->geometry=AcquireString((char *) NULL);
12607         (void) FormatLocaleString(draw_info->geometry,MaxTextExtent,
12608           "%.15g,%.15g",x,y);
12609       }
12610     status=GetMultilineTypeMetrics(image,draw_info,&metrics);
12611     (void) CatchImageException(image);
12612     if (status == MagickFalse)
12613       PUSHs(&sv_undef);
12614     else
12615       {
12616         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.x)));
12617         PUSHs(sv_2mortal(newSVnv(metrics.pixels_per_em.y)));
12618         PUSHs(sv_2mortal(newSVnv(metrics.ascent)));
12619         PUSHs(sv_2mortal(newSVnv(metrics.descent)));
12620         PUSHs(sv_2mortal(newSVnv(metrics.width)));
12621         PUSHs(sv_2mortal(newSVnv(metrics.height)));
12622         PUSHs(sv_2mortal(newSVnv(metrics.max_advance)));
12623         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x1)));
12624         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y1)));
12625         PUSHs(sv_2mortal(newSVnv(metrics.bounds.x2)));
12626         PUSHs(sv_2mortal(newSVnv(metrics.bounds.y2)));
12627         PUSHs(sv_2mortal(newSVnv(metrics.origin.x)));
12628         PUSHs(sv_2mortal(newSVnv(metrics.origin.y)));
12629       }
12630     draw_info=DestroyDrawInfo(draw_info);
12631
12632   PerlException:
12633     if (package_info != (struct PackageInfo *) NULL)
12634       DestroyPackageInfo(package_info);
12635     InheritPerlException(exception,perl_exception);
12636     exception=DestroyExceptionInfo(exception);
12637     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
12638   }
12639 \f
12640 #
12641 ###############################################################################
12642 #                                                                             #
12643 #                                                                             #
12644 #                                                                             #
12645 #   Q u e r y F o r m a t                                                     #
12646 #                                                                             #
12647 #                                                                             #
12648 #                                                                             #
12649 ###############################################################################
12650 #
12651 #
12652 void
12653 QueryFormat(ref,...)
12654   Image::Magick ref=NO_INIT
12655   ALIAS:
12656     queryformat = 1
12657   PPCODE:
12658   {
12659     char
12660       *name;
12661
12662     ExceptionInfo
12663       *exception;
12664
12665     register ssize_t
12666       i;
12667
12668     SV
12669       *perl_exception;
12670
12671     volatile const MagickInfo
12672       *magick_info;
12673
12674     PERL_UNUSED_VAR(ref);
12675     PERL_UNUSED_VAR(ix);
12676     exception=AcquireExceptionInfo();
12677     perl_exception=newSVpv("",0);
12678     if (items == 1)
12679       {
12680         char
12681           format[MaxTextExtent];
12682
12683         const MagickInfo
12684           **format_list;
12685
12686         size_t
12687           types;
12688
12689         format_list=GetMagickInfoList("*",&types,exception);
12690         EXTEND(sp,types);
12691         for (i=0; i < (ssize_t) types; i++)
12692         {
12693           (void) CopyMagickString(format,format_list[i]->name,MaxTextExtent);
12694           LocaleLower(format);
12695           PUSHs(sv_2mortal(newSVpv(format,0)));
12696         }
12697         format_list=(const MagickInfo **)
12698           RelinquishMagickMemory((MagickInfo *) format_list);
12699         goto PerlException;
12700       }
12701     EXTEND(sp,8*items);
12702     for (i=1; i < items; i++)
12703     {
12704       name=(char *) SvPV(ST(i),na);
12705       magick_info=GetMagickInfo(name,exception);
12706       if (magick_info == (const MagickInfo *) NULL)
12707         {
12708           PUSHs(&sv_undef);
12709           continue;
12710         }
12711       PUSHs(sv_2mortal(newSViv(magick_info->adjoin)));
12712       PUSHs(sv_2mortal(newSViv(magick_info->blob_support)));
12713       PUSHs(sv_2mortal(newSViv(magick_info->raw)));
12714       PUSHs(sv_2mortal(newSViv((long) magick_info->decoder)));
12715       PUSHs(sv_2mortal(newSViv((long) magick_info->encoder)));
12716       if (magick_info->description == (char *) NULL)
12717         PUSHs(&sv_undef);
12718       else
12719         PUSHs(sv_2mortal(newSVpv(magick_info->description,0)));
12720       if (magick_info->module == (char *) NULL)
12721         PUSHs(&sv_undef);
12722       else
12723         PUSHs(sv_2mortal(newSVpv(magick_info->module,0)));
12724     }
12725
12726   PerlException:
12727     InheritPerlException(exception,perl_exception);
12728     exception=DestroyExceptionInfo(exception);
12729     SvREFCNT_dec(perl_exception);
12730   }
12731 \f
12732 #
12733 ###############################################################################
12734 #                                                                             #
12735 #                                                                             #
12736 #                                                                             #
12737 #   Q u e r y O p t i o n                                                     #
12738 #                                                                             #
12739 #                                                                             #
12740 #                                                                             #
12741 ###############################################################################
12742 #
12743 #
12744 void
12745 QueryOption(ref,...)
12746   Image::Magick ref=NO_INIT
12747   ALIAS:
12748     queryoption = 1
12749   PPCODE:
12750   {
12751     char
12752       **options;
12753
12754     ExceptionInfo
12755       *exception;
12756
12757     register ssize_t
12758       i;
12759
12760     ssize_t
12761       j,
12762       option;
12763
12764     SV
12765       *perl_exception;
12766
12767     PERL_UNUSED_VAR(ref);
12768     PERL_UNUSED_VAR(ix);
12769     exception=AcquireExceptionInfo();
12770     perl_exception=newSVpv("",0);
12771     EXTEND(sp,8*items);
12772     for (i=1; i < items; i++)
12773     {
12774       option=ParseCommandOption(MagickListOptions,MagickFalse,(char *)
12775         SvPV(ST(i),na));
12776       options=GetCommandOptions((CommandOption) option);
12777       if (options == (char **) NULL)
12778         PUSHs(&sv_undef);
12779       else
12780         {
12781           for (j=0; options[j] != (char *) NULL; j++)
12782             PUSHs(sv_2mortal(newSVpv(options[j],0)));
12783           options=DestroyStringList(options);
12784         }
12785     }
12786
12787     InheritPerlException(exception,perl_exception);
12788     exception=DestroyExceptionInfo(exception);
12789     SvREFCNT_dec(perl_exception);
12790   }
12791 \f
12792 #
12793 ###############################################################################
12794 #                                                                             #
12795 #                                                                             #
12796 #                                                                             #
12797 #   R e a d                                                                   #
12798 #                                                                             #
12799 #                                                                             #
12800 #                                                                             #
12801 ###############################################################################
12802 #
12803 #
12804 void
12805 Read(ref,...)
12806   Image::Magick ref=NO_INIT
12807   ALIAS:
12808     ReadImage  = 1
12809     read       = 2
12810     readimage  = 3
12811   PPCODE:
12812   {
12813     AV
12814       *av;
12815
12816     char
12817       **keep,
12818       **list;
12819
12820     ExceptionInfo
12821       *exception;
12822
12823     HV
12824       *hv;
12825
12826     Image
12827       *image;
12828
12829     int
12830       n;
12831
12832     MagickBooleanType
12833       status;
12834
12835     register char
12836       **p;
12837
12838     register ssize_t
12839       i;
12840
12841     ssize_t
12842       ac,
12843       number_images;
12844
12845     STRLEN
12846       *length;
12847
12848     struct PackageInfo
12849       *info,
12850       *package_info;
12851
12852     SV
12853       *perl_exception,  /* Perl variable for storing messages */
12854       *reference,
12855       *rv,
12856       *sv;
12857
12858     PERL_UNUSED_VAR(ref);
12859     PERL_UNUSED_VAR(ix);
12860     exception=AcquireExceptionInfo();
12861     perl_exception=newSVpv("",0);
12862     sv=NULL;
12863     package_info=(struct PackageInfo *) NULL;
12864     number_images=0;
12865     ac=(items < 2) ? 1 : items-1;
12866     list=(char **) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*list));
12867     keep=list;
12868     length=(STRLEN *) NULL;
12869     if (list == (char **) NULL)
12870       {
12871         ThrowPerlException(exception,ResourceLimitError,
12872           "MemoryAllocationFailed",PackageName);
12873         goto PerlException;
12874       }
12875     length=(STRLEN *) AcquireQuantumMemory((size_t) ac+1UL,sizeof(*length));
12876     if (length == (STRLEN *) NULL)
12877       {
12878         ThrowPerlException(exception,ResourceLimitError,
12879           "MemoryAllocationFailed",PackageName);
12880         goto PerlException;
12881       }
12882     if (sv_isobject(ST(0)) == 0)
12883       {
12884         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12885           PackageName);
12886         goto PerlException;
12887       }
12888     reference=SvRV(ST(0));
12889     hv=SvSTASH(reference);
12890     if (SvTYPE(reference) != SVt_PVAV)
12891       {
12892         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
12893           PackageName);
12894         goto PerlException;
12895       }
12896     av=(AV *) reference;
12897     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
12898       exception);
12899     package_info=ClonePackageInfo(info,exception);
12900     n=1;
12901     if (items <= 1)
12902       *list=(char *) (*package_info->image_info->filename ?
12903         package_info->image_info->filename : "XC:black");
12904     else
12905       for (n=0, i=0; i < ac; i++)
12906       {
12907         list[n]=(char *) SvPV(ST(i+1),length[n]);
12908         if ((items >= 3) && strEQcase(list[n],"blob"))
12909           {
12910             void
12911               *blob;
12912
12913             i++;
12914             blob=(void *) (SvPV(ST(i+1),length[n]));
12915             SetImageInfoBlob(package_info->image_info,blob,(size_t) length[n]);
12916           }
12917         if ((items >= 3) && strEQcase(list[n],"filename"))
12918           continue;
12919         if ((items >= 3) && strEQcase(list[n],"file"))
12920           {
12921             FILE
12922               *file;
12923
12924             PerlIO
12925               *io_info;
12926
12927             i++;
12928             io_info=IoIFP(sv_2io(ST(i+1)));
12929             if (io_info == (PerlIO *) NULL)
12930               {
12931                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12932                   PackageName);
12933                 continue;
12934               }
12935             file=PerlIO_findFILE(io_info);
12936             if (file == (FILE *) NULL)
12937               {
12938                 ThrowPerlException(exception,BlobError,"UnableToOpenFile",
12939                   PackageName);
12940                 continue;
12941               }
12942             SetImageInfoFile(package_info->image_info,file);
12943           }
12944         if ((items >= 3) && strEQcase(list[n],"magick"))
12945           continue;
12946         n++;
12947       }
12948     list[n]=(char *) NULL;
12949     keep=list;
12950     status=ExpandFilenames(&n,&list);
12951     if (status == MagickFalse)
12952       {
12953         ThrowPerlException(exception,ResourceLimitError,
12954           "MemoryAllocationFailed",PackageName);
12955         goto PerlException;
12956       }
12957     number_images=0;
12958     for (i=0; i < n; i++)
12959     {
12960       if ((package_info->image_info->file != (FILE *) NULL) ||
12961           (package_info->image_info->blob != (void *) NULL))
12962         {
12963           image=ReadImages(package_info->image_info,exception);
12964           if (image != (Image *) NULL)
12965             DisassociateImageStream(image);
12966         }
12967       else
12968         {
12969           (void) CopyMagickString(package_info->image_info->filename,list[i],
12970             MaxTextExtent);
12971           image=ReadImages(package_info->image_info,exception);
12972         }
12973       if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
12974         break;
12975       for ( ; image; image=image->next)
12976       {
12977         AddImageToRegistry(sv,image);
12978         rv=newRV(sv);
12979         av_push(av,sv_bless(rv,hv));
12980         SvREFCNT_dec(sv);
12981         number_images++;
12982       }
12983     }
12984     /*
12985       Free resources.
12986     */
12987     for (i=0; i < n; i++)
12988       if (list[i] != (char *) NULL)
12989         for (p=keep; list[i] != *p++; )
12990           if (*p == (char *) NULL)
12991             {
12992               list[i]=(char *) RelinquishMagickMemory(list[i]);
12993               break;
12994             }
12995
12996   PerlException:
12997     if (package_info != (struct PackageInfo *) NULL)
12998       DestroyPackageInfo(package_info);
12999     if (list && (list != keep))
13000       list=(char **) RelinquishMagickMemory(list);
13001     if (keep)
13002       keep=(char **) RelinquishMagickMemory(keep);
13003     if (length)
13004       length=(STRLEN *) RelinquishMagickMemory(length);
13005     InheritPerlException(exception,perl_exception);
13006     exception=DestroyExceptionInfo(exception);
13007     sv_setiv(perl_exception,(IV) number_images);
13008     SvPOK_on(perl_exception);
13009     ST(0)=sv_2mortal(perl_exception);
13010     XSRETURN(1);
13011   }
13012 \f
13013 #
13014 ###############################################################################
13015 #                                                                             #
13016 #                                                                             #
13017 #                                                                             #
13018 #   R e m o t e                                                               #
13019 #                                                                             #
13020 #                                                                             #
13021 #                                                                             #
13022 ###############################################################################
13023 #
13024 #
13025 void
13026 Remote(ref,...)
13027   Image::Magick ref=NO_INIT
13028   ALIAS:
13029     RemoteCommand  = 1
13030     remote         = 2
13031     remoteCommand  = 3
13032   PPCODE:
13033   {
13034     AV
13035       *av;
13036
13037     ExceptionInfo
13038       *exception;
13039
13040     register ssize_t
13041       i;
13042
13043     SV
13044       *perl_exception,
13045       *reference;
13046
13047     struct PackageInfo
13048       *info;
13049
13050     PERL_UNUSED_VAR(ref);
13051     PERL_UNUSED_VAR(ix);
13052     exception=AcquireExceptionInfo();
13053     perl_exception=newSVpv("",0);
13054     reference=SvRV(ST(0));
13055     av=(AV *) reference;
13056     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13057       exception);
13058     for (i=1; i < items; i++)
13059       (void) RemoteDisplayCommand(info->image_info,(char *) NULL,(char *)
13060         SvPV(ST(i),na),exception);
13061     InheritPerlException(exception,perl_exception);
13062     exception=DestroyExceptionInfo(exception);
13063     SvREFCNT_dec(perl_exception);    /* throw away all errors */
13064   }
13065 \f
13066 #
13067 ###############################################################################
13068 #                                                                             #
13069 #                                                                             #
13070 #                                                                             #
13071 #   S e t                                                                     #
13072 #                                                                             #
13073 #                                                                             #
13074 #                                                                             #
13075 ###############################################################################
13076 #
13077 #
13078 void
13079 Set(ref,...)
13080   Image::Magick ref=NO_INIT
13081   ALIAS:
13082     SetAttributes  = 1
13083     SetAttribute   = 2
13084     set            = 3
13085     setattributes  = 4
13086     setattribute   = 5
13087   PPCODE:
13088   {
13089     ExceptionInfo
13090       *exception;
13091
13092     Image
13093       *image;
13094
13095     register ssize_t
13096       i;
13097
13098     struct PackageInfo
13099       *info;
13100
13101     SV
13102       *perl_exception,
13103       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13104
13105     PERL_UNUSED_VAR(ref);
13106     PERL_UNUSED_VAR(ix);
13107     exception=AcquireExceptionInfo();
13108     perl_exception=newSVpv("",0);
13109     if (sv_isobject(ST(0)) == 0)
13110       {
13111         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13112           PackageName);
13113         goto PerlException;
13114       }
13115     reference=SvRV(ST(0));
13116     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13117     if (items == 2)
13118       SetAttribute(aTHX_ info,image,"size",ST(1),exception);
13119     else
13120       for (i=2; i < items; i+=2)
13121         SetAttribute(aTHX_ info,image,SvPV(ST(i-1),na),ST(i),exception);
13122
13123   PerlException:
13124     InheritPerlException(exception,perl_exception);
13125     exception=DestroyExceptionInfo(exception);
13126     sv_setiv(perl_exception,(IV) (SvCUR(perl_exception) != 0));
13127     SvPOK_on(perl_exception);
13128     ST(0)=sv_2mortal(perl_exception);
13129     XSRETURN(1);
13130   }
13131 \f
13132 #
13133 ###############################################################################
13134 #                                                                             #
13135 #                                                                             #
13136 #                                                                             #
13137 #   S e t P i x e l                                                           #
13138 #                                                                             #
13139 #                                                                             #
13140 #                                                                             #
13141 ###############################################################################
13142 #
13143 #
13144 void
13145 SetPixel(ref,...)
13146   Image::Magick ref=NO_INIT
13147   ALIAS:
13148     setpixel = 1
13149     setPixel = 2
13150   PPCODE:
13151   {
13152     AV
13153       *av;
13154
13155     char
13156       *attribute;
13157
13158     ChannelType
13159       channel;
13160
13161     ExceptionInfo
13162       *exception;
13163
13164     Image
13165       *image;
13166
13167     MagickBooleanType
13168       normalize;
13169
13170     RectangleInfo
13171       region;
13172
13173     register ssize_t
13174       i;
13175
13176     register Quantum
13177       *q;
13178
13179     ssize_t
13180       option;
13181
13182     struct PackageInfo
13183       *info;
13184
13185     SV
13186       *perl_exception,
13187       *reference;  /* reference is the SV* of ref=SvIV(reference) */
13188
13189     PERL_UNUSED_VAR(ref);
13190     PERL_UNUSED_VAR(ix);
13191     exception=AcquireExceptionInfo();
13192     perl_exception=newSVpv("",0);
13193     reference=SvRV(ST(0));
13194     av=(AV *) reference;
13195     info=GetPackageInfo(aTHX_ (void *) av,(struct PackageInfo *) NULL,
13196       exception);
13197     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13198     if (image == (Image *) NULL)
13199       {
13200         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13201           PackageName);
13202         goto PerlException;
13203       }
13204     av=(AV *) NULL;
13205     channel=DefaultChannels;
13206     normalize=MagickTrue;
13207     region.x=0;
13208     region.y=0;
13209     region.width=image->columns;
13210     region.height=1;
13211     if (items == 1)
13212       (void) ParseAbsoluteGeometry(SvPV(ST(1),na),&region);
13213     for (i=2; i < items; i+=2)
13214     {
13215       attribute=(char *) SvPV(ST(i-1),na);
13216       switch (*attribute)
13217       {
13218         case 'C':
13219         case 'c':
13220         {
13221           if (LocaleCompare(attribute,"channel") == 0)
13222             {
13223               ssize_t
13224                 option;
13225
13226               option=ParseChannelOption(SvPV(ST(i),na));
13227               if (option < 0)
13228                 {
13229                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13230                     SvPV(ST(i),na));
13231                   return;
13232                 }
13233                channel=(ChannelType) option;
13234               break;
13235             }
13236           if (LocaleCompare(attribute,"color") == 0)
13237             {
13238               if (SvTYPE(ST(i)) != SVt_RV)
13239                 {
13240                   char
13241                     message[MaxTextExtent];
13242
13243                   (void) FormatLocaleString(message,MaxTextExtent,
13244                     "invalid %.60s value",attribute);
13245                   ThrowPerlException(exception,OptionError,message,
13246                     SvPV(ST(i),na));
13247                 }
13248               av=(AV *) SvRV(ST(i));
13249               break;
13250             }
13251           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13252             attribute);
13253           break;
13254         }
13255         case 'g':
13256         case 'G':
13257         {
13258           if (LocaleCompare(attribute,"geometry") == 0)
13259             {
13260               (void) ParseAbsoluteGeometry(SvPV(ST(i),na),&region);
13261               break;
13262             }
13263           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13264             attribute);
13265           break;
13266         }
13267         case 'N':
13268         case 'n':
13269         {
13270           if (LocaleCompare(attribute,"normalize") == 0)
13271             {
13272               option=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13273                 SvPV(ST(i),na));
13274               if (option < 0)
13275                 {
13276                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13277                     SvPV(ST(i),na));
13278                   break;
13279                 }
13280              normalize=option != 0 ? MagickTrue : MagickFalse;
13281              break;
13282             }
13283           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13284             attribute);
13285           break;
13286         }
13287         case 'x':
13288         case 'X':
13289         {
13290           if (LocaleCompare(attribute,"x") == 0)
13291             {
13292               region.x=SvIV(ST(i));
13293               break;
13294             }
13295           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13296             attribute);
13297           break;
13298         }
13299         case 'y':
13300         case 'Y':
13301         {
13302           if (LocaleCompare(attribute,"y") == 0)
13303             {
13304               region.y=SvIV(ST(i));
13305               break;
13306             }
13307           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13308             attribute);
13309           break;
13310         }
13311         default:
13312         {
13313           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13314             attribute);
13315           break;
13316         }
13317       }
13318     }
13319     (void) SetImageStorageClass(image,DirectClass);
13320     q=GetAuthenticPixels(image,region.x,region.y,1,1,exception);
13321     if ((q == (const Quantum *) NULL) || (av == (AV *) NULL) ||
13322         (SvTYPE(av) != SVt_PVAV))
13323       PUSHs(&sv_undef);
13324     else
13325       {
13326         double
13327           scale;
13328
13329         register ssize_t
13330           i;
13331
13332         i=0;
13333         scale=1.0;
13334         if (normalize != MagickFalse)
13335           scale=QuantumRange;
13336         if (((GetPixelRedTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13337           {
13338             SetPixelRed(image,ClampToQuantum(scale*SvNV(*(
13339               av_fetch(av,i,0)))),q);
13340             i++;
13341           }
13342         if (((GetPixelGreenTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13343           {
13344             SetPixelGreen(image,ClampToQuantum(scale*SvNV(*(
13345               av_fetch(av,i,0)))),q);
13346             i++;
13347           }
13348         if (((GetPixelBlueTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13349           {
13350             SetPixelBlue(image,ClampToQuantum(scale*SvNV(*(
13351               av_fetch(av,i,0)))),q);
13352             i++;
13353           }
13354         if ((((GetPixelBlackTraits(image) & ActivePixelTrait) != 0) &&
13355             (image->colorspace == CMYKColorspace)) && (i <= av_len(av)))
13356           {
13357             SetPixelBlack(image,ClampToQuantum(scale*
13358               SvNV(*(av_fetch(av,i,0)))),q);
13359             i++;
13360           }
13361         if (((GetPixelAlphaTraits(image) & ActivePixelTrait) != 0) && (i <= av_len(av)))
13362           {
13363             SetPixelAlpha(image,ClampToQuantum(scale*
13364               SvNV(*(av_fetch(av,i,0)))),q);
13365             i++;
13366           }
13367         (void) SyncAuthenticPixels(image,exception);
13368       }
13369
13370   PerlException:
13371     InheritPerlException(exception,perl_exception);
13372     exception=DestroyExceptionInfo(exception);
13373     SvREFCNT_dec(perl_exception);
13374   }
13375 \f
13376 #
13377 ###############################################################################
13378 #                                                                             #
13379 #                                                                             #
13380 #                                                                             #
13381 #   S m u s h                                                                 #
13382 #                                                                             #
13383 #                                                                             #
13384 #                                                                             #
13385 ###############################################################################
13386 #
13387 #
13388 void
13389 Smush(ref,...)
13390   Image::Magick ref=NO_INIT
13391   ALIAS:
13392     SmushImage  = 1
13393     smush       = 2
13394     smushimage  = 3
13395   PPCODE:
13396   {
13397     AV
13398       *av;
13399
13400     char
13401       *attribute;
13402
13403     ExceptionInfo
13404       *exception;
13405
13406     HV
13407       *hv;
13408
13409     Image
13410       *image;
13411
13412     register ssize_t
13413       i;
13414
13415     ssize_t
13416       offset,
13417       stack;
13418
13419     struct PackageInfo
13420       *info;
13421
13422     SV
13423       *av_reference,
13424       *perl_exception,
13425       *reference,
13426       *rv,
13427       *sv;
13428
13429     PERL_UNUSED_VAR(ref);
13430     PERL_UNUSED_VAR(ix);
13431     exception=AcquireExceptionInfo();
13432     perl_exception=newSVpv("",0);
13433     sv=NULL;
13434     attribute=NULL;
13435     av=NULL;
13436     if (sv_isobject(ST(0)) == 0)
13437       {
13438         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13439           PackageName);
13440         goto PerlException;
13441       }
13442     reference=SvRV(ST(0));
13443     hv=SvSTASH(reference);
13444     av=newAV();
13445     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13446     SvREFCNT_dec(av);
13447     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13448     if (image == (Image *) NULL)
13449       {
13450         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13451           PackageName);
13452         goto PerlException;
13453       }
13454     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13455     /*
13456       Get options.
13457     */
13458     offset=0;
13459     stack=MagickTrue;
13460     for (i=2; i < items; i+=2)
13461     {
13462       attribute=(char *) SvPV(ST(i-1),na);
13463       switch (*attribute)
13464       {
13465         case 'O':
13466         case 'o':
13467         {
13468           if (LocaleCompare(attribute,"offset") == 0)
13469             {
13470               offset=(ssize_t) StringToLong((char *) SvPV(ST(1),na));
13471               break;
13472             }
13473           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13474             attribute);
13475           break;
13476         }
13477         case 'S':
13478         case 's':
13479         {
13480           if (LocaleCompare(attribute,"stack") == 0)
13481             {
13482               stack=ParseCommandOption(MagickBooleanOptions,MagickFalse,
13483                 SvPV(ST(i),na));
13484               if (stack < 0)
13485                 {
13486                   ThrowPerlException(exception,OptionError,"UnrecognizedType",
13487                     SvPV(ST(i),na));
13488                   return;
13489                 }
13490               break;
13491             }
13492           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13493             attribute);
13494           break;
13495         }
13496         default:
13497         {
13498           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13499             attribute);
13500           break;
13501         }
13502       }
13503     }
13504     image=SmushImages(image,stack != 0 ? MagickTrue : MagickFalse,offset,
13505       exception);
13506     if ((image == (Image *) NULL) || (exception->severity >= ErrorException))
13507       goto PerlException;
13508     for ( ; image; image=image->next)
13509     {
13510       AddImageToRegistry(sv,image);
13511       rv=newRV(sv);
13512       av_push(av,sv_bless(rv,hv));
13513       SvREFCNT_dec(sv);
13514     }
13515     exception=DestroyExceptionInfo(exception);
13516     ST(0)=av_reference;
13517     SvREFCNT_dec(perl_exception);
13518     XSRETURN(1);
13519
13520   PerlException:
13521     InheritPerlException(exception,perl_exception);
13522     exception=DestroyExceptionInfo(exception);
13523     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13524     SvPOK_on(perl_exception);
13525     ST(0)=sv_2mortal(perl_exception);
13526     XSRETURN(1);
13527   }
13528 \f
13529 #
13530 ###############################################################################
13531 #                                                                             #
13532 #                                                                             #
13533 #                                                                             #
13534 #   S t a t i s t i c s                                                       #
13535 #                                                                             #
13536 #                                                                             #
13537 #                                                                             #
13538 ###############################################################################
13539 #
13540 #
13541 void
13542 Statistics(ref,...)
13543   Image::Magick ref=NO_INIT
13544   ALIAS:
13545     StatisticsImage = 1
13546     statistics      = 2
13547     statisticsimage = 3
13548   PPCODE:
13549   {
13550 #define ChannelStatistics(channel) \
13551 { \
13552   (void) FormatLocaleString(message,MaxTextExtent,"%.20g", \
13553     (double) channel_statistics[channel].depth); \
13554   PUSHs(sv_2mortal(newSVpv(message,0))); \
13555   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13556     channel_statistics[channel].minima/scale); \
13557   PUSHs(sv_2mortal(newSVpv(message,0))); \
13558   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13559     channel_statistics[channel].maxima/scale); \
13560   PUSHs(sv_2mortal(newSVpv(message,0))); \
13561   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13562     channel_statistics[channel].mean/scale); \
13563   PUSHs(sv_2mortal(newSVpv(message,0))); \
13564   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13565     channel_statistics[channel].standard_deviation/scale); \
13566   PUSHs(sv_2mortal(newSVpv(message,0))); \
13567   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13568     channel_statistics[channel].kurtosis); \
13569   PUSHs(sv_2mortal(newSVpv(message,0))); \
13570   (void) FormatLocaleString(message,MaxTextExtent,"%.15g", \
13571     channel_statistics[channel].skewness); \
13572   PUSHs(sv_2mortal(newSVpv(message,0))); \
13573 }
13574
13575     AV
13576       *av;
13577
13578     char
13579       message[MaxTextExtent];
13580
13581     ChannelStatistics
13582       *channel_statistics;
13583
13584     double
13585       scale;
13586
13587     ExceptionInfo
13588       *exception;
13589
13590     Image
13591       *image;
13592
13593     ssize_t
13594       count;
13595
13596     struct PackageInfo
13597       *info;
13598
13599     SV
13600       *perl_exception,
13601       *reference;
13602
13603     PERL_UNUSED_VAR(ref);
13604     PERL_UNUSED_VAR(ix);
13605     exception=AcquireExceptionInfo();
13606     perl_exception=newSVpv("",0);
13607     av=NULL;
13608     if (sv_isobject(ST(0)) == 0)
13609       {
13610         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13611           PackageName);
13612         goto PerlException;
13613       }
13614     reference=SvRV(ST(0));
13615     av=newAV();
13616     SvREFCNT_dec(av);
13617     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13618     if (image == (Image *) NULL)
13619       {
13620         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13621           PackageName);
13622         goto PerlException;
13623       }
13624     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13625     count=0;
13626     for ( ; image; image=image->next)
13627     {
13628       channel_statistics=GetImageChannelStatistics(image,&image->exception);
13629       if (channel_statistics == (ChannelStatistics *) NULL)
13630         continue;
13631       count++;
13632       EXTEND(sp,35*count);
13633       scale=(double) QuantumRange;
13634       ChannelStatistics(RedChannel);
13635       ChannelStatistics(GreenChannel);
13636       ChannelStatistics(BlueChannel);
13637       if (image->colorspace == CMYKColorspace)
13638         ChannelStatistics(BlackChannel);
13639       if (image->matte != MagickFalse)
13640         ChannelStatistics(AlphaChannel);
13641       channel_statistics=(ChannelStatistics *)
13642         RelinquishMagickMemory(channel_statistics);
13643     }
13644
13645   PerlException:
13646     InheritPerlException(exception,perl_exception);
13647     exception=DestroyExceptionInfo(exception);
13648     SvREFCNT_dec(perl_exception);
13649   }
13650 \f
13651 #
13652 ###############################################################################
13653 #                                                                             #
13654 #                                                                             #
13655 #                                                                             #
13656 #   S y n c A u t h e n t i c P i x e l s                                     #
13657 #                                                                             #
13658 #                                                                             #
13659 #                                                                             #
13660 ###############################################################################
13661 #
13662 #
13663 void
13664 SyncAuthenticPixels(ref,...)
13665   Image::Magick ref = NO_INIT
13666   ALIAS:
13667     Syncauthenticpixels = 1
13668     SyncImagePixels = 2
13669     syncimagepixels = 3
13670   CODE:
13671   {
13672     ExceptionInfo
13673       *exception;
13674
13675     Image
13676       *image;
13677
13678     MagickBooleanType
13679       status;
13680
13681     struct PackageInfo
13682       *info;
13683
13684     SV
13685       *perl_exception,
13686       *reference;
13687
13688     PERL_UNUSED_VAR(ref);
13689     PERL_UNUSED_VAR(ix);
13690     exception=AcquireExceptionInfo();
13691     perl_exception=newSVpv("",0);
13692     if (sv_isobject(ST(0)) == 0)
13693       {
13694         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13695           PackageName);
13696         goto PerlException;
13697       }
13698
13699     reference=SvRV(ST(0));
13700     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13701     if (image == (Image *) NULL)
13702       {
13703         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13704           PackageName);
13705         goto PerlException;
13706       }
13707
13708     status=SyncAuthenticPixels(image,exception);
13709     if (status != MagickFalse)
13710       return;
13711     InheritException(exception,&image->exception);
13712
13713   PerlException:
13714     InheritPerlException(exception,perl_exception);
13715     exception=DestroyExceptionInfo(exception);
13716     SvREFCNT_dec(perl_exception);  /* throw away all errors */
13717   }
13718 \f
13719 #
13720 ###############################################################################
13721 #                                                                             #
13722 #                                                                             #
13723 #                                                                             #
13724 #   T r a n s f o r m                                                         #
13725 #                                                                             #
13726 #                                                                             #
13727 #                                                                             #
13728 ###############################################################################
13729 #
13730 #
13731 void
13732 Transform(ref,...)
13733   Image::Magick ref=NO_INIT
13734   ALIAS:
13735     TransformImage = 1
13736     transform      = 2
13737     transformimage = 3
13738   PPCODE:
13739   {
13740     AV
13741       *av;
13742
13743     char
13744       *attribute,
13745       *crop_geometry,
13746       *geometry;
13747
13748     ExceptionInfo
13749       *exception;
13750
13751     HV
13752       *hv;
13753
13754     Image
13755       *clone,
13756       *image;
13757
13758     register ssize_t
13759       i;
13760
13761     struct PackageInfo
13762       *info;
13763
13764     SV
13765       *av_reference,
13766       *perl_exception,
13767       *reference,
13768       *rv,
13769       *sv;
13770
13771     PERL_UNUSED_VAR(ref);
13772     PERL_UNUSED_VAR(ix);
13773     exception=AcquireExceptionInfo();
13774     perl_exception=newSVpv("",0);
13775     sv=NULL;
13776     av=NULL;
13777     attribute=NULL;
13778     if (sv_isobject(ST(0)) == 0)
13779       {
13780         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13781           PackageName);
13782         goto PerlException;
13783       }
13784     reference=SvRV(ST(0));
13785     hv=SvSTASH(reference);
13786     av=newAV();
13787     av_reference=sv_2mortal(sv_bless(newRV((SV *) av),hv));
13788     SvREFCNT_dec(av);
13789     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13790     if (image == (Image *) NULL)
13791       {
13792         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13793           PackageName);
13794         goto PerlException;
13795       }
13796     info=GetPackageInfo(aTHX_ (void *) av,info,exception);
13797     /*
13798       Get attribute.
13799     */
13800     crop_geometry=(char *) NULL;
13801     geometry=(char *) NULL;
13802     for (i=2; i < items; i+=2)
13803     {
13804       attribute=(char *) SvPV(ST(i-1),na);
13805       switch (*attribute)
13806       {
13807         case 'c':
13808         case 'C':
13809         {
13810           if (LocaleCompare(attribute,"crop") == 0)
13811             {
13812               crop_geometry=SvPV(ST(i),na);
13813               break;
13814             }
13815           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13816             attribute);
13817           break;
13818         }
13819         case 'g':
13820         case 'G':
13821         {
13822           if (LocaleCompare(attribute,"geometry") == 0)
13823             {
13824               geometry=SvPV(ST(i),na);
13825               break;
13826             }
13827          if (LocaleCompare(attribute,"gravity") == 0)
13828            {
13829              Image
13830                *next;
13831
13832              ssize_t
13833                in;
13834
13835              in=!SvPOK(ST(i)) ? SvIV(ST(i)) : ParseCommandOption(
13836                MagickGravityOptions,MagickFalse,SvPV(ST(i),na));
13837              if (in < 0)
13838                {
13839                  ThrowPerlException(exception,OptionError,"UnrecognizedType",
13840                    SvPV(ST(i),na));
13841                  return;
13842                }
13843              for (next=image; next; next=next->next)
13844                next->gravity=(GravityType) in;
13845              break;
13846            }
13847           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13848             attribute);
13849           break;
13850         }
13851         default:
13852         {
13853           ThrowPerlException(exception,OptionError,"UnrecognizedAttribute",
13854             attribute);
13855           break;
13856         }
13857       }
13858     }
13859     for ( ; image; image=image->next)
13860     {
13861       clone=CloneImage(image,0,0,MagickTrue,exception);
13862       if ((clone == (Image *) NULL) || (exception->severity >= ErrorException))
13863         goto PerlException;
13864       TransformImage(&clone,crop_geometry,geometry);
13865       for ( ; clone; clone=clone->next)
13866       {
13867         AddImageToRegistry(sv,clone);
13868         rv=newRV(sv);
13869         av_push(av,sv_bless(rv,hv));
13870         SvREFCNT_dec(sv);
13871       }
13872     }
13873     exception=DestroyExceptionInfo(exception);
13874     ST(0)=av_reference;
13875     SvREFCNT_dec(perl_exception);  /* can't return warning messages */
13876     XSRETURN(1);
13877
13878   PerlException:
13879     InheritPerlException(exception,perl_exception);
13880     exception=DestroyExceptionInfo(exception);
13881     sv_setiv(perl_exception,(IV) SvCUR(perl_exception) != 0);
13882     SvPOK_on(perl_exception);
13883     ST(0)=sv_2mortal(perl_exception);
13884     XSRETURN(1);
13885   }
13886 \f
13887 #
13888 ###############################################################################
13889 #                                                                             #
13890 #                                                                             #
13891 #                                                                             #
13892 #   W r i t e                                                                 #
13893 #                                                                             #
13894 #                                                                             #
13895 #                                                                             #
13896 ###############################################################################
13897 #
13898 #
13899 void
13900 Write(ref,...)
13901   Image::Magick ref=NO_INIT
13902   ALIAS:
13903     WriteImage    = 1
13904     write         = 2
13905     writeimage    = 3
13906   PPCODE:
13907   {
13908     char
13909       filename[MaxTextExtent];
13910
13911     ExceptionInfo
13912       *exception;
13913
13914     Image
13915       *image,
13916       *next;
13917
13918     register ssize_t
13919       i;
13920
13921     ssize_t
13922       number_images,
13923       scene;
13924
13925     struct PackageInfo
13926       *info,
13927       *package_info;
13928
13929     SV
13930       *perl_exception,
13931       *reference;
13932
13933     PERL_UNUSED_VAR(ref);
13934     PERL_UNUSED_VAR(ix);
13935     exception=AcquireExceptionInfo();
13936     perl_exception=newSVpv("",0);
13937     number_images=0;
13938     package_info=(struct PackageInfo *) NULL;
13939     if (sv_isobject(ST(0)) == 0)
13940       {
13941         ThrowPerlException(exception,OptionError,"ReferenceIsNotMyType",
13942           PackageName);
13943         goto PerlException;
13944       }
13945     reference=SvRV(ST(0));
13946     image=SetupList(aTHX_ reference,&info,(SV ***) NULL,exception);
13947     if (image == (Image *) NULL)
13948       {
13949         ThrowPerlException(exception,OptionError,"NoImagesDefined",
13950           PackageName);
13951         goto PerlException;
13952       }
13953     package_info=ClonePackageInfo(info,exception);
13954     if (items == 2)
13955       SetAttribute(aTHX_ package_info,NULL,"filename",ST(1),exception);
13956     else
13957       if (items > 2)
13958         for (i=2; i < items; i+=2)
13959           SetAttribute(aTHX_ package_info,image,SvPV(ST(i-1),na),ST(i),
13960             exception);
13961     (void) CopyMagickString(filename,package_info->image_info->filename,
13962       MaxTextExtent);
13963     scene=0;
13964     for (next=image; next; next=next->next)
13965     {
13966       (void) CopyMagickString(next->filename,filename,MaxTextExtent);
13967       next->scene=scene++;
13968     }
13969     SetImageInfo(package_info->image_info,(unsigned int)
13970       GetImageListLength(image),&image->exception);
13971     for (next=image; next; next=next->next)
13972     {
13973       (void) WriteImage(package_info->image_info,next);
13974       if (next->exception.severity >= ErrorException)
13975         InheritException(exception,&next->exception);
13976       GetImageException(next,exception);
13977       number_images++;
13978       if (package_info->image_info->adjoin)
13979         break;
13980     }
13981
13982   PerlException:
13983     if (package_info != (struct PackageInfo *) NULL)
13984       DestroyPackageInfo(package_info);
13985     InheritPerlException(exception,perl_exception);
13986     exception=DestroyExceptionInfo(exception);
13987     sv_setiv(perl_exception,(IV) number_images);
13988     SvPOK_on(perl_exception);
13989     ST(0)=sv_2mortal(perl_exception);
13990     XSRETURN(1);
13991   }